Authentication
The Tamandua API supports multiple authentication methods to accommodate different use cases, from server-to-server integrations to agent enrollment and web dashboard access.
API Keys
API keys are the recommended authentication method for server-to-server integrations, scripts, and third-party applications.
API Key Format
API keys follow a structured format for easy identification:
tam_<environment>_<random_string>
tam_live_- Production keystam_dev_- Development keystam_test_- Test environment keys
Example: tam_live_7a8b9c0d1e2f3g4h5i6j7k8l9m0n
Creating an API Key
Endpoint:POST /api/v1/api-keys
curl -X POST "https://api.tamandua.io/api/v1/api-keys" \
-H "Authorization: Bearer <session_token>" \
-H "Content-Type: application/json" \
-d '{
"api_key": {
"name": "Production Integration",
"description": "SIEM integration for alert forwarding",
"permissions": ["alerts:read", "alerts:write", "events:read"],
"scope": "organization",
"rate_limit_per_minute": 500,
"rate_limit_per_hour": 5000,
"expires_at": "2025-12-31T23:59:59Z",
"allowed_ips": ["10.0.0.0/8", "192.168.1.100"]
}
}'
Response:
{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Production Integration",
"description": "SIEM integration for alert forwarding",
"key_prefix": "tam_live_",
"permissions": ["alerts:read", "alerts:write", "events:read"],
"scope": "organization",
"rate_limit_per_minute": 500,
"rate_limit_per_hour": 5000,
"expires_at": "2025-12-31T23:59:59Z",
"allowed_ips": ["10.0.0.0/8", "192.168.1.100"],
"is_active": true,
"last_used_at": null,
"created_at": "2024-01-15T10:30:00Z"
},
"raw_key": "tam_live_7a8b9c0d1e2f3g4h5i6j7k8l9m0n",
"message": "API key created. Save this key securely - it cannot be retrieved later."
}
Important: The raw_key is only returned once at creation time. Store it securely.
Using an API Key
Include the API key in the Authorization header:
curl -X GET "https://api.tamandua.io/api/v1/alerts" \
-H "Authorization: Bearer tam_live_7a8b9c0d1e2f3g4h5i6j7k8l9m0n"
Listing API Keys
Endpoint:GET /api/v1/api-keys
curl -X GET "https://api.tamandua.io/api/v1/api-keys" \
-H "Authorization: Bearer <session_token>"
Response:
{
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Production Integration",
"key_prefix": "tam_live_",
"permissions": ["alerts:read", "alerts:write"],
"is_active": true,
"last_used_at": "2024-01-15T14:20:00Z",
"created_at": "2024-01-10T09:00:00Z"
}
]
}
Rotating an API Key
Endpoint:POST /api/v1/api-keys/:id/rotate
Creates a new key with the same settings and deactivates the old one:
curl -X POST "https://api.tamandua.io/api/v1/api-keys/550e8400-e29b-41d4-a716-446655440000/rotate" \
-H "Authorization: Bearer <session_token>"
Response:
{
"data": {
"id": "660e8400-e29b-41d4-a716-446655440001",
"name": "Production Integration (rotated)",
"key_prefix": "tam_live_",
"is_active": true
},
"raw_key": "tam_live_newkey123456789abcdefghijk",
"old_key_id": "550e8400-e29b-41d4-a716-446655440000",
"message": "API key rotated. Save the new key securely - it cannot be retrieved later."
}
Deactivating an API Key
Endpoint:POST /api/v1/api-keys/:id/deactivate
curl -X POST "https://api.tamandua.io/api/v1/api-keys/550e8400-e29b-41d4-a716-446655440000/deactivate" \
-H "Authorization: Bearer <session_token>"
Deleting an API Key
Endpoint:DELETE /api/v1/api-keys/:id
curl -X DELETE "https://api.tamandua.io/api/v1/api-keys/550e8400-e29b-41d4-a716-446655440000" \
-H "Authorization: Bearer <session_token>"
JWT Tokens (Agent Authentication)
JWT tokens are used for agent-to-server authentication. Agents receive a JWT during enrollment and can refresh it automatically.
Token Structure
Agent JWT tokens contain:
{
"agent_id": "uuid",
"generation": 5,
"iat": 1705312200,
"exp": 1705398600,
"iss": "tamandua"
}
agent_id: The unique agent identifiergeneration: Token generation number (increments on rotation)iat: Issued at timestampexp: Expiration timestampiss: Token issuer
Checking Token Status
Endpoint:GET /api/v1/agents/auth/status
curl -X GET "https://api.tamandua.io/api/v1/agents/auth/status" \
-H "Authorization: Bearer <agent_jwt_token>"
Response:
{
"valid": true,
"agent_id": "550e8400-e29b-41d4-a716-446655440000",
"generation": 5,
"issued_at": "2024-01-15T10:00:00Z",
"expires_at": "2024-01-16T10:00:00Z",
"refresh_eligible": true,
"time_to_expiry_seconds": 43200,
"percent_elapsed": 50.0,
"refresh_count": 2,
"revoked": false
}
Refreshing a Token
Endpoint:POST /api/v1/agents/auth/refresh
Tokens can be refreshed when they reach 80% of their TTL:
curl -X POST "https://api.tamandua.io/api/v1/agents/auth/refresh" \
-H "Authorization: Bearer <current_agent_jwt>"
Response:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expires_at": "2024-01-17T10:00:00Z",
"generation": 6,
"refresh_count": 3,
"message": "Token refreshed successfully"
}
Error Responses:
{
"error": "Token refresh not allowed yet",
"message": "Token must reach refresh window (typically 80% of TTL) before it can be refreshed"
}
Revoking Agent Tokens
Endpoint:POST /api/v1/agents/auth/revoke
Revoke tokens for a specific agent (requires admin authentication):
curl -X POST "https://api.tamandua.io/api/v1/agents/auth/revoke" \
-H "Authorization: Bearer <admin_api_key>" \
-H "Content-Type: application/json" \
-d '{
"agent_id": "550e8400-e29b-41d4-a716-446655440000",
"reason": "security_incident",
"all_generations": true
}'
Response:
{
"status": "revoked",
"agent_id": "550e8400-e29b-41d4-a716-446655440000",
"revoked_count": 3,
"reason": "security_incident"
}
Token Statistics
Endpoint:GET /api/v1/agents/auth/stats/:agent_id
curl -X GET "https://api.tamandua.io/api/v1/agents/auth/stats/550e8400-e29b-41d4-a716-446655440000" \
-H "Authorization: Bearer <admin_api_key>"
Scopes and Permissions
API keys and tokens can have granular permissions:
Available Scopes
| Scope | Description |
|---|---|
organization | Access to organization resources |
tenant | Multi-tenant access |
global | System-wide access (admin only) |
Available Permissions
| Permission | Description |
|---|---|
agents:read | View agent information |
agents:write | Modify agent settings |
agents:manage | Full agent control including isolation |
alerts:read | View alerts |
alerts:write | Update alert status |
events:read | Query telemetry events |
events:write | Submit events (agent only) |
response:execute | Execute response actions |
rules:read | View detection rules |
rules:write | Create/modify detection rules |
users:read | View user information |
users:manage | Manage users and permissions |
integrations:manage | Configure SIEM/SOAR integrations |
settings:manage | Modify organization settings |
Permission Check Example
When a request lacks required permissions:
{
"error": "insufficient_permissions",
"required": ["alerts:write"],
"message": "Your API key does not have permission to perform this action"
}
Session Authentication (Web Dashboard)
The web dashboard uses session-based authentication with CSRF protection.
Login
Endpoint:POST /login
curl -X POST "https://app.tamandua.io/login" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "email=user@example.com&password=yourpassword"
CSRF Token
For session-authenticated API requests, include the CSRF token:
curl -X POST "https://app.tamandua.io/api/v1/alerts/bulk" \
-H "Cookie: _tamandua_session=xxx" \
-H "X-CSRF-Token: abc123" \
-H "Content-Type: application/json" \
-d '{"alert_ids": ["id1", "id2"], "action": "resolve"}'
Web3 Wallet Authentication Preview
Tamandua includes a preview wallet-authentication flow for deployments that explicitly enable it:
Request Challenge
Endpoint:POST /wallet/challenge
curl -X POST "https://app.tamandua.io/wallet/challenge" \
-H "Content-Type: application/json" \
-d '{
"wallet_address": "0x742d35Cc6634C0532925a3b844Bc9e7595f..."
}'
Response:
{
"challenge": "Sign this message to authenticate: nonce=abc123xyz",
"nonce": "abc123xyz"
}
Wallet Login
Endpoint:POST /wallet/login
curl -X POST "https://app.tamandua.io/wallet/login" \
-H "Content-Type: application/json" \
-d '{
"wallet_address": "0x742d35Cc6634C0532925a3b844Bc9e7595f...",
"signature": "0x...",
"nonce": "abc123xyz"
}'
SSO / SAML Authentication
Enterprise SSO is supported via SAML 2.0:
SAML Metadata
Endpoint:GET /auth/sso/saml/metadata/:provider_id
SAML Login
Endpoint:GET /auth/sso/saml/login/:provider_id
SAML ACS (Assertion Consumer Service)
Endpoint:POST /auth/sso/saml/acs/:provider_id
OAuth 2.0 / OIDC
Authorize:GET /auth/sso/oauth/authorize/:provider_id
Callback: GET /auth/sso/oauth/callback/:provider_id
IP Restrictions
API keys can be restricted to specific IP addresses:
{
"allowed_ips": [
"10.0.0.0/8",
"192.168.1.100",
"2001:db8::/32"
]
}
When a request comes from a non-allowed IP:
{
"error": "ip_not_allowed",
"message": "This API key cannot be used from your IP address"
}
Security Best Practices
- Never commit API keys to version control
- Use environment variables for API keys in code
- Rotate keys regularly (every 90 days recommended)
- Use IP restrictions for production integrations
- Set expiration dates on keys when possible
- Use minimal permissions - only request scopes you need
- Monitor key usage via the dashboard
- Revoke compromised keys immediately
Rate Limiting by Auth Type
| Auth Type | Rate Limit | Notes |
|---|---|---|
| API Key | Per-key limits | Configurable per key |
| JWT (Agent) | 100/min | Fixed for agent stability |
| Session | 1000/min | Per user session |
Error Codes
| Error | HTTP Code | Description |
|---|---|---|
missing_token | 401 | No authentication provided |
invalid_token | 401 | Token is malformed or invalid |
token_expired | 401 | Token has expired |
token_revoked | 401 | Token has been revoked |
generation_mismatch | 401 | A newer token generation exists |
ip_not_allowed | 403 | Request IP not in allowlist |
insufficient_permissions | 403 | Missing required permissions |
key_deactivated | 401 | API key has been deactivated |