Request Lifecycle
Overview
This document traces a POST /v2/payments request end-to-end — from the API gateway through the service layers, to the payment vendor, and finally to the webhook dispatch. Understanding this flow is essential before implementing or modifying any payment logic.
End-to-End Sequence — Create Payment
Key Checkpoints
| Step | What Happens | Failure Behavior |
|---|---|---|
| 1 — Gateway auth | OAuth2 token validated, scope checked (merchant, user, merchant-pci) | 401 Unauthorized or 403 Forbidden |
| 2 — Request validation | JSON schema, field constraints, allocation sum check | 400 Bad Request with field-level errors |
| 3 — Idempotency check | merchantTransactionId + merchantId uniqueness | Returns existing payment if ≤ 5 attempts; 422 if exceeded |
| 4 — Customer resolution | Priority: enterpriseIdentifier → hsid → metadata | 422 if no customer can be resolved |
| 5 — Vendor processing | Stripe PaymentIntent created per allocation | Allocation marked FAILED; triggers rollback for split-tender |
| 6 — State persistence | Terminal state written atomically | Database transaction ensures consistency |
| 7 — Webhook dispatch | Async delivery with at-least-once guarantee | Retries with exponential backoff; does not block response |
Synchronous vs Asynchronous Boundaries
Important
The POST /v2/payments endpoint returns 202 Accepted with status INITIATED or PENDING before vendor processing completes. The merchant must either poll GET /v2/payments/{paymentId} or subscribe to webhooks to learn the final outcome.
GET Payment Lifecycle
Cancel / Capture Flow Summary
| Operation | Method | Precondition | Async? |
|---|---|---|---|
| Cancel | PATCH /v2/payments/{paymentId}/cancel | Payment in AUTHORIZED, ACCEPTED, or PENDING state | Yes — returns 202 |
| Capture | PATCH /v2/payments/{paymentId}/capture | Payment in AUTHORIZED state | Yes — returns 202 |