Authentication
ComplianceLayer uses API keys for authentication. Nearly every API request must include a valid API key. API keys are prefixed with cl_, and each account has exactly one.
Getting Your API Key
To find your API key:
- Sign in at compliancelayer.net/login
- Open Settings and select the API Keys tab
- Copy the key — it starts with
cl_
If you created your account through the API, POST /v1/auth/signup already returned the key in the api_key field of its response. You can also read it at any time from GET /v1/auth/me.
Using API Keys
Include your API key in the Authorization header with the Bearer scheme. Two alternatives are also accepted: the X-API-Key header, and a bare key in Authorization without the Bearer prefix. Prefer Bearer — the alternatives exist for gateways and clients that can't set a standard Authorization header.
curl -X POST "https://api.compliancelayer.net/v1/scan" \
-H "Authorization: Bearer cl_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"domain": "example.com"
}'
# Equivalent, using the X-API-Key header instead
curl -X POST "https://api.compliancelayer.net/v1/scan" \
-H "X-API-Key: cl_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"domain": "example.com"
}'Authentication Errors
If authentication fails you'll receive 401 Unauthorized with a single detail field. A missing key and an invalid key produce an identical response — the API deliberately does not distinguish them, so don't branch on the message to work out whether a key was sent.
HTTP/1.1 401 Unauthorized
{
"detail": "Invalid or missing authentication"
}Both strings mean the same thing. "Authentication required" comes from the request middleware and is what you'll see when a state-changing request such as POST /v1/scan arrives with no credentials at all; "Invalid or missing authentication" comes from the endpoint itself. Handle 401 by status code, not by message text.
API Key Management
Each account has exactly one API key. There are no named keys, no per-environment keys, and no separate create, list, or revoke operations. The only key operation is regeneration.
Regenerating Your Key
POST /v1/auth/api-key/regenerate issues a new key and returns it. Authenticate the request with your current key or a session token.
curl -X POST "https://api.compliancelayer.net/v1/auth/api-key/regenerate" \
-H "Authorization: Bearer cl_YOUR_CURRENT_API_KEY"
# Response
{
"api_key": "cl_YOUR_NEW_API_KEY",
"created_at": "2026-07-29T17:05:47Z"
}401 immediately.Planning the Cutover
Because the swap is instantaneous, keep the window between regenerating and redeploying as short as you can:
- Make sure every place that holds the key is known and reachable — secret stores, CI variables, running services, scheduled jobs.
- Stage the deploy or secret update so it's ready to trigger before you regenerate.
- Regenerate, then immediately push the new key everywhere and restart anything that reads it at startup.
- Verify with a cheap authenticated call such as
GET /v1/auth/me.
Expect a brief period of failed requests during the swap. If a key is compromised, regenerate straight away and accept the interruption — a leaked key is the larger problem.
JWT Tokens (Dashboard Access)
In addition to API keys, ComplianceLayer uses JWT tokens for dashboard authentication. These are managed automatically when you sign in through the web interface.
Signing In
curl -X POST "https://api.compliancelayer.net/v1/auth/login" \
-H "Content-Type: application/json" \
-d '{
"email": "team@company.com",
"password": "your_password"
}'
# Response
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "bearer",
"expires_in": 86400,
"csrf_token": "..."
}The response contains only these token fields — there is no user object. The token itself is in access_token, and expires_in is in seconds (86,400 = 24 hours). For account details, call GET /v1/auth/me, which returns your id, email, plan, API key, scan usage, and limits.
Using JWT Tokens
JWT tokens can be used in place of API keys for all API requests. Include the token in the Authorization header:
curl "https://api.compliancelayer.net/v1/auth/me" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."JWT tokens expire after 24 hours. For server-to-server communication, use API keys instead.
Security Best Practices
1. Use Environment Variables
Never hardcode API keys in your source code. Use environment variables:
# .env
COMPLIANCELAYER_API_KEY=cl_your_api_key_here2. Use Secrets Management
For production deployments, use a secrets management service:
- AWS Secrets Manager — For AWS deployments
- HashiCorp Vault — For on-premises or multi-cloud
- Azure Key Vault — For Azure deployments
- Google Secret Manager — For GCP deployments
A secrets manager also makes regeneration far less painful: one update propagates to every consumer instead of a hunt through deploy configs.
3. Separate Environments With Separate Accounts
Since an account has a single key, the only way to isolate environments is to use a separate account for each:
- A free-tier account for development and testing
- A separate account for staging
- A dedicated account for production
This limits the blast radius if a key is compromised, and it means regenerating a development key never interrupts production.
4. Monitor API Usage
Review your usage regularly, either in the dashboard or through the usage endpoints (GET /v1/usage/summary, /v1/usage/limits, /v1/usage/history, /v1/usage/by-endpoint):
- Check for unexpected spikes in requests
- Watch which endpoints are consuming your scan quota
- Investigate bursts of failed authentication attempts
5. Regenerate When It Matters
Because regeneration causes a brief outage, tie it to events rather than to a fixed calendar:
- Immediately if you suspect the key has leaked
- When team members leave who had access to it
- After any exposure in logs, a screenshot, or a shared terminal
Troubleshooting
401 Unauthorized
- Check that your API key starts with
cl_ - Ensure the
Authorization(orX-API-Key) header is actually being sent — some proxies strip it - Verify the key hasn't been superseded by a regeneration; the previous key stops working instantly
- Remember that a missing key and an invalid key return the same message
403 Forbidden
- Your account may be disabled (
"Account is disabled") - The endpoint may be gated to a higher plan — the Zapier integration is, and returns messages such as
"Zapier integration requires the Pro plan or higher. Upgrade at /billing/checkout". Webhooks and PDF reports are available on every plan and never produce this error. The plan named in these messages is derived from the plan definitions and can change, so detect the condition from the403and the endpoint you called rather than by matching the text. - Your subscription may be inactive (
"Subscription is not active")
Note that running out of scan quota is not a 403 — it returns 429.
429 Too Many Requests
- You've either exceeded your request rate limit or exhausted your monthly scan quota — both use this status
- Rate-limit responses include a
retry_afterfield; wait that long and retry - A
Retry-Afterheader is only guaranteed on the public scanner path, so readretry_afterfrom the body rather than relying on the header - A quota response carries neither, and retrying won't help until the next billing period — upgrade your plan or wait
The error handling guide shows how to tell the two apart in code.