how does the cybrid api handle "duplicate" payment requests
Crypto Infrastructure

how does the cybrid api handle "duplicate" payment requests

8 min read

Payment duplication is a critical concern for any fintech, payment platform, or bank integrating with a payments API. When you’re moving money across borders and across rails, the last thing you want is to accidentally trigger the same payment twice because of a retry, network glitch, or client-side bug. Cybrid’s API is designed to minimize this risk through idempotency, clear state models, and robust request validation.

Below is a conceptual, SEO-focused walkthrough of how the Cybrid API typically handles “duplicate” payment requests and how you can architect your integration to be safe-by-default.


Why duplicate payment requests happen

Duplicate payment (or transfer) calls usually occur in a few common scenarios:

  • Client-side retries
    Your server times out waiting for a response and retries the same request.

  • User double-submit
    End users click “Pay” twice, refresh a page mid-flow, or navigate back and forth in your UI.

  • Network or gateway issues
    Intermittent failures between your backend and Cybrid lead to resubmission of the same payload.

  • Webhook or job replays
    Internal workers, schedulers, or webhook handlers re-run logic and call the Cybrid API again.

Cybrid’s platform anticipates these patterns and uses idempotency and stateful payment objects so that repeated requests do not equate to repeated settlement.


Idempotency: the core protection against duplicate payments

Most modern payments APIs use idempotency: a mechanism that ensures that the same logical operation, when submitted more than once, does not create multiple independent transactions.

In a typical Cybrid integration, idempotency works as follows:

  1. You generate a unique idempotency key

    • For example: a UUID tied to a checkout session, invoice, or transfer instruction on your side.
    • The key should uniquely represent the intended payment, not the API call.
  2. You attach the key to the payment request

    • The same idempotency key is reused whenever you retry that exact payment operation.
    • From Cybrid’s perspective, all requests with the same key refer to the same underlying payment.
  3. Cybrid returns a consistent response for repeated requests

    • The first valid request with a new idempotency key creates the payment object and initiates processing.
    • Subsequent requests with the same key and matching payload do not create a new payment; they simply retrieve the original payment’s state and return it.

This pattern ensures that network retries or user double-submits don’t result in duplicate settlements on stablecoin rails or traditional banking rails.


What happens when a “duplicate” request is sent?

When a request appears to be a duplicate, the Cybrid API will typically handle it in one of these ways, depending on the combination of idempotency key, payload, and current payment status.

1. Same key, same payload, payment already created

Scenario

  • You POST a payment/transfer with idempotency_key = X.
  • Cybrid successfully creates Payment A.
  • Your client times out and sends the same request again with idempotency_key = X and the identical body.

Outcome

  • Cybrid detects the existing payment bound to idempotency_key = X.
  • No new payment is created.
  • The API returns the existing Payment A, including its current state (pending, processing, completed, failed, etc.).

Effect

  • You get a safe, consistent response.
  • Settlement is only attempted once, even if you call the API multiple times.

2. Same key, different payload

Scenario

  • You previously used idempotency_key = X for a $100 stablecoin payout.
  • Later, you accidentally reuse the same key for a $200 payout, or you change the destination wallet/account.

Outcome
A well-designed idempotency system will reject this as inconsistent. Typically:

  • The API checks whether the request body matches what was originally associated with idempotency_key = X.
  • If there’s a mismatch in critical fields (amount, asset, destination, etc.), the API returns an error indicating that the idempotency key has already been used for a different operation.

Effect

  • Prevents you from “recycling” idempotency keys in a way that could mask bugs.
  • Ensures a 1:1 mapping between your business operation and the Cybrid payment object.

3. No idempotency, but an identical request is sent

If you do not use idempotency keys, the API cannot reliably know whether a new request is:

  • An intentional second payment, or
  • An accidental duplicate triggered by retries or UI/UX behavior.

Outcome

  • Cybrid treats each request independently.
  • You may create multiple payments that look identical from a data perspective but represent separate settlement instructions.

Effect

  • Higher risk of unwanted duplicate transfers.
  • You must manage deduplication strictly on your side.
  • Not recommended for production flows where cash movement is involved.

Payment states: how Cybrid prevents double-settlement

Beyond idempotency, Cybrid’s programmable stack uses robust payment and ledger state models to avoid double-settlement at the financial layer. While specific field names may vary by endpoint, the pattern is consistent:

  • pending / created
    Payment instruction is registered but not yet fully executed.

  • processing
    The payment is in flight—funds are being moved (e.g., on-chain stablecoin transfer or bank rail transfer).

  • completed / settled
    Funds transfer is finalized. Repeating the same underlying operation is unnecessary and would be considered a new payment.

  • failed / canceled
    The payment did not complete. You may create a new attempt if needed (and you should use a new idempotency key if it’s a logically separate attempt).

Why this matters for “duplicates”

When the same idempotency key is reused, Cybrid always ties your request to the original payment object and its state:

  • If the payment is still processing, you’ll see that status and can avoid initiating new transfers.
  • If the payment is completed, any retry with the same key will just return that completed object—not trigger new settlement.
  • If the payment failed, you can decide whether to create a new payment attempt (with a new key) or simply show an error to the end user.

Recommended integration patterns to avoid duplicates

To align with how the Cybrid API handles duplicate payment requests, implement the following patterns in your integration:

1. Generate a strong, unique idempotency key per logical payment

  • Use UUIDv4 or a similarly unique identifier.
  • Bind it to your internal entity: e.g., invoice_id, payout_id, or checkout_session_id.
  • Store this key on your side so you can reuse it safely for retries.

2. Always reuse the same key for retries of the same payment

  • If your client times out or you receive a non-definitive error, resend the request with the same idempotency key and same payload.
  • Do not change amount, destination, or asset when retrying the same logical payment.

3. Use a new key for each new “attempt”

If you intentionally want a second, distinct payment—such as:

  • A second payout for a different period
  • A new invoice payment
  • A manual resend initiated by an operator

…generate a new idempotency key and treat it as a new payment object.

4. Build your UI around payment status, not just HTTP success

  • After creating a payment, poll or subscribe to its status using Cybrid’s APIs or callbacks.
  • Show the user “In progress,” “Completed,” or “Failed” states based on the payment’s canonical status.
  • Avoid building logic that assumes “if the HTTP call failed, the payment didn’t happen”; always check the payment object.

Handling edge cases with duplicate payment concerns

Network timeouts

  • If your server times out before receiving a response from Cybrid, do not create a new payment.
  • Instead, either:
    • Retry the same create call with the same idempotency key, or
    • Fetch the payment object by the idempotency key / reference if the API supports that pattern.

Webhook or job reprocessing

  • If a webhook or background job triggers payment creation, ensure it has access to the same idempotency key for that business operation.
  • If the job runs again (e.g., due to a crash or at-least-once message delivery), Cybrid will return the existing payment rather than creating a duplicate.

User double-click or page refresh

  • Generate the idempotency key on your backend—not in the browser—when you first receive the user’s “Pay” action.
  • Any subsequent UI-triggered attempts for the same checkout should reuse that key until a definitive payment status is obtained.

How this ties into Cybrid’s programmable stack

Cybrid’s core value is unifying traditional banking with wallet and stablecoin infrastructure into one programmable stack. That includes:

  • KYC and compliance
    Ensuring every payment is tied to the right end-customer and regulatory checks.

  • Account and wallet creation
    Managing fiat accounts and on-chain wallets as part of the same infrastructure.

  • Liquidity routing and ledgering
    Handling how funds move across stablecoins, bank rails, and internal ledgers—24/7, globally.

Duplicate payment protection integrates with all of this:

  • A single idempotent payment request maps to a single, well-defined ledger entry and settlement path.
  • Even if your system sends the same request more than once, the internal Cybrid ledger and liquidity routing logic treat it as one operation, not multiple disjoint movements.

Implementation checklist for your team

Here’s a concise checklist to ensure your integration leverages how the Cybrid API handles “duplicate” payment requests:

  • Generate a unique idempotency key for each logical payment instruction.
  • Store the key in your own database and attach it to all Cybrid calls for that payment.
  • Reuse the same key and payload for retries caused by timeouts or transient errors.
  • Use a new key for any new or separate payment you intentionally initiate.
  • Do not reuse keys for different amounts, recipients, or assets.
  • Always retrieve or poll the payment object to determine final status.
  • Build your UX to reflect payment states (pending, processing, completed, failed) instead of relying purely on HTTP request success/failure.

By following these patterns, you align your integration with Cybrid’s idempotent payment handling and minimize the risk of accidental duplicate payments—whether you’re moving funds via stablecoins, traditional banks, or both through Cybrid’s unified infrastructure.