Client-side receipt verification

Receipts that prove the decision, not just the payment.

Paste a GateCore signed action receipt below. Your browser recomputes the signed bytes, checks the hash, and checks the Ed25519 signature. Nothing you paste here reaches GateCore, or anyone else.

RUNS ENTIRELY IN YOUR BROWSER · NO ACCOUNT · NO NETWORK CALL · VIEW SOURCE TO CONFIRM IT
Who uses this

Three reasons to paste a receipt here.

Finance teams at month-end: every agent purchase has a receipt; paste it and settle "did we authorize this?" in seconds.

Sellers in a dispute: the receipt shows exactly what was delivered, under which terms, and proves the record was never altered.

Security reviewers before a contract: test the audit claim yourself in thirty seconds instead of trusting a PDF.

Every vendor says trust us. This page is how you check.

How this page works

Five steps, all offline.

The same check a receipt would get from the standalone Python verifier GateCore publishes at examples/verify_receipt.py, ported to run in a browser tab instead of a terminal.

01
PASTE
The JSON envelope returned by GET /v1/receipts/{request_id}
INPUT
02
RECOMPUTE
Rebuild the exact canonical bytes GateCore signed
BYTES
03
HASH
Check payload_sha256 against those recomputed bytes
SHA-256
04
VERIFY
Check the Ed25519 signature against the named key
ED25519
05
RENDER
Show what the receipt binds, field by field
RESULT
The verifier

Paste a receipt.

Works with the full envelope from GET /v1/receipts/{request_id}: {receipt, payload_sha256, signature, signing_key_id, alg}.

Receipt JSON
Signing key
Kidreceipt-20260809-prod
StatusACTIVE
SourceEmbedded in this page at build time
ProvenanceFetched 2026-08-13 from api.gatecoreai.com/v1/receipts/keys

GateCore's API blocks cross-origin browser requests by design (see below), so this page cannot live-fetch the current key list. The active production key ships embedded above. If you're checking a receipt signed under a rotated or retired key, paste that key set instead.

Use a different key
Paste a keys envelope or a single PEM public key
Verify the original request binding (advanced)

Optional. GateCore receipt_version 2 carries request.request_sha256, the hash of the exact bytes the agent's own signature covers. If you also hold the original signed request JSON, paste it here to check that binding, and optionally the agent's Ed25519 public key to check the agent's own signature.

Original request JSON Agent public key (PEM or base64url, optional)
Why this page can't just fetch the key

The key endpoint is public. Browser access to it is not.

GET /v1/receipts/keys is unauthenticated on purpose. Anyone verifying a receipt needs the public key, with no account. What it does not do is answer cross-origin browser requests: GateCore's CORS policy allows only its own applications to call the API from a browser tab. Confirmed directly against the live endpoint before this page shipped: a preflight from this origin comes back 400 Disallowed CORS origin. That is a locked-down security posture, not an oversight, so this page embeds the key instead of fetching it.

What's embedded

One active key, one date.

  • The kid and PEM currently returned by the live endpoint
  • A provenance line naming when and where it was fetched
  • Rotation adds a kid; it does not invalidate old receipts
Full independence

You don't have to trust our copy.

Call api.gatecoreai.com/v1/receipts/keys yourself, from a terminal or server, and paste what it returns into "Use a different key" above. Or skip this page entirely and run examples/verify_receipt.py, the same reference verifier this page's canonicalization was checked against.

What a passing check means

Read this before you trust a green result.

What verification proves

GateCore signed exactly these bytes.

  • The receipt was signed by the named key, under GateCore's receipt domain
  • Nobody altered a single byte after signing, or the hash and signature both fail
  • Identity, decision, execution, and settlement were bound under one signature
What it doesn't prove

GateCore is still the issuer.

  • A compromised signing key could sign a false receipt at issuance time
  • A receipt proves an action happened; it can't prove no other action happened
  • Execution status is what the gateway observed, not the target's real-world outcome

Read the full model, including the ledger's hash chain and off-box checkpoint anchoring, on the security page.

FAQ

Questions, answered.

Where do I get a receipt to paste here?
GET /v1/receipts/{request_id} on your gateway returns the exact envelope this page expects: {receipt, payload_sha256, signature, signing_key_id, alg}. The Operator Console's Activity view links a transaction to its receipt for download.
Why receipt_version 2, specifically?
Version 2 is what GateCore issues today. It replaced floating-point trust and provenance scores with integer basis points, because floating-point numbers don't reliably serialize to identical bytes across languages, the same reason this page declines to attempt cryptographic verification of legacy version-1 receipts. Use the offline Python verifier for those.
What does a failed check usually mean?
Most often: the wrong key was used, a character in the pasted JSON was changed or truncated, or the JSON isn't the full envelope (missing payload_sha256, signature, or signing_key_id). A genuine tamper produces the same failure, which is the point.
Does this page call GateCore, or anyone, over the network?
No. Every check runs with the browser's built-in WebCrypto API, against bytes you provide and a key embedded in this page or one you paste yourself. View source to confirm it.
Early access

Bring your security team. Bring your receipts.

Every governed transaction gets one of these. Ask us for a live one against your own use case.

Request early access