THINKHX

API keys

A key is what authenticates a call and what scopes it. This resource manages the project's keys, including the one making the request. The raw secret is never stored — only its SHA-256 hash — so a key is shown in full exactly once, in the response that creates it.

To create your first key from the workspace instead, see API keys.

Endpoints

MethodPathScope
GET/v1/keykey:read
GET/v1/key/currentkey:read
GET/v1/key/<key_id>key:read
POST/v1/keykey:write
DELETE/v1/key/<key_id>key:write

<key_id> is a key identifier, prefixed papi_. current is a reserved word in that position and resolves to the key the request is authenticated with.

The API key object

FieldTypeDescription
idstringThe key identifier, prefixed papi_.
objectstringAlways api_key.
namestringThe key's name.
key_previewstringThe literal prefix sk-project-... followed by the last four characters of the secret, for recognising it.
scopearrayThe scopes the key grants. See below.
statusstringOnly an activated key authenticates.
expires_atintegerWhen the key stops working, in Unix seconds, or null for a key that never expires.
last_used_atintegerWhen the key last authenticated a call, or null.
created_bystringThe consumer who created the key.
created_atintegerCreation time, in Unix seconds.
updated_atintegerLast change, in Unix seconds.

The secret itself appears in no read response. key_preview is the only part of it the API will show you again.

List the keys

GET /v1/key returns the project's keys, newest first.

curl
curl https://api.thinkhx.com/v1/key \
  -H "Authorization: Bearer sk-project-YOUR_KEY"
json
{
  "code": 200,
  "title": "OK",
  "response": {
    "object": "list",
    "data": [
      {
        "id": "papi_4e07c1b8a35df926104c",
        "object": "api_key",
        "name": "Production backend",
        "key_preview": "sk-project-...a7e1",
        "scope": ["reasoning:*", "app:read", "usage:read"],
        "status": "activated",
        "expires_at": null,
        "last_used_at": 1754209200,
        "created_by": "cons_8e2b45a10c9df7631b4a",
        "created_at": 1751414400,
        "updated_at": 1754209200
      }
    ],
    "total": 1
  }
}

Read the calling key

GET /v1/key/current is the quickest way to find out what your key may do, without knowing its identifier.

curl
curl https://api.thinkhx.com/v1/key/current \
  -H "Authorization: Bearer sk-project-YOUR_KEY"

A key of another project gives 404 and API key not found.

Create a key

POST /v1/key mints a new key for the same project.

ParameterTypeRequiredDescription
namestringyesA name to recognise the key by.
scopearraynoThe scopes to grant. Defaults to ["*"], which is refused unless your own key holds *. See below.
expires_atintegernoWhen the key should stop working, in Unix seconds. Omit or send 0 for a key that never expires.
curl
curl -X POST https://api.thinkhx.com/v1/key \
  -H "Authorization: Bearer sk-project-YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Nightly batch",
    "scope": ["reasoning:read", "reasoning:write", "usage:read"]
  }'
json
{
  "code": 201,
  "title": "Created",
  "response": {
    "id": "papi_b6294fc0e178ad35c9b2",
    "object": "api_key",
    "name": "Nightly batch",
    "key": "sk-project-7Qd1xR0mZ8pKvT3sLb...",
    "key_preview": "sk-project-...Lb92",
    "scope": ["reasoning:read", "reasoning:write", "usage:read"],
    "status": "activated",
    "expires_at": null,
    "last_used_at": null,
    "created_by": "cons_8e2b45a10c9df7631b4a",
    "created_at": 1754209800,
    "updated_at": 1754209800
  }
}

Importantkey is present in this one response and nowhere else. Store it before you discard the response. A lost secret cannot be recovered, only replaced by creating another key.

A key can never grant more than the key that created it. Asking for a scope the caller does not itself hold is refused rather than silently trimmed.

Important — Nothing is narrowed for you, and that includes the default. Because omitting scope means ["*"], a key that does not itself hold * must send an explicit scope array: leaving the parameter out is a 403, even though it is not a required field.

CodeMessageCause
422name is required.No name was sent.
400scope must be an array.scope was sent as a string or an object.
403Cannot create a key with wider scope than the calling key.A requested scope is outside the caller's own.

Revoke a key

DELETE /v1/key/<key_id> revokes the key immediately. Any call made with it afterwards answers 403 and The API key doesn't have permissions to perform the request. — the same answer an unknown key gets. 401 is reserved for a key that had an expiry and reached it. See Errors.

curl
curl -X DELETE https://api.thinkhx.com/v1/key/papi_b6294fc0e178ad35c9b2 \
  -H "Authorization: Bearer sk-project-YOUR_KEY"
json
{
  "code": 200,
  "title": "OK",
  "response": {
    "deleted": true,
    "id": "papi_b6294fc0e178ad35c9b2"
  }
}

The key you are calling with is refused with 422 and Cannot revoke the API key currently in use., so a rotation cannot lock you out halfway. Create the replacement, move your traffic onto it, then revoke the old key with the new one.

Need help? Contact Support.