API reference
Anchors
External timestamp receipts for your record's root, each with instructions a stranger can follow without asking us.
GET /v1/anchors
List anchor receipts
Lists the receipts written when your root was anchored externally, each with instructions to check it without us.
A failed attempt is still a receipt: status anchor_failed with the error text and no how_to_check. With the provider set to none the list reports provider_status anchoring_disabled and no receipts are written.
Parameters
None.
Request body
None.
Example request
curl
curl -sS -X GET "https://api.afaprotocol.com/v1/anchors" \
-H "X-API-Key: afa-beta-EXAMPLE-e4qs"
Python
import requests
API = "https://api.afaprotocol.com"
headers = {"X-API-Key": "afa-beta-EXAMPLE-e4qs"}
r = requests.get(f"{API}/v1/anchors", headers=headers, timeout=30)
r.raise_for_status()
print(r.json())
Example response
HTTP 200
{
"anchors": [
{
"anchor_id": "anc-7d2f9a1c4b3e8065",
"created_at": "2026-09-01T14:12:10+00:00",
"error": null,
"external_ref": "90de9e6cde8c1f312afba912cfed5bf673d11b43884607adf9ee608a2b6bc79f50b3722e2df1539b",
"how_to_check": {
"commands": [
"rekor-cli get --uuid 90de9e6cde8c1f312afba912cfed5bf673d11b43884607adf9ee608a2b6bc79f50b3722e2df1539b",
"rekor-cli get --log-index 412039871"
],
"provider": "rekor",
"recompute": "sha256 over proof_json.record serialised as JSON with sorted keys and no whitespace must equal proof_json.record_sha256; that digest is the hash the external entry carries. The entry's signature verifies against proof_json.public_key_pem over that digest.",
"search_url": "https://search.sigstore.dev/?uuid=90de9e6cde8c1f312afba912cfed5bf673d11b43884607adf9ee608a2b6bc79f50b3722e2df1539b",
"url": "https://rekor.sigstore.dev/api/v1/log/entries/90de9e6cde8c1f312afba912cfed5bf673d11b43884607adf9ee608a2b6bc79f50b3722e2df1539b"
},
"integrated_time": 1756735930,
"proof_json": {
"log_index": 412039871,
"public_key_pem": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAExampleKeyBytesOnlyReplaceMe0000000000=\n-----END PUBLIC KEY-----\n",
"record": {
"issued_at": "2026-09-01T14:12:10+00:00",
"root": "sha256:fa169e47437c116de26d2e8a91c3cd7c75c91c12cbe418cb3d60804008eb496c",
"schema": "afa.anchor.record.v1",
"subject": "2f6e1a0c-9b4d-4e8a-8c31-5d7f0a2b9c14"
},
"record_sha256": "a5b922e3dbf400f3ca9f9194635e1d84c9e9813af47b651757dfcb6084007e2b",
"rekor_url": "https://rekor.sigstore.dev"
},
"provider": "rekor",
"root": "sha256:fa169e47437c116de26d2e8a91c3cd7c75c91c12cbe418cb3d60804008eb496c",
"status": "anchored",
"user_id": "2f6e1a0c-9b4d-4e8a-8c31-5d7f0a2b9c14"
}
],
"provider": "rekor",
"provider_error": null,
"provider_status": "ok",
"user_id": "2f6e1a0c-9b4d-4e8a-8c31-5d7f0a2b9c14"
}
Errors
| Status | Code | Meaning |
|---|---|---|
| 401 | missing_token / invalid_or_expired_api_key | No credential, an expired session, or a revoked or expired key. |
| 403 | scope_missing | A key limited by scopes lacks anchors; the body names it. |
What would show this is false
Follow how_to_check without us: fetch the log entry by its reference and recompute record_sha256 from proof_json.record. The entry carries that digest.
POST /v1/anchors/run
Anchor the current root now
Anchors the account's current root with the configured provider, or reports unchanged if it has not moved.
HTTP 200 describes the request; status describes the outcome: anchored, unchanged, anchor_failed, no_root, anchoring_disabled or provider_misconfigured. A provider failure still writes a receipt row carrying the error.
Parameters
None.
Request body
None.
Example request
curl
curl -sS -X POST "https://api.afaprotocol.com/v1/anchors/run" \
-H "X-API-Key: afa-beta-EXAMPLE-e4qs"
Python
import requests
API = "https://api.afaprotocol.com"
headers = {"X-API-Key": "afa-beta-EXAMPLE-e4qs"}
r = requests.post(f"{API}/v1/anchors/run", headers=headers, timeout=30)
r.raise_for_status()
print(r.json())
Example response
HTTP 200
{
"anchor_id": "anc-7d2f9a1c4b3e8065",
"provider": "rekor",
"receipt": {
"anchor_id": "anc-7d2f9a1c4b3e8065",
"created_at": "2026-09-01T14:12:10+00:00",
"error": null,
"external_ref": "90de9e6cde8c1f312afba912cfed5bf673d11b43884607adf9ee608a2b6bc79f50b3722e2df1539b",
"how_to_check": {
"commands": [
"rekor-cli get --uuid 90de9e6cde8c1f312afba912cfed5bf673d11b43884607adf9ee608a2b6bc79f50b3722e2df1539b",
"rekor-cli get --log-index 412039871"
],
"provider": "rekor",
"recompute": "sha256 over proof_json.record serialised as JSON with sorted keys and no whitespace must equal proof_json.record_sha256; that digest is the hash the external entry carries. The entry's signature verifies against proof_json.public_key_pem over that digest.",
"search_url": "https://search.sigstore.dev/?uuid=90de9e6cde8c1f312afba912cfed5bf673d11b43884607adf9ee608a2b6bc79f50b3722e2df1539b",
"url": "https://rekor.sigstore.dev/api/v1/log/entries/90de9e6cde8c1f312afba912cfed5bf673d11b43884607adf9ee608a2b6bc79f50b3722e2df1539b"
},
"integrated_time": 1756735930,
"proof_json": {
"log_index": 412039871,
"public_key_pem": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAExampleKeyBytesOnlyReplaceMe0000000000=\n-----END PUBLIC KEY-----\n",
"record": {
"issued_at": "2026-09-01T14:12:10+00:00",
"root": "sha256:fa169e47437c116de26d2e8a91c3cd7c75c91c12cbe418cb3d60804008eb496c",
"schema": "afa.anchor.record.v1",
"subject": "2f6e1a0c-9b4d-4e8a-8c31-5d7f0a2b9c14"
},
"record_sha256": "a5b922e3dbf400f3ca9f9194635e1d84c9e9813af47b651757dfcb6084007e2b",
"rekor_url": "https://rekor.sigstore.dev"
},
"provider": "rekor",
"root": "sha256:fa169e47437c116de26d2e8a91c3cd7c75c91c12cbe418cb3d60804008eb496c",
"status": "anchored",
"user_id": "2f6e1a0c-9b4d-4e8a-8c31-5d7f0a2b9c14"
},
"recorded": true,
"root": "sha256:fa169e47437c116de26d2e8a91c3cd7c75c91c12cbe418cb3d60804008eb496c",
"status": "anchored"
}
Errors
| Status | Code | Meaning |
|---|---|---|
| 401 | missing_token / invalid_or_expired_api_key | No credential, an expired session, or a revoked or expired key. |
| 403 | scope_missing | A key limited by scopes lacks anchors; the body names it. |
What would show this is false
Run twice without new events: the second answers unchanged, names the first anchor_id, and recorded is false.