Production checklist
Before you move real money.
Most production incidents in payments are not exotic. A retry without an idempotency key, a webhook handled twice, a timeout shown to the customer as a failure. Check these before go-live.
Credentials and environments
- Production API keys are created separately from sandbox keys. Credentials do not cross environments.
- Keys are stored in a secrets manager, never in client-side code or mobile apps.
- Requests that target a project send x-project-id.
- Your base URL switches between sandbox and production through configuration, not code changes.
Provider configuration
- Every provider and rail you rely on is configured for your production tenant, not only in sandbox.
- You have checked the integration status (Production, Private Preview, In Development) for each provider you depend on.
- For routed pay-ins, you have reviewed the route order for each product and know which provider is primary.
- For payouts, you know which provider executes each product. Payout failover is in development, so a second payout provider is not tried automatically.
Idempotency
- Every payout request carries an idempotency_key that you generate and persist before sending the request.
- Retries of the same business operation reuse the same key. A new key means a new payout.
- Checkout payment creation has no idempotency key today. Store the payment_id as soon as it is returned, and if a create call times out, find the existing payment before creating another.
- You persist the payoutId or paymentId returned by Orangepill against your own record.
Webhooks
- Every callback is registered with a secret, and every delivery is verified (HMAC-SHA256 over timestamp.body).
- Deliveries with a stale X-Orangepill-Timestamp are rejected.
- Events are deduplicated on the event id. Your handler is safe to run twice.
- Your handler responds quickly with 2xx and does slow work asynchronously. Deliveries time out after 10 seconds.
- You do not rely on event order. When in doubt, read the current status from the API.
Timeouts and retries
- A timeout on your request is treated as unknown, not as failure.
- After a timeout you read the existing operation (or retry with the same idempotency key) before doing anything else.
- Non-terminal statuses (pending, processing, requires_action, awaiting_collection) are shown to users as in progress, never as failed.
- A payout that is failed with errorCode RETRY_EXHAUSTED is treated as unknown and escalated, not paid again.
- Payout reservations are currently released after one hour even if the payout is still pending. Payouts that stay non-terminal for that long are escalated to operations.
Failure testing
- In sandbox you have tested success, insufficient funds, expired card, wrong CVC, timeout, rate limiting and network errors.
- You have tested duplicate webhook delivery and out-of-order events.
- You have tested a client retry after a timeout, with the same idempotency key.
- You have tested what your product shows while an operation is non-terminal.
Monitoring and escalation
- You alert on operations that stay non-terminal longer than you expect for that provider and rail.
- You monitor webhook delivery failures, which are visible in the delivery history routes.
- Your operations team can open a payment or payout and see its status, timeline and attempts.
- There is a named owner and a path to Orangepill for operations whose outcome cannot be established.
Review your go-live with us.
Bring your integration and the flows you plan to launch first.