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.