OAuth 2.0 & API Access
Authenticate with Evergreen using OAuth 2.0 access tokens or long-lived API keys.
Evergreen supports two ways for external applications and integrations to authenticate against its API:
| Method | Token prefix | Best for |
|---|---|---|
| Long-lived API key | evg_ | Server-to-server integrations, personal scripts |
| OAuth 2.0 access token | evg_at_ | Third-party apps that act on behalf of a user |
Both token formats are accepted in the same Authorization: Bearer header — Evergreen detects the format automatically based on the prefix.
OAuth 2.0 Authorization Code Flow
Evergreen implements the RFC 6749 Authorization Code Grant with PKCE and supports dynamic client registration (RFC 7591).
Discovery endpoints
| Endpoint | URL |
|---|---|
| Authorization server metadata | /.well-known/oauth-authorization-server |
| Protected resource metadata | /.well-known/oauth-protected-resource |
These follow standard OAuth 2.0 discovery conventions and allow compatible clients to configure themselves automatically.
Step 1 — Register your client
Send a POST request to /api/oauth/register with a JSON body:
{
"client_name": "My App",
"redirect_uris": ["https://myapp.example.com/callback"],
"grant_types": ["authorization_code", "refresh_token"],
"response_types": ["code"],
"token_endpoint_auth_method": "none"
}
Required fields:
client_name— Human-readable name shown on the consent screen.redirect_uris— One or more callback URLs. Each URI must usehttpsor point tolocalhost.
Optional fields:
| Field | Default |
|---|---|
grant_types | ["authorization_code", "refresh_token"] |
response_types | ["code"] |
token_endpoint_auth_method | "none" (public client) |
scope | All available scopes |
The response contains your client_id and, for confidential clients, a client_secret. Store the secret securely — it is shown only once.
Step 2 — Redirect the user to /oauth/authorize
Construct an authorization URL:
https://app.evergreen.so/oauth/authorize
?response_type=code
&client_id=evg_client_…
&redirect_uri=https://myapp.example.com/callback
&scope=read:projects%20read:analytics
&state=<random-state>
&code_challenge=<base64url-sha256-of-verifier>
&code_challenge_method=S256
The user will see a consent screen listing the requested scopes and registered client name. After they approve, Evergreen redirects back to your redirect_uri with a short-lived authorization code (valid for 10 minutes).
Step 3 — Exchange the code for tokens
Send a POST request to /api/oauth/token:
{
"grant_type": "authorization_code",
"code": "<auth-code>",
"redirect_uri": "https://myapp.example.com/callback",
"client_id": "evg_client_…",
"code_verifier": "<pkce-verifier>"
}
A successful response returns:
{
"access_token": "evg_at_…",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "evg_rt_…",
"scope": "read:projects read:analytics"
}
- Access tokens (
evg_at_) expire after 1 hour. - Refresh tokens expire after 30 days.
Step 4 — Call the API
Include the access token as a Bearer token in every request:
Authorization: Bearer evg_at_…
Step 5 — Refresh the access token
When the access token expires, obtain a new one using the refresh token:
{
"grant_type": "refresh_token",
"refresh_token": "evg_rt_…",
"client_id": "evg_client_…"
}
Available Scopes
| Scope | Access granted |
|---|---|
read:projects | List and read project details |
read:pages | Read page-level data |
read:analytics | Read analytics data |
read:performance | Read performance metrics |
read:structure | Read site structure data |
If no scope is specified, all available scopes are granted by default. Requests for unlisted scopes are silently dropped.
Long-Lived API Keys
API keys use the evg_ prefix. They do not expire and are suitable for automated server-side workflows. You can manage API keys from Settings → MCP Server.
Note: API keys grant the same scopes as OAuth tokens but are not tied to a specific user authorization flow. Use OAuth when building apps that act on behalf of individual users.
Error Codes
Token endpoint errors follow RFC 6749 §5.2 and return a JSON body:
{
"error": "invalid_grant",
"error_description": "…"
}
Common error codes:
| Code | Meaning |
|---|---|
invalid_request | A required parameter is missing or malformed |
invalid_client | Client authentication failed |
invalid_grant | The authorization code or refresh token is invalid or expired |
unauthorized_client | The client is not permitted to use this grant type |
unsupported_grant_type | The requested grant type is not supported |
invalid_scope | The requested scope is invalid |
