If you’re building a product that other people’s XOXO accounts will sign in to — for example, an integration that reads their subscribers or sends emails on their behalf — register an OAuth app and use the authorization code flow.Documentation Index
Fetch the complete documentation index at: https://help.xoxo.email/llms.txt
Use this file to discover all available pages before exploring further.
Building an integration just for your own account? Use a personal API key from Settings → Apps instead — it’s simpler and works the same way.
Request client credentials
OAuth apps are created by the XOXO team. Email hi@xoxo.email with:- App name — shown to users on the consent screen
- Description — one or two sentences about what your app does
- Redirect URIs — every callback URL your app uses, including local development (e.g.
http://localhost:3000/callback) - Logo — optional SVG, shown on the consent screen
client_id and client_secret. Treat the secret like a password.
Endpoints
All OAuth endpoints live onapp.xoxo.email.
| Purpose | Method | URL |
|---|---|---|
| Authorization | GET | https://app.xoxo.email/oauth/authorize |
| Token exchange | POST | https://app.xoxo.email/oauth/token |
| Token revocation | POST | https://app.xoxo.email/oauth/revoke |
Scopes
XOXO uses a single scope,account, which grants your app the same access the signed-in user has. Request it on every authorization.
Authorization code flow
XOXO supports the authorization code flow with PKCE. Other grant types (client credentials, implicit, password) aren’t supported.Generate a PKCE pair
Create a random
code_verifier (43–128 characters) and derive the code_challenge by SHA-256 hashing the verifier and base64url-encoding the result. Only S256 is accepted as the code_challenge_method.Redirect the user to the authorization URL
redirect_uri with code and state query parameters.Call the API
Use the access token as a bearer token against the REST API or MCP server:
Refresh tokens
Access tokens expire after two hours. Exchange therefresh_token for a new access token before it expires: