ℹ️ IndieAuth

IndieAuth

Micro.blog supports IndieAuth, an OAuth-based way to sign in and authorize apps. Your app is identified by a URL, not a separately issued client ID or secret.

Authorizing your app

For an app that works across blogging platforms, ask for the user’s blog URL, then discover these links on their home page:

<link rel="authorization_endpoint" href="https://micro.blog/indieauth/auth" />
<link rel="token_endpoint" href="https://micro.blog/indieauth/token" />

Micro.blog-specific apps can use those endpoints directly and omit me; Micro.blog will use the user’s default blog.

Open the authorization endpoint in the user’s browser with these query parameters:

  • client_id: Your app’s home page or client metadata URL, such as https://app.example/client.json.
  • redirect_uri: Your callback URL, such as https://app.example/callback.
  • response_type: code.
  • scope: Space-separated permissions, such as read write; see below.
  • state: An unpredictable value tied to this sign-in attempt.
  • me: The user’s blog URL, if supplied.

Encode each value once. Use the system browser so the user can reuse their website sign-in; an API token cannot authorize another app.

After approval, your callback receives code and state. Verify the saved state before exchanging the code, which expires after 60 seconds and can only be used once.

Getting an access token

Send a form-encoded POST to the token endpoint:

curl https://micro.blog/indieauth/token \
  -H 'Accept: application/json' \
  --data-urlencode 'grant_type=authorization_code' \
  --data-urlencode 'code=CODE_FROM_CALLBACK' \
  --data-urlencode 'client_id=https://app.example/client.json' \
  --data-urlencode 'redirect_uri=https://app.example/callback'

Both client_id and redirect_uri must be identical to the values used for authorization, including trailing slashes. No client_secret is required. An expired, reused, or mismatched code returns invalid_grant; start a new authorization attempt.

The JSON response includes access_token, token_type, scope, me, and profile. Use profile.name, profile.photo, and profile.nickname (the username) instead of account-management endpoints for basic profile details.

Check the returned scope, which may be narrower than requested. Store the token securely and send it in the Authorization header. For example, with read write:

GET /posts/timeline HTTP/1.1
Host: micro.blog
Authorization: Bearer YOUR_ACCESS_TOKEN

Scopes

Request only the permissions your app needs. These are Micro.blog’s supported public scopes:

Scope Access
read Read timelines and content, including reader-state actions such as marking items read.
write Read and manage content, including creating, editing, deleting, and uploading media.
create Create content, including posts, bookmarks, notes, notebooks, and media uploads. No general read, edit, or delete access.
update Edit posts and retrieve Micropub post source for editing.
delete Delete posts.
media Upload files without permission to publish posts.
profile Sign-in and profile information. By itself, this does not issue an API access token.
follow, channels Manage follows or channels through Microsub, which requires these scopes separately from write.

Micro.blog-specific clients that read and post usually request read write; read-only clients need just read. Micropub-only apps should request the operations they support, such as create update delete media for a full editor or create for creating content without editing or deleting it. Micro.blog includes uploads with create; requesting media explicitly can help with other servers. See the IndieWeb scope conventions.

The Micro.blog-specific follow and feed-subscription APIs accept either write or follow, including subscription changes under /feeds/v2/subscriptions and OPML import at /account/inkwell/opml. Microsub clients must request follow for following/unfollowing and channels for channel management; write does not substitute for either. Creating private bookmarks through /posts/favorites, /posts/bookmarks, or Micropub’s bookmark-of is included in create.

write remains supported for Micropub, and combining it with create is harmless but redundant. Older tokens may retain broader permissions for compatibility, so test with a newly authorized token too. Do not assume create permits timeline reading. Micropub q=source requires read or update, and listing existing media requires read.

The account scope is reserved for trusted Micro.blog sign-in flows, not IndieAuth clients. Unsupported scopes, including openid and email, are rejected. Empty or profile-only grants return identity information without an access token. For scope-related HTTP 403 errors, request the necessary public scopes through a new authorization. Users can revoke tokens, so support signing in again.

Callback URLs and client metadata

Without registered callbacks, a web callback must share the client’s scheme, hostname, and port. Native URL schemes and callbacks on another origin must be registered in metadata served at your publicly accessible client_id URL:

{
  "client_id": "https://app.example/client.json",
  "client_name": "Example App",
  "logo_uri": "https://app.example/logo.png",
  "redirect_uris": [
    "https://app.example/callback",
    "exampleapp://callback"
  ]
}

When redirect_uris is present, only exact listed callbacks are accepted, even for the same origin. Include any fixed query parameters and trailing slashes; fragments are not allowed. If metadata includes client_id, it must identify the URL requested. HTML or HTTP Link registration with rel="redirect_uri" is also supported.

For API requests, see the JSON API documentation and Micropub specification.

1 Like