.md raw

/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