Authentication
The Turqoa API supports two authentication methods: API key authentication for server-to-server integrations, and OAuth 2.0 for applications that act on behalf of users. All requests must be authenticated.
API Key Authentication
API keys are the simplest way to authenticate. Each key is scoped to specific permissions and tied to a service account.
Creating an API Key
API keys are created in the Turqoa admin panel under Settings > API Keys, or via the API:
curl -X POST https://api.turqoa.com/v1/auth/api-keys \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "SIEM Integration",
"scopes": ["events:read", "transactions:read"],
"expires_in_days": 365,
"ip_allowlist": ["10.0.0.0/8", "192.168.1.0/24"]
}'
Response:
{
"data": {
"id": "key_abc123",
"name": "SIEM Integration",
"key": "tqa_live_a1b2c3d4e5f6g7h8i9j0...",
"scopes": ["events:read", "transactions:read"],
"expires_at": "2027-04-06T00:00:00Z",
"created_at": "2026-04-06T10:00:00Z"
}
}
The full key is only shown once at creation time. Store it securely.
Using an API Key
Include the key in the Authorization header with the Bearer prefix:
curl https://api.turqoa.com/v1/events \
-H "Authorization: Bearer tqa_live_a1b2c3d4e5f6g7h8i9j0..."
import requests
headers = {
"Authorization": "Bearer tqa_live_a1b2c3d4e5f6g7h8i9j0..."
}
response = requests.get(
"https://api.turqoa.com/v1/events",
headers=headers
)
events = response.json()
const response = await fetch("https://api.turqoa.com/v1/events", {
headers: {
Authorization: "Bearer tqa_live_a1b2c3d4e5f6g7h8i9j0...",
},
});
const events = await response.json();
Key Prefixes
| Prefix | Environment |
|---|---|
tqa_live_ | Production |
tqa_test_ | Staging/test |
tqa_dev_ | Development |
Key Rotation
Rotate keys without downtime by creating a new key before revoking the old one:
# 1. Create new key with same scopes
curl -X POST https://api.turqoa.com/v1/auth/api-keys \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-d '{"name": "SIEM Integration v2", "scopes": ["events:read", "transactions:read"]}'
# 2. Update your integration to use the new key
# 3. Revoke the old key
curl -X DELETE https://api.turqoa.com/v1/auth/api-keys/key_abc123 \
-H "Authorization: Bearer $ADMIN_TOKEN"
OAuth 2.0 Flow
For applications that need to act on behalf of Turqoa users (e.g., third-party dashboards), use the OAuth 2.0 Authorization Code flow.
Register an Application
Register your application in the admin panel under Settings > OAuth Applications:
{
"name": "Security Dashboard",
"redirect_uris": ["https://dashboard.example.com/callback"],
"scopes": ["events:read", "transactions:read", "maritime:read"],
"grant_types": ["authorization_code", "refresh_token"]
}
You will receive a client_id and client_secret.
Authorization Flow
Step 1: Redirect to Authorization
Redirect the user to the Turqoa authorization endpoint:
https://auth.turqoa.com/oauth/authorize?
response_type=code&
client_id=YOUR_CLIENT_ID&
redirect_uri=https://dashboard.example.com/callback&
scope=events:read+transactions:read&
state=random_csrf_token
Step 2: User Grants Access
The user logs in and approves the requested scopes. Turqoa redirects back to your redirect_uri with an authorization code:
https://dashboard.example.com/callback?code=AUTH_CODE&state=random_csrf_token
Step 3: Exchange Code for Tokens
curl -X POST https://auth.turqoa.com/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code" \
-d "code=AUTH_CODE" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "redirect_uri=https://dashboard.example.com/callback"
Response:
{
"access_token": "tqa_oauth_eyJhbGciOiJSUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "tqa_refresh_dGhpcyBpcyBhIH...",
"scope": "events:read transactions:read"
}
Step 4: Use the Access Token
curl https://api.turqoa.com/v1/events \
-H "Authorization: Bearer tqa_oauth_eyJhbGciOiJSUzI1NiIs..."
Token Refresh
Access tokens expire after 1 hour. Use the refresh token to obtain a new access token without user interaction:
curl -X POST https://auth.turqoa.com/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=refresh_token" \
-d "refresh_token=tqa_refresh_dGhpcyBpcyBhIH..." \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET"
{
"access_token": "tqa_oauth_bmV3IGFjY2VzcyB0b2tl...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "tqa_refresh_bmV3IHJlZnJlc2gg..."
}
Refresh tokens expire after 30 days of inactivity. Each refresh returns a new refresh token (rotation).
Automatic Refresh in SDKs
from turqoa import TurqoaClient
# The SDK handles token refresh automatically
client = TurqoaClient(
client_id="YOUR_CLIENT_ID",
client_secret="YOUR_CLIENT_SECRET",
refresh_token="tqa_refresh_dGhpcyBpcyBhIH..."
)
# This will auto-refresh if the token has expired
events = client.events.list(severity="high")
import { TurqoaClient } from "@turqoa/sdk";
const client = new TurqoaClient({
clientId: "YOUR_CLIENT_ID",
clientSecret: "YOUR_CLIENT_SECRET",
refreshToken: "tqa_refresh_dGhpcyBpcyBhIH...",
});
// Auto-refreshes transparently
const events = await client.events.list({ severity: "high" });
Scoped Permissions
Both API keys and OAuth tokens are scoped to specific permissions. A request to an endpoint outside the token's scope returns 403 Forbidden.
Available Scopes
| Scope | Description |
|---|---|
events:read | Read security events |
events:write | Create and update events |
transactions:read | Read gate transactions |
transactions:write | Override transaction decisions |
maritime:read | Read vessel data, zones, risk scores |
maritime:write | Create/modify threat zones |
drones:read | Read fleet status and mission data |
drones:write | Create missions, abort flights |
webhooks:read | List webhook configurations |
webhooks:write | Create, update, delete webhooks |
system:read | Read system health and config |
system:write | Modify system configuration |
admin | Full administrative access |
Checking Token Scopes
curl https://api.turqoa.com/v1/auth/introspect \
-H "Authorization: Bearer YOUR_TOKEN"
{
"data": {
"active": true,
"scopes": ["events:read", "transactions:read"],
"expires_at": "2026-04-06T11:00:00Z",
"client_id": "YOUR_CLIENT_ID",
"token_type": "oauth"
}
}
Security Best Practices
- Store API keys in environment variables or a secrets manager, never in source code
- Use the narrowest scope necessary for each integration
- Set IP allowlists on API keys when the calling service has a fixed IP
- Rotate API keys at least every 90 days
- Monitor the API Key Usage dashboard in the admin panel for anomalies
- Use OAuth 2.0 for any user-facing application rather than embedding API keys in client-side code
- Enable webhook signature verification (see Webhooks)