Authentication Guide
Netallion AI Assurance supports three authentication methods: API keys for server-to-server calls, JWT for user sessions, and OAuth for third-party integrations.
API Key Authentication
API keys are the simplest way to authenticate. They are best suited for server-side integrations, CI/CD pipelines, and CLI usage.
Navigate to Settings
Open the Netallion AI Assurance dashboard and go to Settings > API Keys.
Create a new key
Click Create API Key. Give it a descriptive name (e.g., "CI Pipeline") and select the scopes you need: scan:read, scan:write, incidents:read, admin.
Copy your key
The key is shown once. Copy it and store it securely (e.g., in a secrets manager). Keys are prefixed with cpf_live_ (production) or cpf_test_ (sandbox).
Include in requests
Pass the key in the Authorization header:
Authorization: Bearer cpf_live_abc123...
JWT Flow
For user-facing applications, use the JWT flow. Users authenticate with email/password and receive a short-lived access token.
Flow overview
POST /api/v1/auth/loginwith{"email": "...", "password": "..."}- Receive
access_token(15 min TTL) andrefresh_token(7 day TTL) - Include
Authorization: Bearer <access_token>on subsequent requests - When the access token expires, call
POST /api/v1/auth/refreshwith the refresh token
# Login
curl -X POST https://api.netallion.ai/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email": "user@example.com", "password": "..."}'
# Response
{
"access_token": "eyJhbGciOiJSUzI1NiIs...",
"refresh_token": "cpf_rt_...",
"expires_in": 900,
"token_type": "Bearer"
}
# Refresh
curl -X POST https://api.netallion.ai/api/v1/auth/refresh \
-H "Content-Type: application/json" \
-d '{"refresh_token": "cpf_rt_..."}'OAuth 2.0 Flow
For third-party integrations (e.g., Slack bots, CI/CD platforms), use the OAuth 2.0 authorization code flow.
Endpoints
- Authorization:
https://app.netallion.ai/oauth/authorize?client_id=...&redirect_uri=...&scope=scan:read+incidents:read&response_type=code - Token exchange:
POST https://api.netallion.ai/oauth/token - Token refresh:
POST https://api.netallion.ai/oauth/tokenwithgrant_type=refresh_token
# Exchange authorization code for access token
curl -X POST https://api.netallion.ai/oauth/token \
-H "Content-Type: application/json" \
-d '{
"grant_type": "authorization_code",
"client_id": "your_client_id",
"client_secret": "your_client_secret",
"code": "auth_code_from_redirect",
"redirect_uri": "https://your-app.com/callback"
}'
# Response
{
"access_token": "cpf_oat_...",
"refresh_token": "cpf_ort_...",
"expires_in": 3600,
"scope": "scan:read incidents:read",
"token_type": "Bearer"
}Rate Limits
Rate limits are enforced per API key or access token. Limits vary by plan tier.
| Plan | Rate Limit | Burst | Daily Quota |
|---|---|---|---|
| Starter | 100 req/min | 20 req/s | 10,000 req/day |
| Professional | 500 req/min | 100 req/s | 100,000 req/day |
| Enterprise | 2,000 req/min | 500 req/s | Unlimited |
Rate limit headers: Every response includes X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset (Unix timestamp). When rate limited, you receive HTTP 429 with a Retry-After header.
Code Samples
cURL
# List recent scan results
curl -s https://api.netallion.ai/api/v1/scans \
-H "Authorization: Bearer cpf_live_abc123..." \
-H "Accept: application/json"
# Trigger a new scan
curl -X POST https://api.netallion.ai/api/v1/scans \
-H "Authorization: Bearer cpf_live_abc123..." \
-H "Content-Type: application/json" \
-d '{"workspace_id": "ws_...", "scope": "full"}'Python (httpx)
import httpx
client = httpx.Client(
base_url="https://api.netallion.ai/api/v1",
headers={"Authorization": "Bearer cpf_live_abc123..."},
timeout=30.0,
)
# List scans
scans = client.get("/scans").json()
# Trigger scan
resp = client.post("/scans", json={
"workspace_id": "ws_...",
"scope": "full",
})
scan = resp.json()
print(f"Scan {scan['id']} started")TypeScript (fetch)
const API_BASE = "https://api.netallion.ai/api/v1";
const API_KEY = process.env.NETALLION_API_KEY!;
const headers = {
Authorization: `Bearer ${API_KEY}`,
"Content-Type": "application/json",
};
// List scans
const scans = await fetch(`${API_BASE}/scans`, { headers }).then((r) =>
r.json()
);
// Trigger scan
const resp = await fetch(`${API_BASE}/scans`, {
method: "POST",
headers,
body: JSON.stringify({ workspace_id: "ws_...", scope: "full" }),
});
const scan = await resp.json();
console.log(`Scan ${scan.id} started`);