Skip to main content

Error Handling

Use the following guidelines for handling errors in the system.

Idempotency and Request Handling

All payment-related API calls have idempotency built into them. To leverage idempotency, pass the x-idempotency-key header with each API request. There is no harm in making the same API call multiple times with the same key. Note however that any changes to the request after the initial request will likely not be processed if the original request was successful.

Payment Errors

The system does not consider a payment decline an HTTP error. We do not use HTTP response codes to indicate failure of a successful call to the payment provider (card brands or banks). Inspect the status field returned to understand if the payment was successful or not. Common status values include:

  • succeeded: Payment completed successfully
  • failed: Payment was declined or failed
  • pending: Payment is being processed
  • created: Initial state, ready for payment attempt

Non-200 HTTP errors are used to indicate either a logic error (e.g., validation, configuration) or a system error.

Retries and Preventing Duplicates

There are several things that happen during the processing of a payment, from validation to fraud detection to persisting across our distributed system. While we take extreme measures to ensure that when things go wrong they are handled, there are times when unexpected behavior occurs. If you experience a 500 code error, often times it is best to not attempt the transaction again. Keep reading for best practices.

Best Practices

Create one Payment Intent per Checkout Experience

Creating one Payment Intent (PI) and using that PI to both collect payment data and attach payments to for an entire session is the correct way to use the API. If a payment fails, perhaps due to a decline or system error, continue to use the PI for new payment methods and new attempts. Do not create a new PI if the first payment attempt fails, as doing so will bypass a number of guards the system has in place to prevent issues such as duplicates. A great technique is to use your unique checkout cart id as the reference id on the PI (ex. cart_123456), and either a unique id or postfix per payment attempt (ex. cart_123456-1, cart_123456-2, etc.)

Always Use Idempotency Keys

Leverage idempotency keys to prevent duplicate charges to a customer. Each unique operation should have its own idempotency key that remains consistent across retries.

Handling 500 Errors for Payments

In the rare event that you receive a system error when creating a payment, you should fetch the Payment Intent by ID and inspect the status:

  • If the status is created, you can make additional payment attempts. Our team will be alerted to such errors and will investigate the primary issue, but feel free to reach out to support.
  • If the status is pending, this indicates an error late in the processing attempt. Best practice is to not process this payment again (assume the payment went through), and provide guidance to the end user to not attempt additional payments. This very specific error comes with special handling by our team and in almost all cases we can resolve the issue. You can make API calls to check on the status of the PI to see if it was processed by our team, or you can listen to webhooks for updates on when the payment gets processed.