Get your API key
Getting started

Server-side login & register

Two ways to authenticate from a server — pick by whose account you act as. In both, register is unified with login: a new user is created and signed in as part of the same flow.

A · Your own account (email + password)

When your app sends from a single MailKite account, just register or log in with email and password and keep the returned token — it's a bearer credential that works exactly like an mk_live_… API key. Signup also provisions your API key and sends a welcome email.

register or log in
// Register a new account (or log in if it already exists), then use the token.
const base = "https://api.mailkite.dev";
let res = await fetch(`${base}/api/auth/signup`, {
  method: "POST", headers: { "content-type": "application/json" },
  body: JSON.stringify({ email: "you@example.com", password: process.env.MK_PASSWORD }),
});
if (res.status === 409) {                       // already registered → log in
  res = await fetch(`${base}/api/auth/login`, {
    method: "POST", headers: { "content-type": "application/json" },
    body: JSON.stringify({ email: "you@example.com", password: process.env.MK_PASSWORD }),
  });
}
const { token } = await res.json();
const mk = new MailKite(token);                 // the session token works like an API key
Install Docs →

POST /api/auth/signup returns 201 { token, user } (or 409 if the email exists). POST /api/auth/login returns { token, user }. Google sign-in is also available at POST /api/auth/google.

B · Your users' accounts (OAuth 2.1 + PKCE)

For multi-tenant apps, send each user to MailKite's hosted page to sign in or create an account, then exchange the returned code for a token that is that user. This is the same flow the client SDKs use, run from your server. No password ever touches your app.

1 · Register a client (once)

POST /oauth/register
# Once per app — dynamically register a public client, cache the client_id.
curl https://api.mailkite.dev/oauth/register \
  -H "Content-Type: application/json" \
  -d '{
    "client_name": "My App",
    "redirect_uris": ["https://app.example.com/callback"],
    "grant_types": ["authorization_code", "refresh_token"],
    "response_types": ["code"]
  }'
# → { "client_id": "mkc_…" }

2 · Send the user to log in or register

Create a PKCE pair, store the verifier against a random state, and redirect:

redirect to /oauth/authorize
// Build the URL you redirect the user to. They LOG IN OR REGISTER on MailKite's
// hosted page, then come back to your redirect_uri with a one-time ?code=.
const url = new URL("https://api.mailkite.dev/oauth/authorize");
url.search = new URLSearchParams({
  response_type: "code",
  client_id,                         // from /oauth/register
  redirect_uri: "https://app.example.com/callback",
  scope: "mcp",                      // full account — the only scope today
  state,                             // random; store with the PKCE verifier
  code_challenge,                    // base64url(sha256(verifier))
  code_challenge_method: "S256",
}).toString();
res.redirect(url.toString());

3 · Handle the callback & exchange the code

GET /callback
// On your /callback route, exchange the code for a token that IS the user.
const tok = await fetch("https://api.mailkite.dev/oauth/token", {
  method: "POST", headers: { "content-type": "application/x-www-form-urlencoded" },
  body: new URLSearchParams({
    grant_type: "authorization_code",
    code,
    redirect_uri: "https://app.example.com/callback",
    client_id,
    code_verifier,                   // the PKCE verifier you stored for this state
  }).toString(),
});
const { access_token, refresh_token } = await tok.json();
const mk = new MailKite(access_token); // now act as that user; store refresh_token to renew

Full runnable examples

Every server SDK ships an end-to-end server-login example (both flows) in its repo's examples/ folder — e.g. Node and Python. Browser & mobile apps should use the client libraries, which handle PKCE, token storage, and refresh for you.