Stablecoin payments do not work in test mode. You need a live API key
to create and accept USDT/USDC payments.
How it works
Create a payment request
Tell us how much to collect (in USD or GMD) and we give you back a payment
link.
Create a payment request
This creates the request and gives you a hosted payment page link to share.How much you want to collect.
Either
USD or GMD. If you send a GMD amount, we convert it to USD for
you at the current exchange rate, so the request itself is always in USD.
Defaults to USD.Any of your own notes you want stored with the request and handed back to you
later (for example, your order number). We return it to you untouched.
A web address where you want to be notified about this payment.
An optional deadline for the payment (ISO 8601 format).
The minimum is 5 USD. If you send a
GMD amount that converts to less
than $5, we reject it and tell you the current exchange rate.Only
amount is required. Add metadata if you want your own references sent
back to you in the notifications.json
link. That page handles the payment and accepts
USDT or USDC. The request starts off as status: "pending" (waiting for
payment).
Getting paid
Your customer pays on the hosted page, so you never deal with the payment method yourself. There’s one thing worth designing around: Two pieces of information tell you everything you need:amount— the total paid toward this request so far. It adds up across transfers. It is not the amount you originally asked for.status—partially_paidwhile the total is still short, andcompletedonce the full amount has arrived.
metadata.usd_amount. The
payment is done when amount reaches metadata.usd_amount, which is also the
moment status becomes completed.
List your payment requests
cURL
Look up a single payment request
cURL
Notifications (webhooks)
A webhook is just an automatic message we send to your web address whenever money comes in. When a payment is received, we send acharge.succeeded event.
You may get it more than once for the same payment as the running total grows.
The type of event, e.g.
charge.succeeded.The payment details. The main fields are below.
Total paid toward this payment so far, in USD. Adds up across transfers.
partially_paid until the full amount is in, then completed.The amount you originally asked for, in USD. Compare
amount against this to
know when the payment is fully covered.A list of each individual payment received, with
amount_paid_usd,
amount_paid_gmd, and timestamp.json
amount is 10 against an asked-for metadata.usd_amount of
20, so status is partially_paid. Once the remaining 10 is paid, amount
becomes 20 and status becomes completed.
To confirm a notification really came from Modem Pay (checking the signature
header), see the Webhooks guide.
Quick checklist
- Save the payment
id(and your own reference inmetadata) when you create the request. - Each time you get a
charge.succeededmessage, readpayload.amount(USD) and compare it topayload.metadata.usd_amount. - Treat the payment as done when
amountreachesusd_amountor whenstatusiscompleted. - Use
payload.metadata.payment_historyif you ever need to see the individual payments. - Make sure getting the same message twice for the same
iddoesn’t cause any double-counting.
