Fastmail can authorize third-party clients to access a user’s data using OAuth 2.0, in conformance with the Authorization Code grant flow of the OAuth 2.0 Authorization Framework, as defined in RFC 6749.


Clients are currently registered manually by contact with Fastmail developers. Want to get started with OAuth? Check out our partnerships page and get in touch!

We’ll need the following information to register your client, but we can update this later, so don’t worry if you’re starting something new and don’t have everything to hand yet — we’d still love to hear from you.

Please provide the following values:

  • clientName: The human-readable name of the client to be presented to the end-user during authorization.
  • logoUrl: The URL for a logo to display for this client. This will be rendered in a square shape.
  • clientUrl: The URL of a web page providing information about the client (e.g. the page on the extension store, or GitHub).
  • tosUrl: A URL that points to a human-readable terms of service document for the client.
  • policyUrl: A URL that points to a human-readable privacy policy document for the client.
  • supportUrl: A URL that points to support and/or contact information for the client.
  • redirectUris: A list of redirect URIs the client may use in the OAuth flow. You can register as many as you like. Each redirect URI:
    • MUST be a full URI including path if desired.
    • MAY include query parameters.
    • MUST NOT include a fragment part (#).
    • MUST NOT include path traversal ([\/]..).
    • MUST start with one of:
      • An https domain owned by the client developer, e.g. https://example.com/ (This is referred to as a “claimed https URI” in OAuth docs.)
      • A private-use URI scheme in reverse domain notation, e.g. com.example:/. Such a scheme MUST have at least one dot in it. It SHOULD be formed from a domain owned by the client developer.
      • http://localhost/ – the loopback URL. During authorization, an arbitrary port may be given by the client, and localhost may be replaced by either or ::1.
  • clientOrigins: A list of origins the client may use to make CORS requests to the token endpoint and JMAP API.

We will assign a client id for the registration and send it back to you.

If the client supports OAuth with multiple authorization servers (e.g. it adds support for another email service) it MUST NOT reuse the same redirect_uri with different registrations. (For example, it should add a per-service path component.) This allows it to detect and prevent server mix-up attacks (see the state parameter below).


Clients initiate authorization by opening the user’s web browser at the Fastmail OAuth Authorization URL:


The following URL parameters MUST be present:

  • client_id: The client id for the application, given to the developer when your application is registered.
  • redirect_uri: One of the redirect uris previously registered with Fastmail. This MUST be identical to the registered URI. The one exception to this is if a URI with the prefix “http://localhost/” was registered, in which case the matching URI MUST also include an arbitrary port and MAY use or ::1 instead of localhost.

For example, if http://localhost/redirect was registered, then the client could send as the redirect_uri for authorization.

  • response_type: This MUST be “code”. No other value is accepted at this time.
  • scope: A space delimited set of scopes the client would like access to. This MUST be a subset of the scopes registered for the client.
  • code_challenge: A PKCE code challenge as per RFC 7636, using SHA-256. To generate a challenge, first generate a code_verifier: a high-entropy cryptographic random STRING using the unreserved characters [A-Z] / [a-z] / [0-9] / "-" / "." / "*" / "~" from Section 2.3 of RFC 3986, with a minimum length of 43 characters and a maximum length of 128 characters. The code_challenge is then BASE64URL-ENCODE(SHA256(ASCII(code_verifier))).
  • code_challenge_method: The only accepted value at this time is “S256”.
  • state: An opaque value used by the client to verify that an authorization response is due to a request that the client initiated. The Fastmail server will include this value when redirecting the user-agent back to the client. Clients MUST generate a state with a unique, unguessable random string when initiating an authorization request. When a response is received, the client MUST:
    • Verify that the state returned matches exactly the state it sent, to verify that this request was indeed initiated by the client and not an attacker.
    • Verify that the redirect URI the authorization response came in on was the one they used when generating the request. This prevents Mix-Up Attacks when the client supports more than one authorization server.

Other URL parameters MAY be supplied but will be ignored.

Fastmail will authenticate the user and ask them if they wish to grant authorization to the client. If successful, the client will receive a response via the redirect_uri, which will include the following query parameters:

  • code: The authorization code. This may be exchanged for the refresh token. It expires 10 minutes after authorization. It MUST NOT be used again once the client has successfully exchanged it for a refresh token.
  • state: The value of the state parameter that was passed in with the initial request.

If the authorization fails due to a missing or invalid client_id or redirect_uri parameter, the user agent will not redirect back to the client. Otherwise, the client will receive a response via the redirect_uri, which will include the following query parameters:

  • error: An error type, as per RFC 6749, section
  • state: The value of the state parameter that was passed in with the initial request.

Obtaining a refresh token

Following authorization, the client will obtain initial refresh tokens and access tokens by making a POST request to the Fastmail token endpoint:


The following parameters MUST be present, using the “application/x-www-form-urlencoded” format with a character encoding of UTF-8 in the HTTP request entity-body:

  • client_id: The client id as given to the developer.
  • redirect_uri: The redirect_uri parameter sent with the authorization request from which the code was obtained.
  • grant_type: This MUST be “authorization_code”.
  • code: The code returned via the redirect back from authorization.
  • code_verifier: The code_verifier generated for the authorization, as per RFC 7636.

Other parameters MAY be supplied but will be ignored.

The server will verify the parameters and if successful, return a 200 OK response with a content type of application/json. The body will be a JSON object with the following properties:

  • access_tokenString A bearer token used to authenticate API requests. This will be valid for a fixed, limited time.
  • token_typeString The type of the access token. For now, this will always be “bearer”.
  • expires_inNumber The lifetime in seconds of the access token. For example, the value 3600 denotes that the access token will expire in one hour from the time the response was generated.
  • scopeString The space delimited set of scopes that this access token may use.
  • refresh_tokenString The refresh token to use next time the client needs to get a new access token.

If the request fails, the server will return an appropriate HTTP error response, probably 400 Bad Request, with a content type of application/json. The body will be a JSON object with the following property:

  • errorString A single ASCII error code indicating why the request failed, with a value as per RFC 6749, Section 5.2

Getting a new access token

Client should keep using an access token they have been issued until it expires, which will result in getting a 401 error back.

When the access token expires, the client must get a new one by making another POST request to the Fastmail token endpoint. The following parameters MUST be present, using the “application/x-www-form-urlencoded” format with a character encoding of UTF-8 in the HTTP request entity-body:

  • client_id: The client id as given to the developer.
  • grant_type: This MUST be “refresh_token”.
  • refresh_token: The refresh token returned last time the client obtained a new access token.

The success and failures responses are identical to those documented in the “obtaining a refresh token” section above.

In the case of an “invalid_grant” error, there MAY be an additional property called “temporary”. If this is present and the value is true, the refresh token MAY become valid again at some point in the future. (This can happen if a user is locked by their admin, but then unlocked again at a later point.) The “error_description” property of the error object SHOULD be present with a user-readable explanation that the client may like to show. If the “temporary” property is not present, an invalid_grant error is permanent and the user will need to go through the OAuth flow again to get a new refresh token if they wish to reconnect to their Fastmail account.

Please note, a new refresh token will be returned in the response and the client MUST replace their previous refresh token with this. The client MUST NOT try to use an old refresh token again; this will result in the authorization being revoked as a protection against leaked refresh tokens. If the user has multiple devices, each client must obtain separate authorization. You cannot share a refresh token between devices.

Revoking a token

If a client no longer needs the access it has been granted to an account, it can make an authenticated POST request to the following URL to immediately revoke all associated access tokens and refresh tokens: