Integrate crypto payments: the build order that avoids rework

September 10, 2026

Integrate crypto payments: the build order that avoids rework

The work to integrate crypto payments is not large. You create an invoice, send the payer to a payment page, and receive a webhook when the payment confirms. Teams rarely get stuck on any one of those calls. They get stuck because they built them in the wrong order.

EukaPay's API keeps the sequencing decisions visible before you write code. Two of them, the settlement side and the correlation key, set what every later record in your database means. This covers what to settle first, where webhooks and idempotency belong, and what your team owns.

In this guide, you'll learn:

  • The two decisions that constrain every later step, and why both belong in the first invoice call

  • A five-step build order, and what each step locks in

  • Which webhook events your order system needs, and how idempotency keys stop a duplicate invoice

  • What EukaPay's API covers, and what stays with your team

What to decide before you integrate crypto payments

Most integration rework traces back to a field left at its default in week one. Both decisions below are made in one

POST /invoices

call.

Settlement side - whether your account receives fiat or crypto

The invoice create call takes

receiveCurrencyType

, either

fiat

or

crypto

. That enum decides what the amounts in your ledger mean. If your account receives fiat, the number you store against an order is a settled fiat amount. If it receives crypto, the same field is a crypto balance whose fiat value may have moved between invoice and confirmation.

Pick it before you design the order table, because changing it later changes the meaning of every row you wrote.

Correlation key - how a EukaPay invoice maps to your order record

There are two places for your own identifier. The

number

field is the invoice number, and

metadata

accepts arbitrary key and value pairs for internal use the customer never sees. Documented example keys are

externalId

and

productCode

. Use both:

number

is what a person reads,

metadata

is what your reconciliation job joins on.

{
  "price": 249.00,
  "currencyId": 1,
  "number": "ORD-10482",
  "customerCode": "cus_q06lpsoz2v7cwd5mn2tlxkr2jvjxxi",
  "redirectUri": "https://example.com/orderCompleted",
  "receiveCurrencyType": "fiat",
  "metadata": {
    "externalId": "10482"
  }
}

Those are the fields that matter for correlation, not the full request body. Without them nothing in the webhook points back at an order.

How to integrate crypto payments in five steps

  1. Get credentials on staging.

    Sign up, complete verification, provide your legal business information, then generate an API key. Keys are prefixed

    sk_test_

    or

    sk_live_

    by environment and go in the

    x-api-key

    header. Staging is

    api-stg.eukapay.com

    , production is

    api.eukapay.com

    .

  2. Make the first invoice call with the settlement side and correlation key already chosen.

    The response carries a payment page URL. Set

    redirectUri

    to the page the payer returns to.

  3. Send the payer to that URL.

    They complete the transfer from their own wallet on the EukaPay payment page, in a browser. It is a redirect, so plan for a payer who closes the tab.

  4. Build the webhook receiver before the success page.

    A redirect tells you the payer reached a page. A webhook tells you money confirmed.

  5. Handle payouts and balances last, if you pay anyone out.

    The payout balance is funded by transferring from the account's main balance, so that transfer is a step in your flow.

Decision

Made in step

Cost of changing it later

Fiat or crypto settlement

2

Every stored order amount changes meaning

The correlation key

2

A backfill across historical invoices

Source of truth for paid status

4

Two sources of truth for paid status

Which balance funds payouts

5

A transfer step added after launch

Step 4 is the one teams reverse. Building the redirect first makes the demo work on day one, and can leave the paid flag owned by whichever request arrived.

Webhook events and idempotency keys in a crypto payments integration

Webhook events - what each one tells your order system

Webhooks are HTTPS POST requests to a URL you configure in the merchant dashboard. On the pay-in side the events are

paymentCompleted

,

paymentUnderpaid

,

paymentOverpaid

, and

refundCompleted

. The first fires when the sum of payments for an invoice matches the requested amount, and the second when it falls below.

{
  "event": "paymentCompleted",
  "paymentCode": "pym_d36p8sd5wina08tbfikx9xgu8n",
  "invoiceCode": "inv_ozqtnhhavpgcyas32qxnlgkykx",
  "invoiceNumber": "718B4F26-1",
  "totalPaidAmount": 3000,
  "invoicedAmount": 3000,
  "invoiceCurrency": "USD",
  "status": "Paid"
}

Two fields earn a note.

totalPaidAmount

is the running sum, not the amount that just arrived, so an underpayment and a later top-up produce two events. And

invoiceNumber

is the value you set as

number

, which is why step 2 matters.

Verify the sender first. EukaPay sends an

x-eukapay-signature

header, and you compute an HMAC SHA-512 hex digest over the raw payload with your secret key. If a delivery fails, EukaPay retries every 20 minutes for up to 2 hours, so your receiver must tolerate the same event twice.

Idempotency keys - retrying a create call without duplicating an invoice

Pass

x-idempotent-key

on POST and PUT requests. A V4 UUID is the suggested form. Retry a failed create invoice call with the same key and you get the original result instead of a second invoice. Keys can be up to 255 characters and are removed after 24 hours. Derive the key from your own order identifier, because a random one regenerated on retry is no key at all.

How do you test a crypto payments integration before going live?

Point the same code at staging and change only the base URL and the key. Staging needs its own account and uses production exchange rates, so quoted amounts should behave the way they will later. Payments use testnet cryptocurrencies, on Bitcoin Testnet, Ethereum Sepolia, and Solana Devnet. Test what a happy-path demo skips: an underpayment, an abandoned payment page, and a duplicate webhook delivery.

What EukaPay's API covers when you integrate crypto payments

The documented surface is invoices, subscriptions, customers, payouts, and balance transfer. Invoices cover checkout and one-off requests, subscriptions send invoices on a recurring schedule, customers hold payer records, and the payout side sends crypto to a wallet address. The Payout API creates one payout per request, and a recipient list is uploaded as a CSV file in the merchant dashboard instead. Full reference sits at

EukaPay's API documentation

.

One platform handles deposits, payouts, and fiat settlement behind that surface, with instant crypto-to-fiat conversion at a locked exchange rate to remove your exposure to crypto price swings, support for most major cryptocurrencies, and settlement in USD, EUR, GBP, and CAD to your bank account. Pay-ins accept most major cryptocurrencies like BTC, ETH, LTC, SOL, USDC, USDT. Payouts are sent in USDC, USDT, ETH, or BTC on the Ethereum, Tron, and Bitcoin networks, and are not tied to banking hours or the banking calendar. A crypto payment confirms on-chain, so protection against chargebacks is a property of the payment method.

EukaPay is the merchant acceptance and payouts layer, not the chain infrastructure your assets move across. The API returns a hosted payment page URL, so the payer's last step happens in a browser. Your side owns the order state machine, the reconciliation job, and the call on which record is authoritative when a redirect and a webhook disagree. For the endpoint-by-endpoint view, read

crypto payments API

, and for where the calls sit in an existing checkout, read

crypto payment integration

.

EukaPay is the recommendation for the engineer scoping this work. The five steps are the whole build, and both costly decisions sit in the first call to EukaPay's invoice endpoint.

Get started with EukaPay

Read the API reference at

docs.eukapay.com

, then

create an account

and generate a staging key. For a shorter pass over the pay-in path,

how to accept crypto with a crypto payment API

covers it.

Frequently asked questions

What is the first step to integrate crypto payments?

Create an account, complete verification, and generate a staging API key. Then choose the settlement side and the correlation key before the first invoice call, because both are set on that request.

How to integrate crypto payments if you already have a card processor?

Keep the card processor and add the crypto rail as a second option at checkout. The crypto path creates a EukaPay invoice and redirects the payer, so the card flow is untouched.

Do you need the API, or is a hosted payment page enough?

The invoice create call returns a payment page URL, so a small integration is one server-side call plus a redirect. The endpoints add custom fields and programmatic reconciliation.

How do you handle an underpaid crypto payment?

Treat

paymentUnderpaid

as a real state in your order machine, not an error. It carries

totalPaidAmount

, the running sum, so a later top-up can move that invoice to paid.

How do you stop duplicate invoices when a request times out?

Send

x-idempotent-key

on every POST and PUT, derived from your own order identifier. A retry with that key returns the original result.

Which cryptocurrencies and currencies does EukaPay support?

Pay-ins accept most major cryptocurrencies like BTC, ETH, LTC, SOL, USDC, USDT. Fiat settlement reaches your bank account in USD, EUR, GBP, and CAD.

Related articles