ChirpieDocs
API Reference

API Keys

Create, list, and revoke API keys programmatically, and narrow a key with scopes.

Create a Key

POST /api/v1/keys
Authorization: Bearer chirpie_sk_YOUR_KEY
Content-Type: application/json

Request Body

FieldTypeRequiredDescription
namestringNoKey name, 100 characters or less. Empty, whitespace or omitted means "Default"
scopesstring[]NoWhat the new key may do. Omit it for a key that can do exactly what the key making the request can do. An empty array is refused. See Scopes

Allowed values for scopes: posts:read, posts:write, accounts:read, accounts:write, analytics:read, comments:read, comments:write, media:write, keys:write.

This endpoint needs keys:write, and so do List and Revoke. There is deliberately no keys:read: the key list is the inventory of your account's credentials, and a key meant only to post has no business enumerating its siblings.

A key can never grant a scope it does not itself hold. Minting with a narrow key and asking for something outside it returns 403 insufficient_scope naming the scope, so a restricted key cannot quietly widen itself. Leaving scopes out is not a way around that: the new key inherits the caller's own scopes, so a scoped key mints a copy of itself and only a full-access key (or the dashboard) mints a key that can grant anything.

Response 201 Created

{
  "data": {
    "key": "chirpie_sk_aBcDeFgHiJkLmNoPqRsTuVwXyZ0123456789ab",
    "prefix": "chirpie_sk_aBcDeFgH",
    "name": "Production",
    "scopes": ["posts:write", "media:write"],
    "expires_at": "2026-06-21T00:00:00.000Z",
    "message": "Save this key securely. It will not be shown again."
  }
}
FieldDescription
keyThe full key. Returned once, here, and never again
prefixThe leading characters of the key, used to identify it in listings
scopesThe scopes the key holds, or null for full access
expires_atKeys expire 90 days after creation. Create a replacement before then

The full key is returned only once in this response. Store it immediately. Chirpie stores a SHA-256 hash, so the raw key cannot be retrieved later.

Limits

Maximum 25 active keys per account. Creating a 26th returns 400 bad_request: API key limit reached (25). Revoke unused keys before creating new ones.


List Keys

GET /api/v1/keys
Authorization: Bearer chirpie_sk_YOUR_KEY

Response 200 OK

{
  "data": [
    {
      "id": "key-uuid-here",
      "name": "Production",
      "key_prefix": "chirpie_sk_aBcDeFgH",
      "scopes": ["posts:write", "media:write"],
      "last_used_at": "2026-03-23T10:00:00.000Z",
      "expires_at": "2026-05-30T00:00:00.000Z",
      "created_at": "2026-03-01T00:00:00.000Z"
    }
  ]
}

Only key prefixes are returned, never the full key. Revoked keys are not listed.

scopes is on every key in the listing. It is null on a key with full access, which is what every key minted before scopes existed carries, and what a key created without scopes by the dashboard or by another full-access key carries. A key created without scopes by a narrowed key carries a copy of that key's list instead.


Revoke a Key

DELETE /api/v1/keys?id=KEY_UUID
Authorization: Bearer chirpie_sk_YOUR_KEY

Query Parameters

ParameterTypeRequiredDescription
idstring (UUID)YesThe key ID to revoke

Response 200 OK

{
  "data": {
    "id": "key-uuid-here",
    "revoked": true
  }
}

Revoked keys stop working immediately. This action cannot be undone.


Error Responses

StatusCodeCondition
400bad_requestA scopes value that is not a scope, an empty scopes array, a name over 100 characters, or the 25-key limit
401unauthorizedInvalid, expired or revoked API key
403insufficient_scopeThe key does not hold keys:write, or is trying to grant a scope it does not itself hold. The message names the scope
404not_foundOn revoke: no key with that id on your account

From the CLI, SDK and MCP

chirpie keys create --name "Publishing bot" --scope posts:write --scope media:write
chirpie keys         # prints each key's scopes, or "all" for full access
await chirpie.createKey({ name: "Publishing bot", scopes: ["posts:write", "media:write"] });
await chirpie.createKey("Everything");   // a bare name still works, and copies this key's scopes

MCP: chirpie_create_key takes name and an optional scopes array.

On this page