Skip to main content
Both the REST API and the MCP server are protected by the same OAuth 2.0 authorization server, mounted at {origin}/oauth. Every request carries a JWT as a Bearer token.

Quick token (server-to-server)

For backend services and scripts, exchange account credentials for a JWT:
curl -X POST "https://api.izap.ai/api/v1/auth/jwt/login" \
     -H "Content-Type: application/x-www-form-urlencoded" \
     -d "username=$IZAP_EMAIL&password=$IZAP_PASSWORD"
# -> {"access_token":"<JWT>","token_type":"bearer"}
Then send it on every request:
Authorization: Bearer <access_token>

OAuth 2.0 (third-party apps)

Use the authorization-code + PKCE flow for clients that act on behalf of a user.

Discovery

Clients discover the authorization server via standard metadata documents:
DocumentPath
Authorization server metadata/.well-known/oauth-authorization-server
Protected resource metadata (MCP)/.well-known/oauth-protected-resource/mcp
The MCP endpoint returns 401 with a WWW-Authenticate header, so spec-compliant MCP clients bootstrap the OAuth flow automatically.

Flow

  1. GET /oauth/authorize with response_type=code, client_id, redirect_uri, code_challenge, code_challenge_method=S256, and state.
  2. The user authenticates and approves; iZap redirects back with code.
  3. POST /oauth/token with grant_type=authorization_code, code, redirect_uri, and code_verifier → returns an access_token (JWT) and a refresh_token.
Public clients may self-register via POST /oauth/register. Refresh an expired token with grant_type=refresh_token.

Token notes

  • The access token is a JWT — treat it as a secret and read it from an environment variable, never hardcode it.
  • Tokens expire. Refresh (re-login or the OAuth refresh grant) when a request returns 401.