/v1/keys — key administration
Admin only. Send the deployment's INGEST_TOKEN as x-admin-token. The plaintext key is returned exactly once, at creation; only its SHA-256 hash is stored.
There is a console for all of this at /admin — sign in with Discord (approved accounts only) and create, name, disable and delete keys in a browser, with each key's calls and spend for the day beside it. Naming a key's project there is what creates that project on the cost tracker. The endpoints below are the same operations for scripts, and still use the
INGEST_TOKEN.
POST /v1/keys — mint a key
curl -X POST "https://tikdata.io/v1/keys" \
-H "x-admin-token: $INGEST_TOKEN" \
-H "content-type: application/json" \
-d '{"label":"market bubble site","project":"market-bubble"}'
Body
| field | required | notes |
|---|---|---|
label |
yes | human name, shown in listings |
project |
yes | attribution bucket; every call this key makes is counted under it |
scopes |
no | array of upstream path prefixes, e.g. ["/api/v1/tiktok/"]; restricts /v1/raw |
Response — 201
{
"key": "thr_live_a2d5c7e1f3b9d4c6a8e0f2b4d6c8a0e2f4b6d8c0a2e4f6b8d0c2e4f6",
"warning": "Store this now — it is hashed on the server and cannot be shown again.",
"record": {
"id": "rk_1630e4b68fd5",
"label": "market bubble site",
"project": "market-bubble",
"enabled": true,
"scopes": null,
"prefix": "thr_live_a2d5c7",
"createdAt": "2026-09-07T21:16:26.000Z",
"lastUsedAt": null,
"requestCount": 0
}
}
prefix is the first 15 characters of the key, kept so a key can be recognized in logs without storing it.
GET /v1/keys — list
curl "https://tikdata.io/v1/keys" -H "x-admin-token: $INGEST_TOKEN"
{ "keys": [ { "id": "rk_…", "label": "…", "project": "…", "enabled": true, "scopes": null,
"prefix": "thr_live_…", "createdAt": "…", "lastUsedAt": "…", "requestCount": 0 } ] }
Newest first. Plaintext keys are never included.
PATCH /v1/keys — enable / disable
curl -X PATCH "https://tikdata.io/v1/keys" \
-H "x-admin-token: $INGEST_TOKEN" \
-H "content-type: application/json" \
-d '{"id":"rk_1630e4b68fd5","enabled":false}'
{ "id": "rk_1630e4b68fd5", "enabled": false }
A disabled key gets 401 on its next call. Disabling is instant and reversible; prefer it to deleting when a consumer may come back.
DELETE /v1/keys?id=… — remove
curl -X DELETE "https://tikdata.io/v1/keys?id=rk_1630e4b68fd5" -H "x-admin-token: $INGEST_TOKEN"
{ "deleted": "rk_1630e4b68fd5" }
Per-key usage rows survive deletion — project is denormalized onto them — so history in /v1/usage?day= stays intact.
Errors
| status | body |
|---|---|
| 401 | {"error":"admin token required","hint":"send: x-admin-token: <INGEST_TOKEN>"} |
| 400 | {"error":"label and project are required"} |
| 400 | {"error":"id and enabled are required"} (PATCH) |
| 400 | {"error":"id query param is required"} (DELETE) |
| 404 | {"error":"no such key"} |
| 500 | {"error":"could not create key (no database)"} — DATABASE_URL unset |