Authentication
Ascend supports multiple authentication methods for different use cases. All API requests require authentication except for the login endpoint.
Authentication Methods
| Method | Use Case | Header/Mechanism | Lifetime |
|---|---|---|---|
| API Key | SDKs, automation, server-to-server | X-API-Key header | Custom (up to 10 years) |
| JWT Token | Web apps, mobile, SSO | Authorization: Bearer <token> | 1 hour (auto-refresh) |
| Session Cookie | Browser-based dashboards | access_token cookie | 24 hours |
API Key Authentication
API keys are the recommended method for SDK integrations and server-to-server communication.
Generating an API Key
POST /api/keys/generate
Authentication: Requires existing session (JWT or cookie)
Request Body:
{
"name": "Production SDK Key",
"description": "API key for production agent integration",
"expires_in_days": 365,
"permissions": [
{"category": "agent_actions", "actions": ["create", "read"]},
{"category": "alerts", "actions": ["read"]}
],
"rate_limit": {
"max_requests": 1000,
"window_seconds": 3600
}
}
Response (200 OK):
{
"success": true,
"api_key": "owkai_admin_aBcDeFgHiJkLmNoPqRsTuVwXyZ123456789",
"key_id": 42,
"key_prefix": "owkai_admin_aBcDeFgHiJkLmNoP",
"name": "Production SDK Key",
"expires_at": "2027-01-20T00:00:00Z",
"created_at": "2026-01-20T12:00:00Z",
"warning": "Save this key now - you will NOT see it again!"
}
Important: The full API key is only returned once at creation. Store it securely.
Using API Keys
Include the API key in the X-API-Key header:
curl -X POST https://pilot.owkai.app/api/v1/actions/submit \
-H "X-API-Key: owkai_admin_aBcDeFgHiJkLmNoPqRsTuVwXyZ123456789" \
-H "Content-Type: application/json" \
-d '{
"agent_id": "my-agent",
"action_type": "database_query",
"description": "Query user data",
"tool_name": "postgresql"
}'
API Key Format
API keys follow the format: owkai_{role}_{random}
| Prefix | Role | Example |
|---|---|---|
owkai_admin_ | Admin user | owkai_admin_aBcDeFg... |
owkai_user_ | Standard user | owkai_user_xYz123... |
owkai_super_admin_ | Platform admin | owkai_super_admin_... |
Permission Shorthand
You can also use string shorthand for permissions:
{
"name": "Limited Access Key",
"permissions": [
"agent:read",
"action:submit",
"alert:read"
]
}
JWT Token Authentication
JWT tokens are used for web applications and mobile apps with AWS Cognito integration.
Obtaining a Token
POST /api/auth/token
Request Body:
{
"email": "admin@company.com",
"password": "SecurePassword123!"
}
Response (200 OK):
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"id": 123,
"email": "admin@company.com",
"role": "admin",
"organization_id": 1
}
}
Using JWT Tokens
Include the token in the Authorization header:
curl https://pilot.owkai.app/api/v1/actions \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
Token Refresh
POST /api/auth/refresh-token
Request Body:
{
"refresh_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Response (200 OK):
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"expires_in": 3600
}
Session Cookie Authentication
Session cookies are automatically set during login for browser-based applications.
Login
POST /api/auth/token
The response includes a Set-Cookie header with an HttpOnly, Secure cookie:
Set-Cookie: access_token=eyJ...; HttpOnly; Secure; SameSite=Strict; Path=/
CSRF Protection
For state-changing requests (POST, PUT, DELETE), include a CSRF token:
GET /api/auth/csrf
Response:
{
"csrf_token": "abc123..."
}
Include in subsequent requests:
curl -X POST https://pilot.owkai.app/api/v1/actions/submit \
-H "X-CSRF-Token: abc123..." \
-b cookies.txt \
-d '{...}'
API Key Management
List API Keys
GET /api/keys/list
Query Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
include_revoked | boolean | false | Include revoked keys |
page | integer | 1 | Page number |
page_size | integer | 20 | Items per page |
Response:
{
"success": true,
"keys": [
{
"id": 42,
"key_prefix": "owkai_admin_aBcDeFgH...",
"name": "Production SDK Key",
"description": "API key for production",
"is_active": true,
"created_at": "2026-01-20T12:00:00Z",
"expires_at": "2027-01-20T00:00:00Z",
"last_used_at": "2026-01-20T15:30:00Z",
"usage_count": 1542
}
],
"total_count": 1,
"page": 1,
"page_size": 20
}
Revoke API Key
DELETE /api/keys/{key_id}/revoke
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
reason | string | No | Reason for revocation |
Response:
{
"success": true,
"message": "API key revoked successfully",
"key_id": 42,
"revoked_at": "2026-01-20T16:00:00Z"
}
Get API Key Usage
GET /api/keys/{key_id}/usage
Query Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | integer | 100 | Max recent activities |
Response:
{
"success": true,
"key_id": 42,
"key_prefix": "owkai_admin_aBcDeFgH...",
"statistics": {
"total_requests": 1542,
"recent_requests": 100,
"success_rate": 98.5,
"last_used_at": "2026-01-20T15:30:00Z"
},
"recent_activity": [
{
"timestamp": "2026-01-20T15:30:00Z",
"endpoint": "/api/v1/actions/submit",
"method": "POST",
"status": 200,
"ip_address": "192.168.1.100",
"response_time_ms": 45
}
]
}
Security Best Practices
API Key Security
- Never expose API keys in client-side code - Use server-side proxies
- Use environment variables - Never hardcode keys
- Rotate keys regularly - Set expiration dates
- Use minimal permissions - Only grant necessary access
- Monitor usage - Review activity logs for anomalies
JWT Token Security
- Short token lifetime - Use 1-hour access tokens
- Secure token storage - Use HttpOnly cookies when possible
- Validate on every request - Server validates signature and expiry
- Use RS256 algorithm - Asymmetric signing for better security
Code Examples
Python
from ascend import AscendClient
# Initialize with API key
client = AscendClient(api_key="owkai_admin_...")
# Submit an action
result = client.actions.submit(
agent_id="my-agent",
action_type="database_query",
description="Query user records",
tool_name="postgresql"
)
Node.js
import { AscendClient } from '@ascend-ai/sdk';
// Initialize with API key
const client = new AscendClient({ apiKey: 'owkai_admin_...' });
// Submit an action
const result = await client.actions.submit({
agentId: 'my-agent',
actionType: 'database_query',
description: 'Query user records',
toolName: 'postgresql'
});
cURL
# Using API Key
curl -X POST https://pilot.owkai.app/api/v1/actions/submit \
-H "X-API-Key: owkai_admin_..." \
-H "Content-Type: application/json" \
-d '{
"agent_id": "my-agent",
"action_type": "database_query",
"description": "Query user records",
"tool_name": "postgresql"
}'
# Using JWT Token
curl -X POST https://pilot.owkai.app/api/v1/actions/submit \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiI..." \
-H "Content-Type: application/json" \
-d '{...}'
Error Responses
| Status Code | Error | Description |
|---|---|---|
| 401 | Unauthorized | Missing or invalid credentials |
| 403 | Forbidden | Valid credentials but insufficient permissions |
| 429 | Too Many Requests | Rate limit exceeded for API key |
Example Error Response:
{
"detail": "Invalid or expired API key",
"error_code": "INVALID_API_KEY",
"status": 401
}