Crypto payment integration: wiring a second rail into a checkout you already have
September 03, 2026

The decision to accept stablecoins or crypto is usually made before an engineer sees a ticket. What lands on the backlog is the harder question: how a second payment rail sits next to the card processor, the order database, and the fulfillment logic already in place. A checkout that has run on one processor for years does not need a rewrite. It needs one more payment method that reports back the same way the others do.
This walks through the pieces of a crypto payment integration on EukaPay: where the invoice endpoint sits relative to an existing checkout button, and what a webhook confirms and when it fires. It also covers how an idempotency key stops a retried request from duplicating an invoice, and what still has to be built.
In this guide, you'll learn:
Where a crypto payment rail fits next to an existing checkout without a rewrite
What the invoice request shape looks like and which fields route a payment back to an order
Which webhook events confirm a payment, an underpayment, or a refund, and how to verify they came from EukaPay
What EukaPay's API covers, and what stays outside it
Adding crypto as a payment method, not replacing the checkout
A crypto payment integration is additive. The existing checkout keeps its card processor, order records, and fulfillment logic. Crypto shows up as one more option where a customer chooses how to pay, the same way a second card processor would.
When a customer selects the crypto payment option, the backend creates an invoice through the
and gets back a payment page URL. The checkout redirects the customer to that URL, and EukaPay's hosted payment page handles wallet connection, network selection, and on-chain confirmation in the browser. Nothing about the card flow changes, and EukaPay's side does not need to know anything about the card processor sitting next to it.
The redirect handoff - what the checkout sends and gets back
The checkout needs three things to hand off correctly: an order total, a way to tie the payment back to that order, and a URL to send the customer to once done. EukaPay's Create Invoice endpoint takes all three, plus a setting for which currency the merchant ends up holding.
{
"price": 129.00,
"currencyId": 1,
"customerCode": "cus_q06lpsoz2v7cwd5mn2tlxkr2jvjxxi",
"redirectUri": "https://example.com/orderCompleted",
"receiveCurrencyType": "fiat"
}price and currencyId set what the customer owes and the fiat currency it is denominated in. customerCode ties the invoice to a buyer record created through the customers endpoint. Above an invoice total of 1,000 in that currency, the customer record must include address1, city, state, and country. redirectUri is the page EukaPay sends the customer's browser to once payment completes, which is how the checkout resumes control of the session. receiveCurrencyType decides whether the invoice settles to the merchant in fiat or crypto, independent of what the customer paid with. Fiat settlement converts crypto to fiat at a locked exchange rate to remove exposure to crypto price swings, landing in a balance denominated in USD, EUR, GBP, or CAD.
A request that includes an x-idempotent-key header can be retried after a timeout without duplicating the invoice, covered below.
What a webhook confirms, and when it fires
Once the invoice exists, the checkout's job is mostly done. Everything that happens after that, whether the customer paid in full, underpaid, overpaid, or later triggered a refund, arrives as a webhook: an HTTPS POST to an endpoint registered in EukaPay Settings > Integrations > Webhooks. A confirmation shown on the page the customer sees is not something a backend can trust for order fulfillment; the webhook is the record that matters.
Event types - what each one means for the order record
Four event types cover a payment's outcome. paymentCompleted fires when the sum of payments for an invoice matches the requested amount. paymentUnderpaid fires when a payment lands short, which can happen when network fees are deducted from a sent amount. paymentOverpaid fires when the total exceeds the requested amount, and refundCompleted fires once a refund is processed. Each payload carries a paymentCode or refundCode and the matching invoiceCode, so the handler can look up the order without polling.
{
"event": "paymentUnderpaid",
"paymentCode": "pym_p9l9sd5wina08tbfikx9xgu8n",
"paidAmount": 500,
"totalPaidAmount": 1000,
"invoiceCode": "inv_ozqtnhhavpgcyas32qxnlgkykx",
"invoicedAmount": 3000
}A card integration rarely has to build for this, since a card charge either succeeds for the full amount or does not go through. A crypto pay-in can settle at a different total than requested, so the handler needs its own branch for paymentUnderpaid and paymentOverpaid instead of treating every payment webhook as completed.
Verifying the sender - the signature header before you trust a payload
Before a webhook handler acts on a payload, it should confirm EukaPay sent it. Every webhook carries an x-eukapay-signature header. The receiving server computes an HMAC SHA-512 digest of the raw request body, in bytes, using the merchant's secret key, and compares that against the header value. A mismatch means the payload gets discarded, not processed.
Idempotency and retries
A network timeout does not tell the caller whether the request landed. Retrying blind risks a duplicate invoice. EukaPay's API supports idempotency for this: a POST or PUT request carrying an x-idempotent-key header, set to a client-generated unique value such as a V4 UUID, is safe to retry. The API stores the request body and resulting status against that key, and a later request with the same key returns the original result instead of repeating the operation. Keys are eligible for removal after 24 hours, so do not reuse one past that window. Send one on every POST and PUT call; GET and DELETE do not need one.
What EukaPay's API covers for this integration
The documented API surface for a crypto payment integration is invoices, subscriptions, customers, payouts, and balance transfer, covered in full at
. That surface is scoped to merchant acceptance and payouts. EukaPay does not issue or mint the stablecoins it processes and is not the chain infrastructure layer moving assets between wallets. Companies like Circle, Fireblocks, BVNK, Bridge, and Zerohash sit below that layer, in stablecoin issuance and cross-chain settlement infrastructure. A crypto payment integration built against EukaPay's API is the layer a checkout talks to directly: creating invoices, receiving webhook confirmations, and moving a settled balance.
Get started with EukaPay
Read the
for the invoice, customer, subscription, payout, and balance endpoints above, including authentication and pagination. When ready to test against real endpoints,
and generate an API key from the merchant dashboard.
Frequently asked questions
Does a crypto payment integration replace an existing card processor?
No. It sits alongside the checkout as an additional payment method. The card processor, order database, and fulfillment logic stay unchanged.
What happens if a customer sends less than the invoice amount?
EukaPay sends a paymentUnderpaid webhook with the amount paid and the amount still outstanding, so the handler can flag the order instead of treating it as complete.
How do I know a webhook actually came from EukaPay?
Every webhook carries an x-eukapay-signature header. Compute an HMAC SHA-512 digest of the raw payload with the merchant's secret key and compare it against that header before acting.
Does EukaPay's API support recurring billing?
The subscriptions endpoint sends invoices on a recurring schedule from daily to annually. It does not include plan management or programmatic billing-cycle control.
What currencies can a merchant settle in?
Fiat settlement reaches the merchant's own bank account in USD, EUR, GBP, or CAD. Crypto settlement is also available, set per invoice through receiveCurrencyType.
Does EukaPay issue the stablecoins it processes?
No. EukaPay does not issue, mint, or hold reserves for any stablecoin. Issuance sits with issuers below the merchant-acceptance layer, such as the companies named above.
How long is an idempotency key valid for a retry?
24 hours. After that window, a retried request with the same key is no longer guaranteed to return the original result.
Can a payout be requested through the same API?
Yes. Payouts sit alongside invoices, subscriptions, customers, and balance transfer in the documented API surface, with their own endpoints in the API documentation.
Related articles
- the endpoint-by-endpoint breakdown of what EukaPay's payment API exposes.
- how the wider stablecoin payments platform fits around this integration.
- the managed alternative to building the integration in house.
Products
Use Cases
© 2026 EukaPay. All rights reserved.
FINTRAC: M22233887