Get a verification record.

GET /v1/certificates/{id} returns one issued verification record: the signed document itself, its lifecycle status, and the evidence that sits beside the document because nothing may edit a signed one. It is the call the quickstart makes to download certificate.json, and the only one a relying party needs before verifying offline.

Request

GET https://api.burnledger.io/v1/certificates/{id}
Authorization: Bearer $BURNLEDGER_API_KEY
ParameterInMeaning
idpathVerification Record UUID, as returned by the verify call that issued it or by GET /v1/certificates. Anything that does not parse as a UUID is a 400, not a 404.
AuthorizationheaderCustomer API key (dp_<hex>) as a bearer token. The key's team scopes the lookup: a verification record belonging to another team is a 404, never a 403, so IDs cannot be probed for existence.
curl -H "Authorization: Bearer $BURNLEDGER_API_KEY" \
  https://api.burnledger.io/v1/certificates/11111111-1111-4111-8111-111111111111 \
  -o certificate.json

No query parameters, no request body, and the response is not paginated. Read-only keys can call it; it never changes state.

Response

The envelope is {"data": …}, as for every single-resource endpoint. The interesting split is between the fields about the verification record and the verification record itself, which arrives verbatim in certificate:

FieldMeaning
idVerification Record UUID. Equal to certificate.certificate_id.
attestation_idThe attestation this verification record closes. Equal to certificate.attestation_id.
format_versionSchema of the signed document, currently 4.0. Earlier versions remain verifiable indefinitely: a verifier reconstructs the payload for the version the verification record declares, so a 3.0 verification record keeps hashing exactly as issued.
issued_atRFC 3339 UTC. When the enclave signed the document.
statusACTIVE or REVOKED. A database column, not a signed claim: for anything that must hold up outside your account, read status_statement instead.
transparency_statusPENDING, INCLUDED or FAILED. Whether the verification record has been appended to the public log. Only INCLUDED verification records carry an inclusion proof inside certificate.transparency.
revoked_at, revocation_reasonPresent only when status is REVOKED.
verification recordThe full signed verification record JSON, byte for byte what the offline verifiers accept. Field by field it is documented in Verification Record anatomy. Save this object on its own and you have the portable file.
status_statementThe enclave-signed revocation statement for this verification record, stapled here so the common path is one fetch and verification stays offline for the statement's validity window. It is the same object GET /v1/certificates/{id}/status returns publicly. Omitted, not errored, if the signer is briefly unavailable: verifiers treat a missing statement as revocation unknown, never as valid, so omission understates and never overstates.
nsm_attestationBase64 AWS Nitro NSM attestation document produced while this verification record was signed. Its PCR measurements identify the enclave image that held the key, and its user_data is this verification record's canonical signing payload, so it cannot be moved to another verification record. Absent for verification records issued before it was recorded and for dev-mode issuance; absence is not a verification result. Today only the Go verifier checks it.

Example

A format 4.0 verification record covering two systems, taken from the SDK conformance fixtures. Binary fields (keys, hashes, signatures) are JSON byte arrays and are abridged here with ; everything else is verbatim.

{
  "data": {
    "id": "11111111-1111-4111-8111-111111111111",
    "attestation_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
    "format_version": "4.0",
    "issued_at": "2025-06-15T12:05:01Z",
    "status": "ACTIVE",
    "transparency_status": "INCLUDED",
    "certificate": {
      "certificate_format_version": "4.0",
      "certificate_id": "11111111-1111-4111-8111-111111111111",
      "attestation_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
      "issued_at": "2025-06-15T12:05:01Z",
      "status": "ACTIVE",
      "issuer": {
        "name": "BurnLedger",
        "public_key": [5, 6, 136, 63, …],
        "key_id": "dp_k_d59705f498f0b0bfa02c2180d2a02b39f3ca26cb1f624ffab5da96ba4e541e82",
        "legal_entity": "ProChatFlow LLC"
      },
      "subject": {
        "identifier_hash": [11, 140, 190, 29, …],
        "identifier_type_hint": "email"
      },
      "attestation": {
        "proof_mode": "count",
        "attested_at": "2025-06-15T12:00:00Z",
        "systems": null,
        "attestation_signature": [153, 150, 140, 180, …]
      },
      "systems": [
        {
          "system_id": "5111e111-1111-4111-8111-111111111111",
          "system_name": "users <db> & cache",
          "connector_type": "postgresql",
          "hash_scope": "existence",
          "query_hash": [118, 56, 100, …],
          "attested_count": 42,
          "attested_at": "2025-06-15T12:00:00Z",
          "verified_count": 0,
          "verified_at": "2025-06-15T12:05:00Z"
        },
        {
          "system_id": "5222e222-2222-4222-8222-222222222222",
          "system_name": "logs-s3",
          "connector_type": "s3",
          "hash_scope": "existence",
          "query_hash": [7, 60, 169, …],
          "attested_count": 7,
          "attested_at": "2025-06-15T12:00:00Z",
          "verified_count": 0,
          "verified_at": "2025-06-15T12:05:00Z"
        }
      ],
      "scope": {
        "version": "1.0",
        "text_sha256": [216, 30, 163, 196, …]
      },
      "certificate_signature": [233, 21, 39, 166, …],
      "transparency_status": "INCLUDED",
      "transparency": {
        "log_url": "https://log.burnledger.io",
        "tree_size": 4,
        "entry_index": 1,
        "entry_type": "CERTIFICATE",
        "appended_at": "2025-06-15T12:05:01Z",
        "inclusion_proof": [[170, 101, 122, 17, …], […]],
        "signed_tree_head": {
          "tree_size": 4,
          "root_hash": [155, 176, 221, 20, …],
          "timestamp": "2025-06-15T12:05:01Z",
          "signature": [165, 67, 196, 16, …]
        }
      }
    },
    "status_statement": {
      "certificate_id": "11111111-1111-4111-8111-111111111111",
      "status": "ACTIVE",
      "statement_issued_at": "2026-08-27T09:00:00Z",
      "statement_expires_at": "2026-08-28T09:00:00Z",
      "sth_tree_size": 4,
      "sth_root_hash": "9bb0dd14…",
      "signature": "a543c410…",
      "key_id": "dp_k_d59705f498f0b0bfa02c2180d2a02b39f3ca26cb1f624ffab5da96ba4e541e82"
    }
  }
}

Two things to notice. 4.0 signs issuer.legal_entity and a scope commitment (the SHA-256 of the scope text the verification record was issued under) that 3.0 did not. And the status_statement hashes are hex strings while the verification record's are byte arrays: the statement is a separate wire object with its own verifier, not part of the signed document.

Errors

Every error is {"error": {"code": …, "message": …}}.

StatusWhen
400id is not a UUID.
401Missing, malformed or revoked API key.
404No verification record with that ID in the key's team. Deliberately indistinguishable from a verification record that exists elsewhere.

What to do with it

  • Verify it offline. Write data.certificate to a file, fetch the published keys from /.well-known/burnledger-keys, and run burnledger check. Verify a record walks through the browser, CLI and transparency-log routes.
  • Hand it to a third party. They need the certificate object and nothing else: no account, no call back to BurnLedger. If they want current revocation status, GET /v1/certificates/{id}/status is public and needs no key.
  • Get the human-readable version. GET /v1/certificates/{id}/pdf renders the same verification record as a PDF for auditors and data subjects. The PDF is a rendering; the JSON is the evidence.
  • Check revocation from your own account. GET /v1/certificates/{id}/revocation-status returns the account-side status and reason without the signed statement.

The full endpoint list, including attest, delete, verify and the verification record list, is in the API reference.

Common questions

Which field is the actual verification record?

data.certificate. It is the complete signed document: issuer key, subject hash, every system's attested and verified counts, both Ed25519 signatures, the scope commitment and the transparency proof. The fields around it (status, status_statement, nsm_attestation) are evidence about the document and are not covered by its signature.

Why is status both a top-level field and a signed statement?

The top-level status is what BurnLedger's database says, useful inside your own account. status_statement is the same fact signed inside the enclave with a validity window, which is what a verifier outside your account can check. A signature commits to bytes at one instant, so revocation cannot be expressed by editing the verification record; it needs its own signed object.

Can I fetch a verification record without an API key?

Not through this endpoint. The verification record is your team's record and is scoped to your key. What is public is the revocation status (GET /v1/certificates/{id}/status), the published signing keys, and the transparency log; a relying party who already holds the verification record file needs nothing more.

© 2026 ProChatFlow LLC Last updated present → absent → proven