HANND merchant integration
Endpoint
POST https://hannd-receipts.ryguyhannicus.chatgpt.site/api/v1/receipts
Call only from your merchant server. Keep the API key in its secret store. The public customer browser must not receive it. While the Site is owner-private, an external integration additionally needs a supported Site service-access header, OAI-Sites-Authorization: Bearer <service token>. This is a server credential, not a receipt token; never send it to the browser. Public rollout removes the private gateway requirement, not the merchant API key requirement.
Request
Authorization: Bearer YOUR_MERCHANT_KEY Content-Type: application/json
{
"token": "SINGLE_USE_TOKEN_FROM_CUSTOMER_HANND_ID",
"transactionId": "store-01:order-1001",
"receipt": {
"purchasedAt": "2026-10-17T16:30:00-07:00",
"items": [{"name": "Oat latte", "quantity": 1, "unitPrice": 600}],
"tax": 50,
"tip": 0,
"total": 650,
"currency": "USD",
"category": "Food & drink",
"last4": "4242"
}
}
Do not send a full card number or customer email. last4 is optional. Merchant name is taken from the authenticated merchant record, regardless of submitted merchant text.
Contract
- Token: scan the customer's QR code as a raw string. It begins
hn_, expires after 300 seconds and is accepted for one receipt. - Transaction ID: stable, unique within the merchant. Include location and POS order ID if order IDs can collide between stores. Maximum 100 characters.
- Amounts: nonnegative integers in cents. The server verifies
sum(quantity * unitPrice) + tax + tip === totalexactly. V1 supports USD only and purchase receipts, not negative refunds, fractional quantities or discounts. - Items: 1–100. Integer quantity from 1 to 1,000; descriptions up to 150 characters.
- Purchase time: ISO 8601 with timezone; not more than 24 hours in the future.
- Category: Food & drink, Shopping, Groceries, Transport, Home, Health, Travel, Other.
- Size limit: 64 KiB JSON. No attachments or full payment credentials.
- Rate limit: 60 requests per merchant key per minute.
Responses and retry rules
| Status | Meaning | Merchant behavior |
|---|---|---|
| 201 | New receipt delivered | Show success |
| 200 | Same transaction and payload already accepted | Show success using returned ID |
| 400 | Invalid totals, malformed payload or expired code | Correct payload or request a fresh code |
| 401 | Missing or revoked merchant key | Stop and repair authentication |
| 403 | Sandbox destination mismatch or inactive live entitlement | Use own test inbox or restore subscription |
| 409 | Token used, duplicate transaction race, or changed retry payload | Retry identical transaction once after a race; otherwise investigate conflict |
| 429 | Key rate limit | Back off with jitter |
| 500 | Transient server failure | Retry exact transaction and payload with backoff |
A successful response is { "id": "receipt-id", "delivered": true, "mode": "sandbox" }. Replays include replayed: true.
Network failures are ambiguous: never invent a new transaction ID just because the first call timed out. The supplied SDK retries network failures, 429 and server errors, while keeping the same JSON payload. Once a receipt is intentionally deleted by its owner, idempotency is not guaranteed indefinitely; its original destination is invalidated and cannot resurrect the deleted receipt.
POS adapter responsibilities
- Complete payment in the existing POS. HANND does not process the retail purchase.
- Offer Print / Email / Send to HANND.
- If HANND is selected, use the POS-supported reader to capture the fresh QR token.
- Normalize completed transaction lines and amounts into the contract above.
- Queue and send to HANND server-to-server; expose a truthful delivery status.
- On an expired code, ask for a fresh code; never silently redirect to someone else's account.
- Keep a bounded retry queue and give the customer an existing receipt fallback if delivery fails.
Universal NFC/wallet compatibility is not provided by this adapter. See launch documentation for the separate hardware integration path.