AUDRIEDOCS
ReferenceVerifications

Read one verification back

GET/v1/verifications/{verificationId}

Returns one verification as it was recorded. Scoped to the calling key's organisation and environment.

matches is always [] here. Matches are derived from the document hash rather than stored, so this operation answers "what did we tell you, and when". To get current matches, POST the hash again, which is the operation that computes them.

Errors

A 404 means the id does not exist, belongs to another organisation, or belongs to another environment. These are not distinguished, and a malformed id answers the same way. Existence is not disclosed.

AuthorizationBearer <token>

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.

Two scopes exist. verifications:read covers every verification operation and is on every key. records:write covers POST /v1/records and is granted only on a live credential whose organisation holds the organisation-issued authentication add-on at the moment the key is minted — a test key never receives it, because there is no sandbox ledger and the records it would create would be permanent — 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. Buying the add-on later means minting a new key; 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

In: header

Path Parameters

verificationId*string

The verificationId returned when the verification was performed. A UUID.

Formatuuid

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/v1/verifications/3c0d9a2e-77b1-4f0a-8a11-d1e2f3a4b5c6"
{  "verificationId": "72d12273-0723-448e-a9f6-f7957128efa5",  "verdict": "verified",  "disclosureTier": "public",  "assuranceLevel": "audrie.registry.v1",  "mode": "partial",  "environment": "live",  "originalDocHash": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",  "verifiedAt": "2019-08-24T14:15:22Z",  "reference": "string",  "matches": [    {      "recordId": "0470cfd4-dcf3-4d8c-ac28-58c6deeff25f",      "kind": "pdf_embedded",      "status": "active",      "recordIssuedAt": "2019-08-24T14:15:22Z",      "signerType": "user",      "signerStanding": "good_standing",      "signerHint": "string",      "signerOrg": "string",      "revocation": {        "reason": "SUPERSEDED",        "revokedAt": "2019-08-24T14:15:22Z"      },      "checksPerformed": {        "hashBinding": "pass",        "userSignature": "pass",        "serverSeal": "pass",        "anchorStatus": "anchored"      },      "anchor": {        "topicId": "0.0.4915623",        "transactionId": "0.0.1234@1746223981.000000000",        "sequenceNumber": 0,        "consensusAt": "2019-08-24T14:15:22Z",        "mirrorNodeUrl": "http://example.com"      }    }  ],  "retryAfterSeconds": 0}

Verify a document hash POST

Submits a document hash and returns a **verdict** — Audrie's answer to "does this document check out, and what do you know about it". Both cryptographic checks are recomputed server-side for your request. Nothing in the request body is trusted beyond the identifiers used to look records up: a client that lies about a hash can only produce a verdict that fails its own verification. Works with or without a credential. See [Disclosure tiers](https://audrie.io/docs/disclosure-tiers). ## What you get back `verdict` is a single value you can branch on. It is derived from the four checks in `matches[].checksPerformed` plus revocation state, and it fails closed: anything Audrie cannot fully substantiate is never reported as `verified`. Every determinate outcome — `no_record` included — returns `200` with a `verdict`. A hash Audrie holds no record of is information, not a failed request. `mode` is `partial` on every response. Read the field rather than hardcoding the value. ## One hash, several records You do not pick the record. One hash can legitimately have several records — a re-signing, or several parties authenticating the same document — so the response returns every anchored match, ordered by anchor time, earliest first. The timeline is the answer. `verdict` asserts that some valid anchored authentication exists, not that a particular party made it. Read each match's own `status`, `signerStanding` and `signerHint` before attributing a document to anyone. ## Signer standing is live `signerStanding` is recomputed at request time. A certificate issued earlier carries a frozen snapshot; this endpoint does not. The two can legitimately disagree, and the live value is the current answer. ## Errors A `400` here means `originalDocHash` is not `sha256:` followed by 64 lowercase hex characters, `reference` is longer than 128 characters or contains a control character, or the body is not a JSON object. `error.details` names the field.

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 cannot reach this operation.** There is > no sandbox ledger: this endpoint signs with your organisation's > production key and anchors a permanent, public Hedera message that > **cannot be withdrawn**, so a key labelled `test` is never granted > `records:write` at all and is refused here with `403`. Mint a `live` > credential when you are ready to create records that are real. ## 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. | 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".