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.
{
"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": "[email protected]",
"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.
{
"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.
/v1/api-keysAuth RequiredNew API key with specified scopes.
{
"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_tokenSwap the code for an access token on your backend. Single-use. Expires in 10 minutes.
/v1/oauth/tokenAuth code in. Access + refresh tokens out.
{
"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.
// 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.