USDC payment API: a developer's integration guide
August 11, 2026

Search for a USDC payment API and the results are dominated by stablecoin infrastructure companies rather than payment processors. That distinction is easy to miss while comparing feature lists, and it determines how much work lands on your team. An infrastructure API gives you the money movement and leaves compliance, settlement and reconciliation as your problem. A licensed processor takes those on.
This guide covers integrating USDC through the EukaPay API, where USDC is supported on Ethereum, and where a completed payment converts at a locked rate and settles to your bank account. It also covers the licensed-versus-infrastructure choice directly, because on this particular search result page it is the real decision.
In this guide, you'll learn:
What EukaPay supports for USDC, and the single-network implication for your integration
How to authenticate, create an invoice, and verify webhooks correctly
What a licensed processor covers that a stablecoin infrastructure API leaves to you
How to reconcile USDC payments against your accounting system
USDC on Ethereum
EukaPay supports USDC on Ethereum as an ERC-20 token, listed as Cryptocurrency ID 4 in the documentation's currency tables.
That identifier is worth reading carefully, because EukaPay maintains two separate numbering systems and they overlap. Cryptocurrency ID 4 is USD Coin on Ethereum. Fiat
currencyId4 is Pound Sterling. The
currencyIdfield you send when creating an invoice refers to the fiat table, not the crypto one, which is covered in detail further down.
Being explicit about that matters more than quoting a large number of supported assets. There is no USDC on Solana and no USDC on Tron at EukaPay. If your checkout offers a Solana USDC option, or your test plan assumes one, it will fail for a reason that has nothing to do with your code.
The single-network position has one useful consequence for your integration. Multi-chain USDC support sounds like a feature, and in practice it introduces the most expensive failure mode in stablecoin payments: a customer sending USDC on a network your address does not exist on. With one supported network, your checkout has one instruction to communicate and one address format to validate.
If your customer base holds stablecoins on Tron, note that EukaPay supports USDT there. Offering USDT on Tron alongside USDC on Ethereum covers both audiences, and both are the same integration.
Authenticating and creating your first invoice
Generate an API key in the merchant dashboard under Settings > Integrations > API keys. The secret appears once at creation.
curl "https://api.eukapay.com/invoices" \
-H "x-api-key: sk_live_YOUR_KEY"Production is
https://api.eukapay.comand staging is
https://api-stg.eukapay.com. Paths carry no version prefix, so the endpoint is
/invoicesrather than
/v1/invoices. Keys are environment-tagged with
sk_test_and
sk_live_prefixes.
Creating an invoice is a single call, and it should always carry an idempotency key:
curl -X POST "https://api.eukapay.com/invoices" \
-H "x-api-key: sk_live_YOUR_KEY" \
-H "x-idempotent-key: c41d7f8a-2b96-4e05-8a71-3fd6b09e5c42" \
-H "Content-Type: application/json" \
-d '{
"price": 620.00,
"currencyId": 2,
"number": "INV-260811-09",
"message": "Platform fee, Q3 2026",
"dueDate": "2026-08-25",
"redirectUri": "https://example.com/orderCompleted",
"metadata": { "externalId": "ord_5290", "productCode": "PLATFORM-Q3" }
}'Note what is not in that body: the cryptocurrency.
currencyId2 is the US Dollar, and the invoice is denominated in fiat. Your customer selects USDC at the payment screen from the currencies enabled on your account. Accepting USDC is therefore an account configuration plus an ordinary fiat-priced invoice, not a per-request currency choice.
The response returns the invoice
codeand a
paymentUrl:
{
"code": "inv_h2qjo7e1qpaled08q0cecn1cal",
"price": 620,
"number": "INV-260811-09",
"status": "Unpaid",
"paymentUrl": "https://app.eukapay.com/payments/inv_h2qjo7e1qpaled08q0cecn1cal",
"totalPaidAmount": 0,
"currency": { "name": "US Dollar", "unit": "USD", "sign": "US$" }
}The
x-idempotent-keyvalue is yours to generate, a V4 UUID is recommended, and keys expire after 24 hours. Derive it from your own order identifier and persist it before sending, so a timeout and retry cannot produce a second invoice for one order. A fresh key generated inside your retry logic protects nothing.
Two limits on
price: the minimum is 1 and the maximum is 100,000. Once the total reaches 1,000,
customerCodebecomes required along with
address1,
city,
stateand
countryon that customer, so create the customer with
POST /customersfirst for larger invoices.
Retrieve an invoice with
GET /invoices/{code}and list them with
GET /invoices.
Webhooks
Configure an endpoint under Settings > Integrations > Webhooks and drive your order state from events rather than polling for a status.
The eight events
EukaPay publishes eight webhook events. Four cover pay-ins and refunds, and four cover outbound payouts:
Event | Category |
|---|---|
| Pay-in |
| Pay-in |
| Pay-in |
| Refund |
| Payout |
| Payout |
| Payout |
| Payout |
Building your state machine on these named events is more reliable than depending on a status string, because each event corresponds to a decision your code has to make.
Verifying the signature - SHA-512
Every delivery carries an
x-eukapay-signatureheader holding an HMAC of the payload, keyed to that webhook's secret, using
SHA-512
. Most gateways use SHA-256, so treat the algorithm as a deliberate detail rather than a typo if a reviewer questions it.
const crypto = require('crypto');
function verifyEukaPaySignature(rawBody, signatureHeader, secret) {
const digest = crypto.createHmac('sha512', secret).update(rawBody).digest('hex');
if (digest.length !== signatureHeader.length) {
return false;
}
return crypto.timingSafeEqual(Buffer.from(digest), Buffer.from(signatureHeader));
}Use
timingSafeEqualrather than
===, since a plain comparison exits on the first differing character. Test the negative case as well: alter one byte of a payload, leave the signature alone, and confirm your handler rejects it.
One point to settle against your own account. EukaPay's documentation gives conflicting instructions here, with the written steps calling for the unaltered payload and the code sample re-serialising it with
JSON.stringify. Those inputs differ whenever key order or whitespace differs. Verify a real delivery against the raw body first, and try the re-serialised form only if that fails.
Duplicate deliveries
EukaPay retries a failed delivery every 20 minutes for up to two hours. Record the
webhookIdfrom each payload and return early on a repeat. Verify, deduplicate, return a 2xx quickly, then do the slow work asynchronously.
Payment payloads carry
webhookId,
event,
paymentCode,
paidAmount,
totalPaidAmount,
status,
paidDatetime,
invoiceCode,
invoiceNumber,
invoicedAmountand
invoiceCurrency.
invoiceCodeis your join key back to your own order.
Licensed processor or stablecoin infrastructure
This is the decision the USDC payment API search results obscure, and it is worth making deliberately.
Stablecoin infrastructure APIs are good at moving tokens. What they generally do not do is take on the regulated parts of accepting a payment. The work does not disappear, it moves to your team.
Capability | Stablecoin infrastructure API | EukaPay |
|---|---|---|
Moves USDC on-chain | Yes | Yes |
Registered money services business | Usually not | FINTRAC in Canada, FinCEN in the United States |
Converts to fiat at a locked rate | Rarely | Yes, to remove all crypto volatility |
Settles to a business bank account | Often not | USD, EUR, GBP, CAD, plus Interac for Canadian merchants |
Screens outbound transfers | Your responsibility | Surfaced as the Reviewingpayout status |
Refunds as an API operation | Varies | POST /refunds, GET /refunds |
Who holds the compliance obligation | You | EukaPay |
That last row is the one to weigh carefully. An infrastructure provider that is not a registered money services business is not taking on your obligations, whatever the integration looks like. If you accept customer payments at any scale, someone has to hold that responsibility.
The
Reviewingpayout status is a small, concrete illustration. EukaPay's crypto payout statuses are
Pending,
Reviewing,
Processing,
Sent,
Errorand
Revoked.
Reviewingexists because a registered processor screens outbound transfers, and it appears in the API rather than as a silent delay. An infrastructure API has no equivalent status because it is not performing that function.
None of this makes infrastructure APIs the wrong choice. If you are building a wallet or a protocol-level product, raw money movement is exactly what you want. For a business accepting payment for goods and services, the calculation usually runs the other way.
Settlement and reconciliation
A completed USDC payment converts at a locked exchange rate to remove all crypto volatility, and settles to your bank account in USD, EUR, GBP, CAD.
For month-end, cursor pagination handles period pulls.
GET /invoicesaccepts
limitwith either
starting_afteror
ending_before, never both, and returns a
{data, has_more}envelope. Page until
has_moreis false.
One trap when writing a shared pagination helper: default page sizes differ by resource. Invoices default to 100, while customers, refunds and crypto payouts default to 10. Set
limitexplicitly.
Store two identifiers against your own order record at write time. The
invoiceCodeties your order to the invoice and appears in every webhook payload. The
x-request-id, returned on every API response, is what support will ask for if a specific call needs investigating. Capturing both at write time turns reconciliation into a join rather than a manual match against a bank statement.
Testing on Sepolia
USDC on Ethereum tests on
Sepolia
.
Register for staging at
stg.eukapay.comand call
https://api-stg.eukapay.comwith a
sk_test_key. Staging verification emails are not sent automatically, so request approval from
support@eukapay.com. Test USDC comes from EukaPay support rather than a public faucet, so ask for both in one message.
Rehearse these before going live:
The happy path end to end, with
paymentCompleteddriving your order state
Underpayment, which commonly occurs when an exchange deducts its withdrawal fee from the amount a customer sends
Overpayment, confirming your fulfilment logic does not reject a payment for failing an equality check
A replayed webhook, confirming
webhookIddeduplication works
A tampered payload, confirming signature verification returns false
A 429, confirming your client backs off. EukaPay documents rate limiting and recommends exponential backoff without publishing a specific requests-per-second figure, so build against the response rather than a threshold
Every EukaPay merchant goes through an onboarding and business review process, and there is no instant registration. The sandbox is available during that review, so the integration is usually finished before the commercial process is.
One platform underneath
USDC is one currency on a platform that handles all of them identically: instant crypto-to-fiat conversion at a locked exchange rate to remove all crypto volatility, protection against chargebacks, support for a wide range of cryptocurrencies, and settlement in USD, EUR, GBP, CAD to your bank account. EukaPay supports most major cryptocurrencies like BTC, ETH, LTC, SOL, USDC, USDT.
Invoices, payment links, hosted checkouts, subscriptions that send invoices on a recurring schedule, refunds and crypto payouts all run on one account. Adding USDT on Ethereum or Tron alongside USDC is a currency configuration, not a second integration, and the endpoints and webhook events do not change.
Get started with EukaPay
Create an account at
, complete verification, provide your legal business information, then generate an API key.
The full reference, including the currency table, request schemas and every error type, is public at
. An official documentation MCP server is available at
docs.eukapay.com/mcpfor coding agents. For the merchant-facing view rather than the developer detail, see
.
Frequently asked questions
Which networks does EukaPay support for USDC?
Ethereum only, as an ERC-20 token. There is no USDC on Solana or Tron at EukaPay. USDT is available on both Ethereum and Tron.
Is EukaPay a licensed payment processor?
Yes. EukaPay is registered with FINTRAC in Canada and with FinCEN in the United States, which is the main difference from a stablecoin infrastructure API that moves tokens without holding a compliance obligation.
What currency will my USDC payments settle in?
Your chosen fiat, settled to your bank account in USD, EUR, GBP, CAD, with Interac withdrawals available for Canadian merchants.
What signature algorithm does EukaPay use for webhooks?
HMAC SHA-512, in the
x-eukapay-signatureheader, computed over the raw request body.
How do I avoid creating duplicate invoices on retry?
Send an
x-idempotent-keyheader derived from your own order identifier, persisted before the request is sent. Keys expire after 24 hours.
Can I refund a USDC payment through the API?
Yes.
POST /refundscreates a refund and
GET /refundslists them, with statuses of
Created,
Pending,
Success,
Failand
Unknown.
Which testnet should I use for USDC?
Sepolia. Test USDC is provided by EukaPay support rather than a public faucet.
How do I reconcile USDC payments at month-end?
Page
GET /invoiceswith
limitand a cursor until
has_moreis false, and join on the
invoiceCodeyou stored against your own order record.
Products
Use Cases
© 2026 EukaPay. All rights reserved.
FINTRAC: M22233887