# Verify a receipt

Last updated: 2026-10-10

`POST /v1/receipt/verify` checks an AttestPage receipt against this service's published keys and returns its decoded payload. Free.

If you would rather not trust our server to check our own receipts, use the [offline checker](/docs/verify-offline) instead.

## Request

```json
{ "receipt": "eyJhbGciOiJFZERTQSIs…" }
```

`receipt` is the compact JWS from the `receipt` field of any response, at most 163,840 characters (160 KB). A 10-URL `check/links` or `verify/citations` receipt with long URLs and every network-evidence field at its cap is about 128 KB. The evidence fields are capped in bytes, so a site whose certificate names or headers use non-ASCII or escaped characters cannot make it bigger. The request body may be up to 168 KB, here and on `/mcp`.

## Response

```json
{
  "valid": true,
  "kid": "https://vehcdj664efetfrsolne5umanq.srv.us/.well-known/jwks.json#ap-1a2b3c4d5e6f7a8b",
  "tier": "paid",
  "payload": { "v": 1, "iss": "https://vehcdj664efetfrsolne5umanq.srv.us", "kind": "quote", "…": "…" }
}
```

When the receipt does not check out, `valid` is false and `reason` and `message` say why. Reasons include `malformed`, `bad_alg`, `bad_signature`, `unknown_kid`, `bad_iss` and `tier_key_mismatch`.

`tier` is `paid`, `trial` or `sample`. Sample receipts are signed with a separate sample key (kid ending `#sample`) and are not evidence about any third-party page.

## Errors

400 when the body is not `{"receipt": "<string>"}` or the receipt is too long; 503 `signing_unavailable` when keys are not loaded.
