Authentication
All Noxys API endpoints (except /healthz, /readyz, /metrics, and /auth/login) require authentication via a JWT Bearer token.
Getting a Token
Login with Email & Password
Endpoint: POST /api/v1/auth/login
curl -X POST https://api.noxys.cloud/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "alice@acme.fr",
"password": "your-password"
}'
Response (200 OK):
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMTAiLCJlbWFpbCI6ImFsaWNlQGFjbWUuZnIiLCJ0ZW5hbnRfaWQiOiIwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDEiLCJyb2xlIjoiYWRtaW4iLCJpYXQiOjE3NDUxNjU5MzEsImV4cCI6MTc0NTI1MjMzMX0...",
"user": {
"id": "00000000-0000-0000-0000-000000000010",
"email": "alice@acme.fr",
"display_name": "Alice Martin",
"role": "admin",
"tenant_id": "00000000-0000-0000-0000-000000000001"
}
}
Token Validity: 24 hours from issue time
Security:
- Store the token securely (environment variables, secure vaults)
- Never commit tokens to version control
- Rotate tokens regularly
- Use HTTPS for all requests
Rate Limiting on Login
Login endpoint is rate-limited to 5 requests per minute per IP address. This prevents brute-force attacks.
If exceeded:
HTTP 429 Too Many Requests
{
"error": "Too many login attempts. Please try again in a few minutes."
}
Using a Token
Include the token in every subsequent request via the Authorization header:
curl https://api.noxys.cloud/api/v1/interactions \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
Token Format
JWT tokens have three parts separated by dots: header.payload.signature
Example Decoded Payload:
{
"sub": "00000000-0000-0000-0000-000000000010",
"email": "alice@acme.fr",
"tenant_id": "00000000-0000-0000-0000-000000000001",
"role": "admin",
"iat": 1745165931,
"exp": 1745252331
}
Claims:
| Claim | Type | Description |
|---|---|---|
sub | UUID | User ID |
email | String | User email address |
tenant_id | UUID | Organization/tenant ID |
role | String | User role (admin or viewer) |
iat | Unix timestamp | Token issued-at time |
exp | Unix timestamp | Token expiration time (24 hours after iat) |
Token Refresh
Tokens expire after 24 hours. When a token expires, you'll receive a 401 Unauthorized response:
HTTP 401 Unauthorized
{
"error": "Token expired"
}
To refresh: Call /auth/login again with your email and password to get a new token.
For automation, consider:
- Storing credentials securely in environment variables
- Calling login once per day before using the API
- Implementing automatic retry-on-401 logic in your client
Example: Python Auto-Refresh
import requests
import os
from datetime import datetime, timedelta
class NoxysClient:
def __init__(self, email: str, password: str):
self.email = email
self.password = password
self.token = None
self.token_expiry = None
self.base_url = "https://api.noxys.cloud/api/v1"
def _login(self):
"""Get a new token."""
response = requests.post(
f"{self.base_url}/auth/login",
json={"email": self.email, "password": self.password}
)
response.raise_for_status()
data = response.json()
self.token = data["token"]
# Token is valid for 24 hours
self.token_expiry = datetime.utcnow() + timedelta(hours=24)
def _ensure_valid_token(self):
"""Refresh token if expired."""
if not self.token or datetime.utcnow() >= self.token_expiry:
self._login()
def get_interactions(self, limit=50):
"""List interactions."""
self._ensure_valid_token()
response = requests.get(
f"{self.base_url}/interactions?limit={limit}",
headers={"Authorization": f"Bearer {self.token}"}
)
response.raise_for_status()
return response.json()
# Usage
client = NoxysClient("alice@acme.fr", "password")
interactions = client.get_interactions()
Role-Based Access Control
Tokens include a role claim that determines permissions:
Admin Role
Full access to all endpoints:
- Create, read, update, delete policies
- Manage users (invite, update role, delete)
- View audit log
- Access admin-only endpoints (e.g.,
/classification/classify) - View all interactions and alerts
- Export data
Viewer Role
Read-only access:
- View dashboard and statistics
- View interactions and alerts
- View policies (read-only)
- Cannot modify policies, users, or settings
Attempting a privileged action as a viewer:
HTTP 403 Forbidden
{
"error": "Insufficient permissions. This action requires admin role."
}
OAuth 2.0 (Coming Soon)
We're implementing OAuth 2.0 for delegated authentication and service-to-service flows in Q2 2026.
Expected flow:
# 1. Redirect user to authorization endpoint
GET https://api.noxys.cloud/oauth/authorize \
?client_id=abc123 \
&response_type=code \
&redirect_uri=https://your-app.com/callback \
&scope=read:interactions write:policies
# 2. User authenticates and grants permission
# Receives authorization code at redirect_uri
# 3. Exchange code for token
POST https://api.noxys.cloud/oauth/token \
-H "Content-Type: application/json" \
-d '{
"grant_type": "authorization_code",
"code": "auth-code-from-step-2",
"client_id": "abc123",
"client_secret": "secret123"
}'
# 4. Use access token for API calls
Authorization: Bearer access_token_value
Scopes (in development):
read:interactions— List and view interactionswrite:policies— Create and modify policiesread:users— View user listadmin:all— Full admin access
Rate Limiting
Beyond the login endpoint, all API calls are rate-limited:
Limits:
- 100 requests/minute per IP address (backstop)
- 1,000 requests/minute per tenant (primary limit)
When exceeded (HTTP 429):
HTTP 429 Too Many Requests
Content-Type: application/json
Retry-After: 60
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1745252400
{
"error": "Rate limit exceeded. Please retry after 60 seconds."
}
Response Headers:
| Header | Description |
|---|---|
Retry-After | Seconds to wait before retrying |
X-RateLimit-Limit | Request limit for this endpoint |
X-RateLimit-Remaining | Requests remaining in current window |
X-RateLimit-Reset | Unix timestamp when limit resets |
Rate Limiting Strategy
To avoid hitting limits:
- Batch operations: Use
/interactions/batchinstead of creating one at a time - Pagination: Use
limitparameter to fetch many items in one request - Exponential backoff: Wait longer before each retry
- Contact us: For higher limits, email support@noxys.eu
Example: Exponential Backoff in Python
import requests
import time
def api_call_with_retry(url, headers, max_retries=3):
for attempt in range(max_retries):
response = requests.get(url, headers=headers)
if response.status_code == 429:
wait_time = int(response.headers.get('Retry-After', 60))
print(f"Rate limited. Waiting {wait_time} seconds...")
time.sleep(wait_time)
continue
return response
raise Exception("Max retries exceeded")
Security Best Practices
- Always use HTTPS — Never send tokens over plain HTTP
- Store tokens securely:
- Use environment variables for credentials
- Use secret management tools (HashiCorp Vault, AWS Secrets Manager)
- Never hardcode in code
- Rotate credentials regularly — Change passwords every 90 days
- Use strong passwords — At least 12 characters, mixed case and numbers
- Monitor token usage — Check audit logs for unauthorized access
- Set up IP whitelisting — Restrict API calls to known IPs (contact support)
- Implement API key rotation — If using API keys, rotate every 90 days
Troubleshooting
"Token expired"
HTTP 401 Unauthorized
{
"error": "Token expired"
}
Solution: Call /auth/login again to get a new token.
"Invalid token"
HTTP 401 Unauthorized
{
"error": "Invalid token"
}
Solutions:
- Verify token is included in
Authorization: Bearer <token>header - Check token hasn't been tampered with
- Ensure token has correct format (three dot-separated parts)
"Insufficient permissions"
HTTP 403 Forbidden
{
"error": "Insufficient permissions"
}
Solution: Contact your admin to upgrade your role from viewer to admin.
"Too many login attempts"
HTTP 429 Too Many Requests
{
"error": "Too many login attempts. Please try again in a few minutes."
}
Solution: Wait at least 60 seconds before retrying. Check for scripts making accidental login loops.
What's Next?
- Events API — Create and list interactions
- Policies API — Manage DLP policies
- Webhooks — Receive real-time events