SafeGate v5.2 / API Contract / Error Boundary

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.

Public boundary: This is a contract and architecture page. It is not a production public API, does not expose API keys, does not expose backend secrets, and does not claim Pi Mainnet settlement proof.

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.

SafeGate principle:
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"
}
These headers are future production design boundaries only. SafeGate does not currently expose a public API key system.

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

13. Related Pages