Three methods. Bearer tokens for sessions. API keys for servers. OAuth 2.0 for third-party apps.
Short-lived JWTs. Obtained via login.
Long-lived, scoped. Built for backends.
Auth code flow for third-party apps.
Credentials in, JWT out. Expires in 1 hour. Refresh tokens keep you alive without re-authenticating.
/v1/auth/loginEmail + password in. Access token + refresh token out.
| Name | Type | Required | Description |
|---|---|---|---|
email | string | Required | Account email. |
password | string | Required | Account password. |
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "rt_a1b2c3d4e5f6..."
}curl -X POST https://api.dyva.ai/v1/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "you@example.com",
"password": "your-password"
}'Drop it in the Authorization header. Every request.
curl https://api.dyva.ai/v1/dyvas \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."Got a 401? Swap the refresh token for a new pair. Single-use. Rotates every call.
/v1/auth/refreshRefresh token in. New token pair out.
| Name | Type | Required | Description |
|---|---|---|---|
refresh_token | string | Required | Refresh token from login or a previous refresh. |
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "rt_x9y8z7w6v5u4..."
}curl -X POST https://api.dyva.ai/v1/auth/refresh \
-H "Content-Type: application/json" \
-d '{ "refresh_token": "rt_a1b2c3d4e5f6..." }'Long-lived, scoped credentials. HardDrives-to-server. Create from settings or via the API.
| Scope | Permissions |
|---|---|
read | List and retrieve characters, conversations, messages. |
chat | Send messages, create conversations, interact. |
admin | Create/delete characters, manage keys, webhooks, billing. |
/v1/api-keysAuth RequiredNew API key with specified scopes.
| Name | Type | Required | Description |
|---|---|---|---|
name | string | Required | Label for this key. |
scopes | string[] | Required | One or more of "read", "chat", "admin". |
expires_in_days | number | Optional | Days until expiry. Omit for permanent. |
{
"id": "key_9f3a1b2c4d5e",
"name": "Production backend",
"key": "rk_live_abc123def456ghi789...",
"scopes": ["read", "chat"],
"created_at": "2026-03-09T12:00:00Z",
"expires_at": null
}curl -X POST https://api.dyva.ai/v1/api-keys \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
-d '{
"name": "Production backend",
"scopes": ["read", "chat"]
}'Drop it in the X-API-Key header.
curl https://api.dyva.ai/v1/dyvas \
-H "X-API-Key: rk_live_abc123def456ghi789..."Auth code flow. Users grant access without sharing credentials.
Send the user to Dyva. They approve, get redirected to your redirect_uri with a code.
https://api.dyva.ai/v1/oauth/authorize?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=https://yourapp.com/callback&scope=read%20chat&state=random_csrf_token| Name | Type | Required | Description |
|---|---|---|---|
response_type | string | Required | Must be "code". |
client_id | string | Required | Your app client ID. |
redirect_uri | string | Required | Where to redirect after authorization. |
scope | string | Required | Space-separated scopes, e.g. "read chat". |
state | string | Required | CSRF-prevention value your app generates. |
Swap the code for an access token on your backend. Single-use. Expires in 10 minutes.
/v1/oauth/tokenAuth code in. Access + refresh tokens out.
| Name | Type | Required | Description |
|---|---|---|---|
grant_type | string | Required | Must be "authorization_code". |
code | string | Required | Auth code from the redirect. |
redirect_uri | string | Required | Must match the authorize request URI. |
client_id | string | Required | Your app client ID. |
client_secret | string | Required | Your app client secret. |
{
"access_token": "eyJhbGciOiJSUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "rt_oauth_m4n5o6p7...",
"scope": "read chat"
}curl -X POST https://api.dyva.ai/v1/oauth/token \
-H "Content-Type: application/json" \
-d '{
"grant_type": "authorization_code",
"code": "ac_xyz789...",
"redirect_uri": "https://yourapp.com/callback",
"client_id": "YOUR_CLIENT_ID",
"client_secret": "YOUR_CLIENT_SECRET"
}'Expires after 1 hour. Refresh the same way as Bearer Token section above. Include client_id and client_secret in the body for OAuth tokens.
Auth failures return JSON with these status codes.
| Status | Error | Meaning |
|---|---|---|
401 | unauthorized | Missing, malformed, or expired credentials. Re-auth or refresh. |
403 | forbidden | Valid credentials, wrong scope. Check your API key permissions. |
// 401 Unauthorized — missing or invalid credentials
{
"error": "unauthorized",
"message": "Invalid or expired access token."
}
// 403 Forbidden — valid credentials, insufficient permissions
{
"error": "forbidden",
"message": "This API key does not have the \"admin\" scope required for this action."
}Every token and API key is a secret. Leaked credentials mean full access until revoked.