Skip to content

Public Keys API

A public key is a key your organization holds the private half of. A channel’s transmit step encrypts a report to it before delivery, and a brief’s Cloak Mode encrypts a report in the reporter’s browser before it is sent; in both cases only the holder of the private key can read the report. Disclose Bot never holds a private key. This page documents the public key resource. Everything here is also in the Platform API reference.

Requests are JSON:API over HTTPS against https://api.disclosebot.io/v1 with a service account bearer token, as described in the API quickstart.

Terminal window
curl https://api.disclosebot.io/v1/public_keys \
-H "Authorization: Bearer disclosebot_svc_xxxxxxxx"
AttributeTypeMeaning
namestringA label for the key.
short_descriptionstring, nullableOptional notes.
public_keystringThe key material (below). Surrounding whitespace is removed on save.
retiredbooleantrue when the key is retired (below).
retired_atdate-time, nullableWhen it was retired.
created_at, updated_atdate-timeTimestamps.

Relationship: organization.

Encryption uses an X25519 key (NaCl box, the format of libsodium and tweetnacl), stored as the base64 encoding of its 32 raw bytes, for example 3FcN9hN1m2yVZs6h5N7C1qfq8Rr2Q1pS5xH0u8wZ2mE=. Only an X25519 key can be chosen for a transmit step or for Cloak Mode; committing a workflow whose transmit step names another kind of key is refused.

A key of another kind, such as a PGP public key block, can be stored for reference (Disclose Bot records the PGP key a security page publishes this way). It cannot be used for encryption.

When you rotate keys, retire the old one instead of deleting it. A retired key:

  • is no longer offered for transmit steps or Cloak Mode, and a workflow commit that names it is refused;
  • keeps its link to every report and encrypted body encrypted to it, so deliveries of those bodies and the history of those reports stay intact.

Retiring is refused while the key is in use for new encryption: a brief uses it for Cloak Mode, or an enabled channel’s running workflow has a transmit step that encrypts to it. Move those to the new key first. A retired key can be reinstated.

Deleting a key that reports or bodies were encrypted to would remove the record of which key opens them, and a brief in Cloak Mode would be left without a key. Deleting is therefore refused while encrypted bodies, cloaked reports, or a brief in Cloak Mode reference the key; retire it instead. For the same reason the key material of a used key cannot be changed: add a new key.

GET /v1/public_keys

Newest first. Filters: q[name_cont], q[retired_at_null] (true for keys in use, false for retired keys), and q[s] to sort (for example name asc). Pagination: page[number] and page[size] (at most 30); the response carries meta.pagination and links (see Pagination).

Terminal window
curl "https://api.disclosebot.io/v1/public_keys?q[retired_at_null]=true" \
-H "Authorization: Bearer disclosebot_svc_xxxxxxxx"
200
{
"data": [
{
"id": "0b6e…",
"type": "public_key",
"attributes": {
"name": "Mobile key",
"short_description": null,
"public_key": "3FcN9hN1m2yVZs6h5N7C1qfq8Rr2Q1pS5xH0u8wZ2mE=",
"retired": false,
"retired_at": null,
"created_at": "2026-09-10T16:02:11.000Z",
"updated_at": "2026-09-10T16:02:11.000Z"
},
"relationships": {
"organization": { "data": { "id": "6d4d…", "type": "organization" } }
}
}
],
"links": { "self": "…", "first": "…", "last": "…" }
}

POST /v1/public_keys

Terminal window
curl -X POST https://api.disclosebot.io/v1/public_keys \
-H "Authorization: Bearer disclosebot_svc_xxxxxxxx" \
-H "Content-Type: application/vnd.api+json" \
-d '{ "data": { "type": "public_key", "attributes": { "name": "Mobile key", "public_key": "3FcN9hN1m2yVZs6h5N7C1qfq8Rr2Q1pS5xH0u8wZ2mE=" } } }'

201 with the key. A blank name or key answers 422.

GET /v1/public_keys/{id}

200 with the key; 404 for an unknown id or another organization’s key.

PATCH /v1/public_keys/{id}

Send name, short_description, retired, or any of them. retired: true retires the key and retired: false reinstates it. The key material cannot be changed over the API.

Terminal window
curl -X PATCH https://api.disclosebot.io/v1/public_keys/0b6e… \
-H "Authorization: Bearer disclosebot_svc_xxxxxxxx" \
-H "Content-Type: application/vnd.api+json" \
-d '{ "data": { "type": "public_key", "attributes": { "retired": true } } }'

Retiring a key that is in use answers 422 and names what uses it:

422
{
"errors": [
{ "status": "422", "title": "Unprocessable Entity", "detail": "The key is in use by brief Mobile; change them to another key first", "source": { "pointer": "/data/attributes" } }
]
}

DELETE /v1/public_keys/{id}

204 for a key nothing references. A key that encrypted reports, a cloaked report, or a brief in Cloak Mode uses answers 422 with the detail This key is in use by encrypted reports or a cloaking brief; retire it instead.