POST /transaction/mint-request
Use this API to request a IDRX minting transaction in one of our supported chains.
POST https://api.idrx.co/transaction/mint-requestQuick start
curl -X POST 'https://api.idrx.co/transaction/mint-request' \
-H 'idrx-api-key: <API_KEY>' \
-H 'idrx-api-sig: <SIGNATURE>' \
-H 'idrx-api-ts: <TIMESTAMP>' \
-H 'Content-Type: application/json' \
-H 'User-Agent: my-app/1.0' \
-d '{
"toBeMinted": "20000",
"destinationWalletAddress": "0x7D1398C397C64368B7079bD5b3EE904aaaf8A495",
"networkChainId": "8453",
"returnUrl": "https://your-app.example.com/callback",
"requestType": "idrx"
}'Redirect the user to data.paymentUrl from the response. After payment, IDRX is delivered to the wallet — usually within minutes.
For end-to-end integration including status tracking and reconciliation, see Processing Mint IDRX Requests.
Authentication
Every request needs four headers:
idrx-api-key
Your API key
idrx-api-sig
HMAC-SHA256 signature (see formula below)
idrx-api-ts
Unix timestamp in milliseconds
User-Agent
Custom string like my-app/1.0 (why)
Signature formula
For GET requests with no body, use SHA256("").
Full guide: Generating a Signature
API keys are issued via:
Custom User-Agent required. Defaults from curl, Python-urllib, or generic SDK strings are blocked at the edge with HTTP 403 (Cloudflare error 1010).
Parameters
toBeMinted
string
✓
Amount to mint. Min 20,000 IDR or 2 USD. Max 1,000,000,000 IDR or 5,555 USD. Must be a whole number on Polygon and BNB Chain, and may carry at most 2 decimals on the other chains — see the note below.
destinationWalletAddress
string
✓
Recipient wallet on the target chain.
networkChainId
string
✓
Target chain ID. Supported chains →
returnUrl
string
Flow A
HTTPS URL the customer returns to after checkout. Required for Flow A. Not used in Flow B — there is no hosted page to return from, so you may omit it.
requestType
string
—
"idrx" (default) or "usdt". Other tokens →
usdtRequested
string
—
Required when requestType is "usdt". Amount of the target stablecoin the customer expects to receive.
expiryPeriod
number
—
Payment window in minutes. Default 120.
productDetails
string
—
Custom note on payment page. Max 255 chars.
paymentMethod
string
Flow B
"va". Sending it selects Flow B: the response carries the Virtual Account number directly and no hosted checkout page is created. Requires channelId. Omit it for Flow A.
channelId
string
—
Required whenever paymentMethod is set. The bank channel — "MANDIRI" or "BRI".
toBeMinted cannot be finer than the token itself. IDRX has 0 decimals on Polygon and BNB Chain — one IDRX is the smallest unit there, so amounts must be whole numbers. On every other chain IDRX has 2 decimals. Amounts are never silently rounded for you: send "556931.42" to Polygon and the request is rejected with
Round the amount in your own system before calling this endpoint, so the figure you show the customer is the figure that gets minted. Trailing zeros are fine — "20000.00" is accepted anywhere, since it carries no real precision. Decimals per chain: Supported Chain and Contract Address.
Choosing a flow
Every mint order goes through the same endpoint, the same authentication, and the same status tracking. What differs is who renders the payment screen.
Flow A — Hosted checkout
No paymentMethod
checkoutUrl (mirrored as paymentUrl)
Redirected to a payment page where they pick a method themselves
Flow B — Direct payment
paymentMethod + channelId
The Virtual Account number
Stays inside your app; you show the VA number yourself
Pick Flow A when you want the fastest integration, no payment UI to build, and the widest choice of payment methods. Pick Flow B when you own the checkout experience end to end — mobile app, white-label web, kiosk — and would rather not send the customer to a page you don't control.
Flow A — Hosted checkout
Request
Response
checkoutUrl and paymentUrl always carry the same value — redirect the customer to either one.
Redirect the user to
paymentUrl.User picks a payment method and pays.
User is redirected to your
returnUrl.You receive a callback on settlement.
Don't rely on the returnUrl redirect to confirm payment. Users close browsers. Always confirm via callback or Transaction History.
Flow B — Direct payment
Send paymentMethod together with channelId. The response contains the generated Virtual Account number directly — no redirect, no hosted page. You render the payment instructions in your own UI.
Request
Response
Response fields
id
number
Mint request ID.
merchantOrderId
string
Your order ID — use it for status polling and reconciliation.
reference
string
Internal payment reference, always SNAP-<merchantOrderId>.
paymentMethod
string
Echoes the method you requested — "va".
amount
number
Total the customer must pay, in IDR. Equals baseAmount plus the sum of fees.
baseAmount
number
The mint amount before channel fees.
fees
array
Fee breakdown for this payment. [] when the channel charges no fee.
fees[].name
string
Fee label.
fees[].amount
number
Fee amount in IDR.
expiredDate
string
ISO-8601 UTC timestamp when the Virtual Account stops accepting payment.
virtualAccountNo
string
The account number the customer transfers to.
virtualAccountName
string
Account holder name shown in the customer's banking app.
checkoutUrl / paymentUrl
string
The IDRX-hosted checkout page for this order. Not needed in Flow B — present so a single response shape works for both flows. Both carry the same value.
The customer must transfer the exact amount. A Virtual Account accepts a differing amount, but the mismatch is flagged — paying less is treated as underpaid, paying more as overpaid. Either way the mint is held for manual review before IDRX is credited. Show the exact amount in your UI and discourage rounding.
Rendering the payload
Display virtualAccountNo as text, ideally with a copy button. The customer opens their banking app and transfers exactly amount to that number.
Supported channels
paymentMethod
channelId
Bank
"va"
"MANDIRI"
Bank Mandiri
"va"
"BRI"
Bank BRI
Any other channelId is rejected with 400.
Errors specific to Flow B
400
paymentMethod must be "va" or "qris" when set, got: <value>
Unsupported paymentMethod — send "va"
400
channelId is required when paymentMethod is set
channelId missing
400
Unsupported VA channel: <value>
channelId is not enabled for your merchant
Retrieving the payment payload again
If your customer closes the app before paying and you no longer have the original response, fetch the cached payload for the same order instead of creating a new one:
The response returns the stored Virtual Account payload plus the current status:
id, merchantOrderId, reference
Order identifiers
paymentStatus, userMintStatus, adminMintStatus
Current state — see Transaction History
paymentAmount, toBeMinted
Amounts
txHash
On-chain mint hash, once minted
paymentMethod
"va"
virtualAccountNo, virtualAccountName
The Virtual Account details
expiredDate
When the payment instrument expires
Only the partner that created the order can retrieve it.
Confirming payment
Status tracking is identical in both flows — the fields, the callback, and the terminal states do not depend on how the payment was collected.
A transaction has two status fields you must track together:
paymentStatus
The fiat payment (VA or hosted checkout)
userMintStatus
The on-chain token delivery
Success state
Terminal states
MINTEDREFUNDREJECTEDpaymentStatus: EXPIRED
Confirm via callback, or poll Transaction History by merchantOrderId and stop on a terminal state.
Full state machine, reconciliation pattern, and edge cases: Processing Mint IDRX Requests
Callbacks are sent once and not retried. If your endpoint is down, you must reconcile by polling the Transaction History API. Always re-fetch the transaction before crediting users — treat the callback body as untrusted input.
Errors
400
Invalid parameter
Check param types and limits
400
invalid toBeMinted: IDRX on chainId <id> supports <n> decimal place(s), got <value>
The amount is finer than IDRX on that chain. Round it — whole numbers on Polygon and BNB Chain, at most 2 decimals elsewhere
401
Bad signature or timestamp drift
Recompute signature; sync server clock (NTP)
401
User is not verified
The account must complete verification before it can transact
403
Blocked User-Agent
Set custom User-Agent like my-app/1.0
429
Rate limit
Back off and retry
5xx
Server error
Retry with backoff. Don't create a new order — recover the payload instead
See also
Callback — webhook payload structure, fee breakdown per payment method, and reconciliation tips.
Processing Mint IDRX Requests — end-to-end mint workflow with status state machine and edge cases.
Transaction History API — query transaction state by
merchantOrderId.Generating a Signature — HMAC-SHA256 signature reference with code examples.
The amount the customer pays is not the same as toBeMinted — fees are applied on top of it, or deducted from the minted IDRX, depending on the payment method. In Flow A the final figure is shown on the checkout page; in Flow B it comes back as amount in the response.
Shortly after the payment is done, IDRX tokens will be minted and sent to the specified destination wallet address. In the case of "usdt" requestType, USDT tokens will be sent to the wallet address.
To check the status of the transaction, you can use the Transaction History API.
Last updated
