Skip to main content

Frequently Asked Questions

Quick answers to the most common questions merchants ask about Odus.

1. What does the requires_action status mean?

A payment moves to requires_action when the customer must complete an additional step before processing can continue — most commonly a 3D Secure (3DS) authentication redirect. The payment object will include an action.redirectUrl that points the customer to the authentication page.

Once the customer completes the action, the payment transitions to succeeded. If the action is not completed within 24 hours, the payment resets to open so a new attempt can be made.

See Payment Statuses for the full state machine.

2. Why was my payment declined?

Every failed payment includes an outcome object on the transaction with a standardized errorCode, a declineType (soft_decline or hard_decline), and a safeErrorMessage suitable for display to customers.

Common reasons:

CodeMeaning
insufficient_fundsThe card does not have enough balance.
expired_cardThe card is past its expiry date.
invalid_card_detailsThe card number, CVV, or other details are incorrect.
authentication_failed3DS or cardholder authentication failed.
fraud_suspectedThe processor flagged the transaction as potentially fraudulent.
generic_processor_errorA transient processor error — retrying may succeed.

Hard declines (fraud_suspected, card_restricted, generic_hard_decline) will not succeed on retry with the same card. Soft declines may succeed if retried or if the customer updates their payment method.

See Error Codes for the full reference.

3. How do I set up webhooks?

  1. In the Dashboard, go to Developers > Webhook Subscribers and create a subscriber.
  2. Save the generated shared secret — it is used to verify payload authenticity.
  3. Expose a publicly accessible HTTPS endpoint that accepts POST requests.
  4. Validate incoming requests by computing the HMAC-SHA256 of the request body using your shared secret and comparing it to the X-Webhook-HMAC header.
  5. Respond with a 2xx status code to acknowledge receipt.

Webhooks are delivered at least once and retried up to 10 times over 3 days with exponential backoff. Use the eventId field to deduplicate.

See Webhooks for the full guide.

4. How do cascades work?

A cascade defines which gateway profiles process your payments and in what order. When one gateway fails, Odus automatically routes to the next gateway — no action required from you.

Three routing algorithms are available:

  • Round-robin — distributes payments evenly across gateways.
  • Weighted round-robin — distributes by percentage weight (e.g., 70/30).
  • Priority queue — always tries the highest-priority gateway first, falling back on failure.

Each gateway in a cascade can have optional transaction limits and caps per day, week, or month.

See How Cascade Routing Works and Configuring Cascades.

5. How does the retry policy work for failed subscription payments?

When a subscription renewal charge fails, Odus automatically retries according to your retry policy. A policy contains ordered steps, each with:

  • retryDelay — days to wait before retrying.
  • useInitialGateway — whether to retry on the same gateway or target a different one.
  • priceReductionPercentage — optionally reduce the charge amount for that attempt.

Every merchant account has a default retry policy. You can create custom policies and assign them to specific subscriptions.

See Configure a Payment Retry Policy.

6. How do I authenticate API requests?

Include your secret key as a Bearer token in the Authorization header:

Authorization: Bearer skey_your_secret_key_here

Secret keys (skey_ prefix) are for server-side use only. Publishable keys (pk_ prefix) are safe for client-side code but have limited permissions.

Create and manage keys in the Dashboard under Developers > Access Keys.

See Authentication.

7. What is the difference between status and displayStatus?

status is the core lifecycle field with four values: open, requires_action, succeeded, and cancelled. Use it in your integration logic.

displayStatus is a derived, human-friendly label (e.g., uncaptured, retrying, partially_reversed) computed from status and the boolean lifecycle flags. It is useful for UI display but should not drive business logic — new values may be added in future releases.

See Payment Statuses.

8. How do I capture a payment manually?

If your payment was created with captureMethod: "manual", the payment will move to succeeded with isCaptured: false (displayStatus: uncaptured) after authorization. To capture:

POST /payments/{id}/capture

You can capture the full authorized amount or a partial amount. Uncaptured authorizations expire according to the processor's hold period (typically 7 days).

See Capture.

9. How do I test payments without processing real charges?

Odus provides a test mode where you can simulate payments, declines, and 3DS flows without hitting live gateways. Use your test-mode API keys (available in the Dashboard) to make requests against the same API endpoints.

See Testing Resources for test card numbers and simulation scenarios.

10. How do I handle 3DS redirects in my checkout flow?

When a payment returns status: "requires_action" with an action.redirectUrl:

  1. Redirect the customer to the URL (or open it in an iframe/popup).
  2. The customer completes authentication with their bank.
  3. The bank redirects back to your configured return URL.
  4. Odus automatically finalizes the payment — poll or listen for the payment.updated webhook to confirm the outcome.

If you use the Odus Checkout SDK, 3DS handling is built in automatically.

See 3DS and Redirect Handling.