Authentication

Set up the authentication for your API to help users manage their credentials.

Log in to see your API keys
API KeyLabelLast Used

Authenticate all Astra API requests by including your API key in the request header.

Astra supports two authentication methods:

  • API Keys — For server-side integrations you control. Pass sk_live_... as a Bearer token.
  • OAuth 2.0 — For third-party integrations that act on behalf of an Astra user. Uses the Authorization Code flow to obtain astra_at_... access tokens.

Get your API key

Create an API key from the Astra Dashboard:

  1. Log in to the Astra Dashboard.
  2. Navigate to Account → API Keys.
  3. Click Create API Key.
  4. Copy and store the key immediately.

Your API key (starting with sk_live_) is displayed only once at creation time. It cannot be retrieved later — store it somewhere safe before closing the dialog.

Authenticate requests

Include your API key in the Authorization header as a Bearer token:

Authorization: Bearer sk_live_your_api_key_here

Alternatively, pass it via the X-API-Key header:

X-API-Key: sk_live_your_api_key_here
curl -X GET https://astra-gateway.wati.io/v1/agents \
  -H "Authorization: Bearer sk_live_your_api_key_here"

A successful request returns a 200 status code with the response body. An invalid or missing key returns a 401:

{
  "error": {
    "code": "unauthorized",
    "message": "Invalid or missing API key"
  }
}

OAuth 2.0

For third-party integrations that need to act on behalf of an Astra user, use the OAuth 2.0 Authorization Code flow. After obtaining an access token, include it in the Authorization header the same way as an API key:

Authorization: Bearer astra_at_your_access_token_here

Flow overview

  1. Register an OAuth app — Call POST /oauth/apps from the Dashboard (requires session auth) to get a client_id and client_secret.
  2. Redirect the user — Send the user to your consent page with client_id, redirect_uri, scope, and state parameters.
  3. User approves — After approval, POST /oauth/authorize returns a redirect URI containing an authorization code.
  4. Exchange the code — Call POST /oauth/token with grant_type: authorization_code to receive an access token and refresh token.
  5. Make API requests — Use the access token (astra_at_...) as a Bearer token.
  6. Refresh when expired — Call POST /oauth/token with grant_type: refresh_token to get a new token pair.

Token lifetimes

TokenPrefixValidity
Access tokenastra_at_24 hours
Refresh tokenastra_rt_30 days

Register an OAuth app

curl -X POST https://astra-gateway.wati.io/v1/oauth/apps \
  -H "Authorization: Bearer $SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "My Integration",
    "redirect_uris": ["https://myapp.example.com/callback"],
    "scopes": ["chat", "agents:read", "agents:write"]
  }'
{
  "app": {
    "id": "a1b2c3d4-...",
    "name": "My Integration",
    "client_id": "oapp_abc123",
    "redirect_uris": ["https://myapp.example.com/callback"],
    "scopes": ["chat", "agents:read", "agents:write"],
    "is_active": true
  },
  "client_secret": "osec_xyz789..."
}

The client_secret is displayed only once at creation time. Store it securely before closing the response.

Exchange code for tokens

curl -X POST https://astra-gateway.wati.io/v1/oauth/token \
  -H "Content-Type: application/json" \
  -d '{
    "grant_type": "authorization_code",
    "code": "auth_code_from_redirect",
    "client_id": "oapp_abc123",
    "client_secret": "osec_xyz789...",
    "redirect_uri": "https://myapp.example.com/callback"
  }'
{
  "access_token": "astra_at_abc123...",
  "refresh_token": "astra_rt_def456...",
  "token_type": "Bearer",
  "expires_in": 86400,
  "scope": "chat agents:read agents:write"
}

Refresh an access token

curl -X POST https://astra-gateway.wati.io/v1/oauth/token \
  -H "Content-Type: application/json" \
  -d '{
    "grant_type": "refresh_token",
    "refresh_token": "astra_rt_def456...",
    "client_id": "oapp_abc123",
    "client_secret": "osec_xyz789..."
  }'

OAuth scopes

OAuth apps can request any combination of the following scopes:

ScopeDescription
*Full access to all resources
chatSend messages and interact with agents
agents:readRead agent configurations
agents:writeCreate and update agents
conversations:readRead conversation history
conversations:writeCreate conversations
contacts:readRead contacts
contacts:writeCreate and update contacts
knowledge:readRead knowledge bases
knowledge:writeManage knowledge bases
webhooks:manageManage webhook subscriptions
analytics:readRead analytics data
actions:readRead configured actions
actions:writeManage actions
connections:readRead platform connections
connections:writeManage connections
files:readRead uploaded files
files:writeUpload and manage files
voice:readRead voice configurations
voice:writeManage voice settings
templates:readRead agent templates

API key scopes

Each API key has scopes that control which endpoints it can access. Assign only the scopes your integration needs.

ScopeDescription
allFull access to all endpoints
chatSend and receive messages
agents:readList and retrieve agents
agents:writeCreate, update, and delete agents
conversations:readList and retrieve conversations
contacts:readList and retrieve contacts
contacts:writeCreate, update, and delete contacts
knowledge:readList and retrieve knowledge bases and documents
knowledge:writeCreate, update, and delete knowledge bases and documents
analytics:readAccess analytics and performance metrics
webhooks:manageCreate, update, and delete webhooks

Security best practices

Astra enforces several security measures for API keys:

  • Hashed storage — Keys are hashed with HMAC-SHA256 before storage. The raw key cannot be recovered from the database.
  • Single display — The full key is shown only once at creation. There is no endpoint to retrieve it again.
  • Tenant isolation — Each key is bound to a tenant_id. Requests cannot access other tenants' data.
  • Immediate revocation — Revoked keys are rejected on the next request with no delay.

Follow these practices to keep your keys secure:

  • Store keys in environment variables — never hardcode them in source files.
    export ASTRA_API_KEY="sk_live_your_api_key_here"
  • Never commit keys to version control. Add your .env file to .gitignore.
  • Rotate keys periodically using the rotate endpoint, even if you don't suspect a leak.
  • Use the minimum scopes required for each integration. Avoid using all unless necessary.

Key management

Manage your API keys programmatically after creating them in the Dashboard.

Rotate a key

Replace a key with a new one in a single atomic operation. The old key is invalidated immediately and a new key is returned with the same name and scopes.

curl -X POST https://astra-gateway.wati.io/v1/api-keys/{key_id}/rotate \
  -H "Authorization: Bearer $SESSION_TOKEN"

Revoke a key

Permanently disable a key. Revoked keys cannot be reactivated.

curl -X DELETE https://astra-gateway.wati.io/v1/api-keys/{key_id} \
  -H "Authorization: Bearer $SESSION_TOKEN"

List keys

Retrieve all API keys for your account. The response includes metadata (name, scopes, request count, last used) but not the raw key values.

curl -X GET https://astra-gateway.wati.io/v1/api-keys \
  -H "Authorization: Bearer $SESSION_TOKEN"

Key management endpoints (/v1/api-keys) require a valid Dashboard session token, not an API key. You must be logged into the Astra Dashboard to create, rotate, revoke, or list keys.

Rate limiting

API requests are rate-limited per key at 10 requests per second with a burst allowance of 20 requests.

When you exceed the limit, the API returns a 429 Too Many Requests response with a Retry-After header indicating how many seconds to wait:

{
  "error": {
    "code": "rate_limited",
    "message": "Too many requests"
  }
}

Handle rate limits by respecting the Retry-After header:

import time
import requests

def make_request(url, headers):
    response = requests.get(url, headers=headers)

    if response.status_code == 429:
        retry_after = int(response.headers.get("Retry-After", 1))
        print(f"Rate limited — retrying in {retry_after}s")
        time.sleep(retry_after)
        return make_request(url, headers)  # Retry once

    return response

Request tracing

Every API response includes an X-Request-Id header. You can also pass your own request ID via the same header. Include this ID when contacting support for faster debugging.

Troubleshooting

401 Unauthorized — Invalid or missing API key
  • Confirm the key starts with sk_live_ and is complete (no trailing whitespace or truncation).
  • Check the header format: Authorization: Bearer sk_live_... (note the space after Bearer).
  • Verify the key hasn't been revoked in Settings → API Keys in the Dashboard.
403 Forbidden — Insufficient scopes

The key is valid but doesn't have the required scope for this endpoint. Check the key's assigned scopes in the Dashboard and add the missing scope, or create a new key with the correct scopes.

429 Too Many Requests — Rate limit exceeded

You're sending more than 10 requests per second. Add retry logic that reads the Retry-After header, or reduce request frequency. If you consistently need higher throughput, contact support.

Key lost — Cannot retrieve API key

API keys are shown only once at creation. If you've lost a key, revoke it in the Dashboard and create a new one. Update all integrations with the new key.

Credentials
LoadingLoading…
Response
Click Try It! to start a request and see the response here!

Did this page help you?