Get your API key
API reference

Account linking

The Account linking endpoints.

Auth: Public · Base URL: https://api.mailkite.dev

Endpoints

Each row expands to its request and response schema. The address bar follows along, so any endpoint can be linked to directly.

GET /.well-known/oauth-authorization-server Discovery document for MailKite's authorization server (RFC 8414). Read the authorize/token/register endpoints from here instead of hard-coding them. Also served at /.well-known/openid-configuration.

Discovery document for MailKite's authorization server (RFC 8414). Read the authorize/token/register endpoints from here instead of hard-coding them. Also served at /.well-known/openid-configuration.

Response body

oauth-metadata-response.json

GET /.well-known/oauth-authorization-server — RFC 8414 discovery document for MailKite's authorization server. Read the endpoints from here rather than hard-coding them. Also served at /.well-known/openid-configuration for clients that probe OIDC discovery.

FieldTypeNotes
issuer req stringThe authorization server's origin.
authorization_endpoint req stringWhere to send the user's browser to sign in and consent.
token_endpoint req stringWhere to exchange the authorization code (or a refresh token) for an access token.
registration_endpoint req stringRFC 7591 dynamic client registration — no pre-shared client secret needed.
revocation_endpointstringRFC 7009 token revocation.
scopes_supported req string[]Scopes this server issues. A single scope today — the token it returns acts on the whole account, so exchange it once for an API key and discard it rather than storing it long-term.
response_types_supported req string[]Authorization-code flow only.
grant_types_supported req string[]Grants accepted at the token endpoint.
code_challenge_methods_supported req string[]PKCE is mandatory, S256 only — a plain challenge is rejected.
token_endpoint_auth_methods_supported req string[]`none` — clients are public and authenticate with PKCE, not a secret.
POST /oauth/register Register an OAuth client for this installation (RFC 7591 dynamic client registration) — step 1 of linking an existing MailKite account to your app. No pre-shared secret and no manual app review: you get a client_id back immediately and prove yourself with PKCE. Register once per install and keep the client_id.

Register an OAuth client for this installation (RFC 7591 dynamic client registration) — step 1 of linking an existing MailKite account to your app. No pre-shared secret and no manual app review: you get a client_id back immediately and prove yourself with PKCE. Register once per install and keep the client_id.

Request body

oauth-client-request.json

POST /oauth/register — RFC 7591 dynamic client registration. Register once per installation (a plugin registers itself per site) and keep the returned client_id; there is no secret to store.

FieldTypeNotes
redirect_uris req string[]Where the authorization code is delivered. Every entry must be an absolute https URL — http is accepted only on loopback, for local development. A javascript: or data: URI is rejected.
client_namestringHuman-readable name shown to the user on the consent screen. Include the site or install it belongs to so someone with several connections can tell them apart.

Response body

oauth-client-response.json

POST /oauth/register — the registered client. Public client: there is no client_secret, and PKCE takes its place.

FieldTypeNotes
client_id req stringPass this to /oauth/authorize and /oauth/token.
client_id_issued_at req integerUnix seconds when the client was registered.
client_namestringEchoed back when supplied.
redirect_uris req string[]The registered redirect URIs. The one passed to /oauth/authorize must match an entry exactly.
grant_types req string[]
response_types req string[]
token_endpoint_auth_method req stringAlways `none` — the client is public and proves itself with PKCE.
POST /oauth/token Exchange an authorization code for an access token (or rotate a refresh token) — step 3 of linking. Between steps you send the user's browser to /oauth/authorize with your client_id, redirect_uri, state, and an S256 code_challenge; they sign in with whatever method they already use and approve, and the code comes back to your redirect_uri. Then call getApiKey with the access token and store the key.

Exchange an authorization code for an access token (or rotate a refresh token) — step 3 of linking. Between steps you send the user's browser to /oauth/authorize with your client_id, redirect_uri, state, and an S256 code_challenge; they sign in with whatever method they already use and approve, and the code comes back to your redirect_uri. Then call getApiKey with the access token and store the key.

Request body

oauth-token-request.json

POST /oauth/token — exchange an authorization code for tokens, or rotate a refresh token. Accepts application/x-www-form-urlencoded (the OAuth norm) or application/json. Which fields are required depends on grant_type.

FieldTypeNotes
grant_type req "authorization_code" · "refresh_token"Which exchange to perform.
codestringauthorization_code grant: the single-use code from the redirect. Expires quickly and is consumed on first use — a replay returns invalid_grant.
redirect_uristringauthorization_code grant: must match the redirect_uri used at /oauth/authorize exactly.
client_idstringauthorization_code grant: required. refresh_token grant: optional, but checked against the token's client when supplied.
code_verifierstringauthorization_code grant: the PKCE verifier whose S256 hash you sent as code_challenge. Required — there is no non-PKCE path.
refresh_tokenstringrefresh_token grant: the token to rotate. Single-use — the old one is revoked and a new one returned alongside the access token.

Response body

oauth-token-response.json

POST /oauth/token — an access token for the linked account. To finish linking, call getApiKey with this access token as the Bearer credential and store the API key it returns; then you can discard the OAuth tokens.

FieldTypeNotes
access_token req stringBearer credential for the account that authorized you. Short-lived — see expires_in.
token_type req stringAlways `Bearer`.
expires_in req integerAccess-token lifetime in seconds.
refresh_token req stringSingle-use refresh token. Rotating it revokes this one and issues a replacement.
scope req stringThe granted scope. Account-wide today, which is why the recommended pattern is to exchange it for an API key immediately rather than keeping it.