Redeem: burn MYRT
Redeem burns MYRT from a customer's wallet and pays the net MYR to the customer's registered bank account.
/v1/redeemscurl -X POST https://sandbox-api.myrt.money/v1/redeems \
-H "Authorization: Bearer $MYRT_API_KEY" \
-H "Idempotency-Key: 7c9e6679-7425-40de-944b-e07fc1f90ae7" \
-H "Content-Type: application/json" \
-d '{
"referenceId": "acme:redeem:2026-09-10:00092",
"amountMyrt": "500.00",
"walletAddress": "0xAbC0000000000000000000000000000000000001",
"customerId": "cus_9f2a3b4c",
"bankReference": "acme-payout-00092"
}'import { randomUUID } from "node:crypto";
const res = await fetch("https://sandbox-api.myrt.money/v1/redeems", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.MYRT_API_KEY}`,
"Idempotency-Key": randomUUID(),
"Content-Type": "application/json",
},
body: JSON.stringify({
referenceId: "acme:redeem:2026-09-10:00092",
amountMyrt: "500.00",
walletAddress: "0xAbC0000000000000000000000000000000000001",
customerId: "cus_9f2a3b4c",
bankReference: "acme-payout-00092",
}),
});
const order = await res.json();
if (!order.ok) throw new Error(`${order.error.code}: ${order.error.message}`);import os, uuid, requests
res = requests.post(
"https://sandbox-api.myrt.money/v1/redeems",
headers={
"Authorization": f"Bearer {os.environ['MYRT_API_KEY']}",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"referenceId": "acme:redeem:2026-09-10:00092",
"amountMyrt": "500.00",
"walletAddress": "0xAbC0000000000000000000000000000000000001",
"customerId": "cus_9f2a3b4c",
"bankReference": "acme-payout-00092",
},
timeout=30,
)
order = res.json()
if not order["ok"]:
raise RuntimeError(f"{order['error']['code']}: {order['error']['message']}")Request fields
| Field | Type | Required | Notes |
|---|---|---|---|
referenceId | string | yes | Your unique handle for this order. See reference IDs |
amountMyrt | string | yes | Positive decimal, at most 6 decimal places |
walletAddress | string | yes | Checksummed EVM address the MYRT is burned from |
customerId | string | yes | Owner of the wallet, linked to your integration |
bankReference | string | no | Your payout reference, echoed in reconciliation |
chainId | number | no | Defaults to the active chain. See network configuration |
Redeem needs both scopes
Creating a redeem order submits it for settlement in the same call. The key must hold both redeem:create and redeem:execute. A key with only redeem:create receives 403 SCOPE_DENIED. See scopes.
Redeem is a single call. There is no separate confirm step. Re-posting a referenceId that already exists on a redeem with different details returns 409 IDEMPOTENCY_CONFLICT.
What is checked before the order is accepted
The checks run in this order. The first one that fails is the error you receive.
- Balance. The wallet's on-chain MYRT balance is read. If it is short, the call returns
400 INSUFFICIENT_BALANCEwithmeta.walletAddress,meta.chainId,meta.requestedMyrtandmeta.walletBalanceMyrt. - Policy.
AMOUNT_NEGATIVE_OR_ZEROwhen the amount is zero or negative.AMOUNT_ABOVE_REDEEM_CEILINGwhen a single redemption is above RM 1,000,000.FOREIGNER_LIMIT_EXCEEDEDwhen a non-resident customer redeems above RM 100,000 in one transaction.POLICY_REJECTEDwhen no more specific reason applies; readmessage. All four are400. - Monthly withdrawal limit. Redemptions count against the customer's monthly withdrawal limit. If this order would exceed it, the call returns
400 MONTHLY_WITHDRAWAL_LIMIT_EXCEEDEDwithmeta.monthlyLimit,meta.monthlyCommittedandmeta.requestedAmount, all numbers in MYR.
A customer's monthly withdrawal cap and remaining headroom are readable through the accounts endpoints.
Response
201 Created
{
"ok": true,
"referenceId": "acme:redeem:2026-09-10:00092",
"status": "pending",
"phase": "ORDER_CREATED",
"direction": "REDEEM",
"chainId": 1,
"network": "Ethereum",
"tokenAddress": "0x...",
"walletAddress": "0xAbC0000000000000000000000000000000000001",
"amounts": {
"myr": "500.00",
"myrt": "500.00",
"feeMyr": "0.00",
"amountRaw": "500000000",
"decimals": 6
},
"blockchain": { "txHash": null, "blockNumber": null },
"timestamps": { "createdAt": "2026-09-10T04:12:33.918Z", "updatedAt": null }
}For a redeem, myrt is the amount burned and myr is the net MYR paid out after feeMyr. walletAddress is the wallet the MYRT is burned from. Fees are quoted server-side and returned on the order. Do not compute them client-side.
status and phase are explained in core concepts. Drive your business logic from status. Amounts are decimal strings; see amounts.
Reading status
/v1/redeems/{referenceId}Returns the same object with updated status, phase, and blockchain.txHash. An order reaches completed only after the chain's confirmation count, so do not treat a transaction hash as final on its own.
curl https://sandbox-api.myrt.money/v1/redeems/acme:redeem:2026-09-10:00092 \
-H "Authorization: Bearer $MYRT_API_KEY"completed means the burn is confirmed on chain and the MYR payout to the customer's registered bank account has been initiated. Bank settlement time is outside the API.
This route returns only redeem orders. A reference that belongs to a mint or a transfer, or to an order another integration created, returns 404 NOT_FOUND, the same as a missing one.
Polling works. Webhooks are preferred for settlement events.
Errors you should handle
| Code | HTTP | When |
|---|---|---|
INVALID_AMOUNT | 400 | amountMyrt is not a positive decimal with at most 6 decimal places |
INVALID_WALLET_ADDRESS | 400 | walletAddress is not a valid EVM address |
INVALID_REFERENCE_ID | 400 | referenceId fails the format rule |
INSUFFICIENT_BALANCE | 400 | The wallet holds less MYRT than amountMyrt. meta carries the requested and actual balances |
AMOUNT_NEGATIVE_OR_ZERO | 400 | amountMyrt is zero or negative |
AMOUNT_ABOVE_REDEEM_CEILING | 400 | A single redemption above RM 1,000,000 |
FOREIGNER_LIMIT_EXCEEDED | 400 | Above RM 100,000 per transaction for a non-resident customer |
POLICY_REJECTED | 400 | Generic policy rejection. Read message |
MONTHLY_WITHDRAWAL_LIMIT_EXCEEDED | 400 | The customer's monthly withdrawal limit would be exceeded. meta carries the limit, the amount committed and the amount requested |
CUSTOMER_NOT_VERIFIED | 403 | The customer has not cleared verification |
SCOPE_DENIED | 403 | The key lacks redeem:create or redeem:execute |
NOT_FOUND | 404 | customerId is not linked to your integration |
IDEMPOTENCY_CONFLICT | 409 | Same Idempotency-Key with a different body, or referenceId reused with different details |
SETTLEMENT_FAILED | 502 | Settlement submission failed. Retry with the same Idempotency-Key |
The full list is on the errors page. The request and response shapes are on the redeems reference.
