Receipt Verify API Contract + Error Boundary
SafeGate defines how a future receipt verification API should behave across success, invalid input, missing receipt, unauthorized access, rate limiting, and ambiguous verification states.
1. Contract Purpose
The v5.1 page introduced the public mock for receipt verification. v5.2 adds the response contract and error boundary model needed before any future production API can be safely exposed.
Payment is the trigger. Trust is the product.
2. Future Endpoint Shape
The future endpoint shape is intentionally minimal. Receipt verification should be server-side, bounded, rate-limited, and free of sensitive implementation details.
GET /api/receipt/verify?receiptId=SG-RCPT-1781465776152
Required query parameter
{
"receiptId": {
"type": "string",
"required": true,
"example": "SG-RCPT-1781465776152",
"rule": "Must match controlled SafeGate receipt identifier format."
}
}
Reserved future headers
{
"X-SafeGate-Merchant-Id": "reserved_for_future_production_api",
"X-SafeGate-API-Key": "reserved_for_future_production_api",
"X-Idempotency-Key": "reserved_for_future_replay_control"
}
3. Standard Response Envelope
Every future verification response should follow a predictable envelope. This keeps merchant integrations, reviewers, and audit tooling easier to reason about.
{
"ok": true,
"mode": "public_mock_or_future_production",
"statusCode": 200,
"code": "RECEIPT_VERIFIED",
"message": "Receipt verification completed.",
"receiptId": "SG-RCPT-1781465776152",
"trustSummary": {},
"boundaries": {},
"verifiedAt": "timestamp"
}
4. Success Response / 200
{
"ok": true,
"mode": "public_mock",
"statusCode": 200,
"code": "RECEIPT_VERIFIED",
"message": "Controlled receipt proof was found.",
"receiptId": "SG-RCPT-1781465776152",
"paymentNetwork": "Pi Testnet",
"paymentState": "PAYMENT_FINALIZED",
"accessState": "UNLOCKED",
"merchantRecord": "FOUND",
"productionApi": false,
"trustSummary": {
"paymentFinalized": true,
"receiptProofCreated": true,
"accessUnlocked": true,
"merchantRecordFound": true
},
"boundaries": {
"piMainnetSettlementClaim": false,
"publicApiKeyExposed": false,
"backendSecretExposed": false
},
"verifiedAt": "mock_timestamp"
}
5. Invalid Receipt ID / 400
Invalid receipt identifiers should fail early. The system should not hit payment verification APIs, database search, or merchant records when the input is malformed.
{
"ok": false,
"mode": "public_mock",
"statusCode": 400,
"code": "INVALID_RECEIPT_ID",
"message": "The receiptId format is invalid.",
"receiptId": "bad-input",
"accessState": "LOCKED_OR_UNKNOWN",
"safeBehavior": "FAIL_CLOSED"
}
6. Receipt Not Found / 404
Unknown receipt IDs should not reveal whether adjacent IDs, merchant IDs, payment IDs, or internal records exist. The response must stay generic and bounded.
{
"ok": false,
"mode": "public_mock",
"statusCode": 404,
"code": "RECEIPT_NOT_FOUND",
"message": "Receipt was not found in the controlled evidence set.",
"receiptId": "SG-RCPT-UNKNOWN",
"paymentState": "UNKNOWN",
"accessState": "LOCKED_OR_UNKNOWN",
"merchantRecord": "NOT_FOUND",
"safeBehavior": "FAIL_CLOSED"
}
7. Unauthorized Future Merchant / 401
When production merchant authentication exists, invalid or missing merchant credentials should fail without revealing whether the receipt exists.
{
"ok": false,
"mode": "future_production_boundary",
"statusCode": 401,
"code": "UNAUTHORIZED_MERCHANT",
"message": "Merchant authentication is required.",
"receiptId": null,
"safeBehavior": "NO_RECEIPT_DISCLOSURE"
}
8. Rate Limited / 429
Verification endpoints must be protected against enumeration, bot probing, and AI-agent abuse. Rate limiting should be merchant/API-key scoped where possible, not only IP-based.
{
"ok": false,
"mode": "future_production_boundary",
"statusCode": 429,
"code": "RATE_LIMITED",
"message": "Too many verification attempts.",
"retryAfterSeconds": 60,
"safeBehavior": "THROTTLED"
}
9. Verification Ambiguous / 503
If a payment verification dependency fails, times out, returns an ambiguous response, or cannot be trusted, SafeGate should fail secure. Access must not be unlocked from an ambiguous verification state.
{
"ok": false,
"mode": "future_production_boundary",
"statusCode": 503,
"code": "VERIFICATION_AMBIGUOUS",
"message": "Verification is temporarily unavailable or ambiguous.",
"paymentState": "UNKNOWN",
"accessState": "LOCKED_OR_UNKNOWN",
"safeBehavior": "FAIL_SECURE_NO_UNLOCK"
}
10. Error Boundary Rules
No Stack Trace Leakage
Public responses must not expose framework errors, database names, table names, Supabase details, environment variable names, service role keys, or internal file paths.
No Secret Exposure
API keys, wallet passphrases, access tokens, webhook secrets, and service role credentials must never be returned, logged publicly, or embedded client-side.
No ID Enumeration
Unknown receipt IDs should not help an attacker infer valid receipt ranges, merchant IDs, payment IDs, or database record structure.
Fail Secure
Invalid, missing, ambiguous, timed-out, or conflicting verification states must not unlock access.
11. Legal State Transitions
Receipt verification should map to a strict state machine. Illegal transitions should be rejected and logged.
{
"legalFlow": [
"PAYMENT_CREATED",
"PAYMENT_PENDING",
"PAYMENT_FINALIZED",
"RECEIPT_PROOF_CREATED",
"ACCESS_UNLOCKED",
"MERCHANT_RECORD_WRITTEN"
],
"illegalExamples": [
"PAYMENT_PENDING -> ACCESS_UNLOCKED",
"UNKNOWN -> ACCESS_UNLOCKED",
"FAILED -> RECEIPT_PROOF_CREATED",
"DUPLICATE_REPLAY -> ACCESS_UNLOCKED"
],
"defaultSafeBehavior": "LOCKED_OR_UNKNOWN"
}
12. Production Readiness Checklist
- Merchant-scoped API keys without exposing backend secrets.
- Server-side receipt signing and verification.
- Replay/idempotency protection with TTL.
- Rate limiting per merchant/API key.
- Durable audit trail for verification attempts.
- Fail-secure handling for payment API timeouts, 502s, or ambiguous responses.
- No stack traces or internal infrastructure leakage in public errors.
- Privacy-preserving merchant evidence views.
- Pi-first adapter boundary with future chain-agnostic PaymentAdapter design.