Authentication
Authenticate with an API key
Every request to the public API carries an X-Api-Key header. There is no OAuth flow and no bearer token exchange - the key is the credential.
Create a key
Keys are created per workspace, under Settings at /workspaces/{workspaceId}/api-keys. The key's value is shown once at creation - store it as a secret, since there is no way to retrieve it again later. A key only ever authenticates requests for the workspace it was created in; it cannot act on any other workspace, even one you also own. Go to your workspaces to open one and create a key there.
Send the header
curl https://api.communiqueue.com/api/v1/notifications/send \
-H "X-Api-Key: cq_live_..." \
-H "Content-Type: application/json" \
-d '{
"tenantId": "<your workspace id>",
"templateId": "<your template id>",
"tags": [{ "key": "firstName", "value": "Ada" }]
}'What can go wrong
| Code | Status | Meaning |
|---|---|---|
| api_keys.missing | 401 | The request had no X-Api-Key header at all. |
| api_keys.invalid | 401 | The header was present, but the key doesn't resolve, or it has been revoked or has expired. |
| api_keys.tenant_mismatch | 403 | The key is valid, but it belongs to a different workspace than the tenantId in the request body. |
Check a key without sending anything
GET /api/v1/api-keys/validate checks a key without queuing a notification. It is meant for a setup screen or a health check, so it does not 401 on a bad key the way the send and preview endpoints do - it responds 200 with isValid: false and every other field null. The only way this endpoint returns 401 is a missing header entirely (api_keys.missing). If your integration expects a 401 for a bad key here, it will never take the false branch.
Request
curl https://api.communiqueue.com/api/v1/api-keys/validate \
-H "X-Api-Key: cq_live_..."Response for a bad key - 200 OK
{
"isValid": false,
"tenantId": null,
"apiKeyId": null,
"name": null,
"status": null,
"createdAt": null,
"lastUsedAt": null,
"expiresAt": null,
"revokedAt": null
}