Authentication
Open as markdownFor AI agents: the docs index is at /llms.txt, and every page is also served as markdown at its URL plus .md.
Every operation under /v1 needs an API key sent as a bearer token. Keys start with cm_live_. The public endpoints /health, /plans, /openapi.json and /llms.txt need no key.
Send your key#
Put the key in the Authorization header.
curl YOUR_API_BASE_URL/v1/account \
-H "Authorization: Bearer $COLDMEETINGS_API_KEY"const res = await fetch('YOUR_API_BASE_URL/v1/account', {
headers: { Authorization: `Bearer ${process.env.COLDMEETINGS_API_KEY}` },
});import os
import requests
res = requests.get(
"YOUR_API_BASE_URL/v1/account",
headers={"Authorization": f"Bearer {os.environ['COLDMEETINGS_API_KEY']}"},
)The API also accepts the key in an X-API-Key header for clients that cannot set Authorization. If both are present, the bearer token is used.
What a key looks like#
- The prefix
cm_live_followed by 43 letters and digits, made from 32 random bytes. - The first 12 characters after the prefix are the key's public id. That id appears in
GET /v1/accountand in logs. The rest is secret.
How keys are stored#
- Only the SHA 256 hash of the whole key and the public id are stored. A leaked database does not leak usable keys.
- The full key is shown once, when it is created. It cannot be recovered. If you lose it, the operator revokes it and issues a new one.
- A presented key is compared with the stored hash in constant time.
- A revoked key stops working at once. It answers the same
unauthorizederror as a key that never existed, so an error never tells a guesser which keys exist.
Keep keys safe#
- Use keys on a server. Never put one in a browser, a mobile app or a public repository.
- Keep one key per system so you can revoke one without stopping the others.
- Load the key from an environment variable or a secrets manager.
Accounts and isolation#
A key belongs to one account. It can read and change only that account. Asking for a campaign, domain or reply that belongs to another account answers unknown_product, the same as an id that does not exist.
If authentication fails#
A missing, malformed, revoked or unknown key answers HTTP 401 with the unauthorized code and a WWW-Authenticate: Bearer header. See Errors. Requests that fail authentication are not counted against the rate limit.
{
"error": {
"code": "unauthorized",
"message": "The API key is missing, malformed, revoked or unknown.",
"fix": "Send a valid key in the Authorization header as \"Bearer <key>\". If the key was revoked, create a new one and retry.",
"docs_url": "/docs/errors#unauthorized",
"retryable": false,
"request_id": "req_Qx7RtVw3ZbN1pEs9fKd2Lm"
}
}