The Blink receipt.
A small signed record of what Blink checked before a purchase. Anyone can verify it, without calling us.
What it says.
Hashes, not personal data.
{
"format": "blink.receipt/0.1",
"decision": "ALLOW",
"route": "mail-free-card",
"purchase": "sha256:3b9c…",
"conditions": "sha256:c4f1…",
"evidence": "sha256:9a02…",
"policy_version": "2026-10-12",
"issued_at": "2026-10-18T22:10:00Z",
"expires_at": "2026-10-18T22:15:00Z",
"key_id": "blink-2026-10",
"signature": "ed25519:7Hq…"
}- format
- Always "blink.receipt/0.1" for this draft.
- decision
- ALLOW. Only allowed purchases get a receipt.
- route
- The one return route that met every condition.
- purchase
- SHA-256 of the purchase: product URL, variant, price.
- conditions
- SHA-256 of the buyer’s conditions as sent.
- evidence
- SHA-256 of the evidence bundle the decision used.
- policy_version
- Which version of the store’s policy was read.
- issued_at · expires_at
- When it was signed, and when it stops applying.
- key_id
- Which Blink key signed it.
- signature
- Ed25519 over the canonical JSON of every other field.
How to verify one.
01
Fetch the keys
Published at a fixed address. Cache them.
02
Check the signature
Canonicalise the rest (RFC 8785). Verify with Ed25519.
03
Check it’s yours
Hash your purchase and conditions. Compare.
04
Check it’s current
Refuse it after expires_at.
import { verify } from "@noble/ed25519"
import canonicalize from "canonicalize" // RFC 8785
const keys = await fetch("https://thankyoublink.com/.well-known/blink-keys.json")
.then(r => r.json())
const { signature, ...body } = receipt
const key = keys[receipt.key_id]
const ok =
await verify(fromB64(signature), canonicalize(body), key) &&
Date.parse(receipt.expires_at) > Date.now() &&
receipt.purchase === sha256(myPurchase) &&
receipt.conditions === sha256(myConditions)Draft 0.1 · October 2026
This format is a draft and open for comment. Changes will be versioned in the format field, and old versions will keep verifying. Write to hello@thankyoublink.com.
Questions.
What is a Blink receipt?
A small signed record Blink attaches to every allowed purchase: the route that met your conditions, hashes of the purchase, the conditions and the evidence, and the policy version. Anyone can check the signature against Blink’s public key without calling Blink.
What happens when a policy doesn’t say?
Blink marks it unknown. A missing fee is never read as a free return. When an unknown fact matters, the answer is REVIEW, with the missing fact named.
What does the API return?
A decision (ALLOW, DENY or REVIEW), the return route that satisfied your conditions if there is one, the facts behind it with their source text, and any facts that were unknown.
Why is it cheaper than letting an agent browse?
Browsing makes the model find and read policy pages on every decision. Blink collects the evidence once per policy version and reuses it, so each decision reads a small, structured record instead.
How is the API priced?
By usage. Tell us your expected volume when you request access and we’ll set you up.