Skip to main content

API Authentication, Key Rotation and Errors

Telemetr.io authenticates REST requests with an API key. This guide covers the request header, key rotation and how to respond to access, billing and request errors.

Authenticate​

Send your selected API key in x-api-key on every request. Obtain the current key from @telemetrio_api_bot using /api_key.

curl --fail-with-body "https://api.tlmtr.io/v1/usage/info" \
-H "x-api-key: $TELEMETRIO_API_KEY"

Change a key​

Send /api_key, choose Credits API key or Subscription API key in the separate rotation prompt, and confirm. Cancelling leaves the current key unchanged. Another /api_key command only retrieves the current key.

After a confirmed change, update the secret in every integration that uses that key. The old key may remain accepted for up to 60 seconds. Your plan, balance, billing period and used allowances are preserved. If delivery of the new key is interrupted, use /api_key to retrieve the current secret.

Keep keys in backend secret storage. Never log them or include them in browser bundles. Contact support if you cannot access the bot to change an exposed key.

Error bodies​

Use the HTTP status and the documented body for that operation. Application errors return JSON with a human-readable message. Additional fields depend on the error; existing numeric fields remain at the top level.

Ordinary errors return a human-readable message:

{"message": "Channel not found"}

Insufficient credits (402, code: insufficient_credits) use integer milli-credits (1000 mc = 1 credit):

{
"code": "insufficient_credits",
"message": "Insufficient credits. Top up your credit balance and retry.",
"cost_known": true,
"total_cost_mc": 801,
"available_mc": 500,
"shortfall_mc": 301
}

When cost_known is true, shortfall_mc is the amount missing from the available balance. Some billing denials report only the balance, without the rejected request's price. In that case the response explicitly marks the cost as unknown:

{
"code": "insufficient_credits",
"message": "Insufficient credits. Top up your credit balance and retry. The exact request cost is unavailable.",
"cost_known": false,
"total_cost_mc": 0,
"available_mc": 0,
"shortfall_mc": 0
}

Here available_mc remains the reported balance. The zero values in total_cost_mc and shortfall_mc are compatibility placeholders, not a free request or a zero deficit. Check cost_known before using these amounts; branch on HTTP 402 or insufficient_credits to recognize the error.

Quota exhaustion (426, code: quota_reached) reports the exhausted counter:

{
"code": "quota_reached",
"message": "The requests quota has been reached. Wait for the quota to reset or upgrade your plan.",
"name": "requests",
"used": 1000,
"limit": 1000
}

Snapshot errors have a stable code and may contain an object in details:

{"code": "SNAPSHOT_TOO_LARGE", "message": "Snapshot is too large", "details": {"max_channels": "50000", "matched_count": "50001"}}

Messages are illustrative; branch on status and stable codes instead of matching message text. A reported matching count can be a lower bound when the scan stops at the limit.

Invalid request parameters or bodies, unknown API routes, unsupported HTTP methods, and request rate limits also return JSON with code and message. For example:

{"code": "not_found", "message": "The requested API endpoint or resource was not found."}

HEAD responses have no body. Responses generated outside the application, such as proxy errors, may use a different format.

Choose the right action​

StatusMeaningAction
400Invalid input; some endpoints also use it for disabled post search or verified-only restrictionsInspect the message and check the relevant input or access setting
401Missing or invalid credentialCheck the selected key and header
402Insufficient available creditsTop up credits; use shortfall_mc only when cost_known is true
403Feature access is not enabledCheck the plan or separately configured access
404A resource read cannot find an accessible resourceVerify the ID and account; snapshot deletions use a result flag instead
405Unsupported HTTP methodUse a method listed in the Allow header
410A retained snapshot or diff has expiredUse an active resource
412Key/subscription is inactiveRestore the appropriate active access
422Invalid request body, or snapshot/current matching set is too largeInspect code and message; correct the body or narrow the filters
426A usage allowance is exhaustedWait for renewal or change the allowance
429Request rate, active resource capacity or concurrent operation conflictInspect the error, Retry-After and x-ratelimit-after
503A dependency is temporarily unavailableRetry eligible operations with backoff

The per-key rate limiter currently allows a sustained 20 requests/second with a burst allowance of 50. Rate-limit errors use code: rate_limit_exceeded and include x-ratelimit-after (seconds), x-ratelimit-limit, and x-ratelimit-remaining. Separate resource and concurrency limits also apply to snapshots.

Temporary snapshot conflicts such as SNAPSHOT_CREATION_IN_PROGRESS, DIFF_CREATION_IN_PROGRESS and SNAPSHOT_MUTATION_IN_PROGRESS can be retried after Retry-After. For SNAPSHOT_LIMIT_REACHED or DIFF_LIMIT_REACHED, release capacity or wait for expiry; a rapid retry does not free storage.

For transient failures on reads, use bounded exponential backoff with jitter. Creating a channel, snapshot or diff changes server state: an uncertain timeout does not prove that creation failed. Check the existing resource/list result before repeating a creation request. See snapshot retries.