AUDRIEDOCS
ReferenceRecords

Revoke a record your organisation authenticated

POST
/v1/records/{recordId}/revoke

Marks a record your organisation authenticated as no longer in good standing, and anchors that decision to Hedera.

Revocation is permanent. It cannot be undone, by you or by us. The record is not removed — a Hedera message cannot be withdrawn — and verification continues to report it, with a revoked verdict and the reason you gave.

The credential must carry records:revoke

This scope is granted only when you ask for it as you mint a credential. A credential that can authenticate documents cannot revoke them unless you requested both, and a credential minted without it never gains the scope — mint a new one.

Ask for it on the credentials you intend to revoke with, and not on the ones your batch jobs carry. A credential holding this scope can revoke any record your organisation authenticated, including records created by a different credential. That is what makes it the right tool after a credential is lost: mint a new credential with records:revoke and clean up with it.

A credential granted records:revoke also carries records:write. There is no revoke-only credential, so a key you mint to clean up after an incident can also authenticate documents as your organisation — protect it as a signing key, and revoke it when the cleanup is done.

A test-prefixed credential can be granted this scope, exactly as a live credential can, and it revokes only its own organisation's sandbox records. Naming a live recordId finds nothing to revoke and answers 404, and the same is true in reverse — a live credential naming a sandbox recordId also gets 404.

What you can revoke

Records your organisation authenticated through this API. Documents a person authenticated in the Audrie app are not revocable here — only that signer can revoke those, from the app.

Revoking is not a way to correct a mistake in the document itself. A corrected document is a new document with a new hash: authenticate the new one, and revoke the old one as SUPERSEDED.

Errors

A 403 has two causes, and they read differently. A credential without records:revoke is told so, and the message names the scope. Otherwise the record is not one your organisation can revoke — and that answer deliberately does not distinguish a record belonging to another organisation from one a person authenticated in the Audrie app.

A 409 has two causes and does not distinguish them. Do not retry blindly: if the record is already revoked, retrying never succeeds, because revocation is permanent. If its anchor has not yet reached consensus, retry once POST /v1/verifications reports verified_org — or, for a test key's own sandbox record, sandbox. That call is also how you tell the two apart — an already-revoked record reports revoked, with a live or a test key.

Authorization

apiKey
headerAuthorizationBearer <aud_{live|test}_<keyId:16><secret:32><crc:6>>

Authorization: Bearer aud_live_…

Optional on POST /v1/verifications, which answers without any credential. Required to list or read verifications back.

Send exactly one Authorization header. A credential that is present and does not work is refused rather than downgraded to the anonymous tier.

Issue a key in the portal under Settings → Organisation → API credentials; it is shown once, at creation.

Three scopes exist. verifications:read covers every verification operation and is on every key. records:write covers POST /v1/records, and records:revoke covers POST /v1/records/{recordId}/revoke. Both are granted to a live or a test credential alike, on an organisation that holds the organisation-issued authentication add-on at the moment the key is minted; records:revoke is granted only when you ask for it. Scopes are fixed then and never widen afterwards, because a credential's recorded scopes are what an auditor reads to know what that key could do on a given date. A test key's records:write and records:revoke reach sandbox records only: signed with the organisation's sandbox key, anchored on Hedera's test network, and never a live record. A key minted without a scope never gains it; mint a new one. Buying the add-on later means minting a new key too; the old one keeps verifying.

Scopes, rotation, revocation, the live and test prefixes and what to do about a leaked key: https://audrie.io/docs/authentication

Path Parameters

recordId*string

The recordId returned when the document was authenticated. UUID.

Formatuuid

Request Body

application/json
  1. body
reason*string

Why the record is being revoked. It is recorded in the ledger message and reported to anyone who verifies the document, so choose the one that is true.

The reason decides how a verifier should read the revocation. Revoking as SUPERSEDED does not suggest the original was improperly authenticated; KEY_COMPROMISE does.

ValueMeaningWhat a verifier should conclude
SUPERSEDEDA newer document replaces this one.The document was validly authenticated. Look for the replacement.
ERROR_IN_DOCUMENTThe document contains an error.The document was validly authenticated, and its contents are wrong.
KEY_COMPROMISEThe signing key may be in someone else's hands.Treat the authentication itself as untrustworthy.
PRIVILEGE_WITHDRAWNThe authority to authenticate this document was withdrawn.The signer was not entitled to authenticate it.
AFFILIATION_CHANGEDThe signer's relationship to the organisation changed.The document was validly authenticated at the time.
CESSATION_OF_OPERATIONThe organisation or service has stopped operating.The document was validly authenticated at the time.
CERTIFICATE_HOLDTemporarily withdrawn pending a decision.Do not rely on it for now.
UNSPECIFIEDNo reason given.Nothing beyond the fact of revocation.
OTHERA reason outside this list.Nothing beyond the fact of revocation.
Value in"SUPERSEDED""ERROR_IN_DOCUMENT""KEY_COMPROMISE""PRIVILEGE_WITHDRAWN""AFFILIATION_CHANGED""CESSATION_OF_OPERATION""CERTIFICATE_HOLD""UNSPECIFIED""OTHER"

Response Body

The record is revoked and the decision has been submitted to Hedera. Verification reports revoked for this record from now on.

application/json
  1. response

The outcome of a revocation.

recordId*string

The record that was revoked. UUID.

Formatuuid
curl -X POST 'https://api.audrie.io/v1/records/497f6eca-6276-4993-bfeb-53cbbbba6f08/revoke' \  -H 'Content-Type: application/json' \  -d '{  "reason": "SUPERSEDED"}'
Example Response
{  "recordId": "9a1b7c3d-4e5f-4a6b-8c9d-0e1f2a3b4c5d"}

Authenticate a document as your organisation POST

Authenticates a document **as the calling organisation**, signing its hash with the organisation's own post-quantum key and anchoring the result to Hedera. This is the only operation on this API that creates anything. Send a hash. Audrie never receives the document. > **A `test`-prefixed credential creates a sandbox record.** It signs > with your organisation's sandbox key — separate from your production > key — and anchors to Hedera's **test** network, never mainnet. A > sandbox record verifies only as `sandbox`, never `verified_org`, > carries no legal weight, and we delete our sandbox record of it after > 30 days; its hash remains on the Hedera test network, which we do not > control. > > A hash you authenticate with a `test` key answers `sandbox` to > **any** caller who submits it, anonymous callers included, for as > long as the sandbox record exists — do not authenticate a hash of a > document whose existence is confidential. Mint a `live` credential > when you are ready to create records that carry legal weight. ## What this is, and what it is not The signature attributes to an **organisation**, not to a person. No individual is accountable for it: there is no identity-verified signer and no WebAuthn ceremony behind an API call. A verifier sees that difference — these records answer `verified_org` rather than `verified`, carry `signerType: org` on the match, and at the `organisation` tier carry your organisation's registered name in `signerOrg`. Use it where an organisation is the right signer: bulk authentication of documents your organisation issues. Where a named person must be accountable, have that person authenticate in the portal instead. ## Idempotency Retrying is safe, and you do not need an idempotency key: the document hash is the key. Your organisation can hold **one active record per document hash**. A repeat call for a hash you already hold returns that record with `200` and creates nothing; a first call returns `201`. The body is identical either way, because after a timeout you cannot know which call you made — branch on the status only if you care. A record whose anchor ultimately **failed** stops counting, so a later call for that hash creates a new record rather than returning the failed one forever. ## Anchoring is asynchronous, and it can fail On a `201`, `anchorState` is `pending` or `accepted`, and reaches `anchored` at Hedera finality — typically 3–5 seconds. On a `200` retry it is whatever the existing record has already reached, which may be `anchored`. Branch over all three values, not two. Poll `POST /v1/verifications` with the same hash rather than this operation. **Read the verdict, not the clock, and expect three outcomes.** Until the record reaches the ledger, verification answers `no_record` — it reports only records that have been accepted for anchoring, so a record you have just created is briefly invisible there. Then: | The verdict becomes | Meaning | What to do | |---|---|---| | `pending_anchor` | On the ledger, awaiting consensus. | Wait `retryAfterSeconds` and poll again. | | `verified_org` | Anchored. Done. A record created with a `test` key reads `sandbox` here instead. | Nothing. | | still `no_record` after ~3 minutes | **The anchor failed** before the message was submitted. The record is abandoned and stops being active. | Call `POST /v1/records` again for this hash. It will create a new record rather than returning the abandoned one. | | stuck at `pending_anchor` for many minutes | The message reached the ledger but consensus has not been reconciled. **This one does not self-resolve by retrying**, and re-authenticating will not help — the record is still active, so a repeat call returns it unchanged. | Report it with the `recordId`. | **An anchored record cannot be withdrawn.** A Hedera message is permanent. Revocation marks a record as no longer in good standing rather than removing it — see `POST /v1/records/{recordId}/revoke`. ## Errors A `400` means `originalDocHash` is not `sha256:` followed by 64 **lowercase** hex characters, `filename` is longer than 500 characters or contains a control or invisible formatting character, or the body is not a JSON object. `error.details` names the field. Uppercase hex is refused rather than normalised: the hash is used verbatim inside the signature and the ledger message, so two spellings would be two separate permanent records for one document. The `402` and `403` each have more than one cause. **Branch on `error.code`**, and read the response descriptions below — they say which causes exist and which of them mean "wait" rather than "fix something".