Skip to content

Transfers

Move MYRT to a recipient wallet on a linked customer's behalf. The flow, the key handling advice and the reasoning are in the transfers guide; this page states the shapes.

Create a transfer

POST/v1/transferstransfer:create

Creates a transfer and submits it for settlement in the same call, so the key must hold both transfer:create and transfer:execute. Two ceilings apply and are enforced on every request: 50,000 MYRT per transaction and 250,000 MYRT per key per UTC day. Failed and cancelled transfers do not count toward the daily total. A recipient that fails screening is refused with 403 RECIPIENT_NOT_PERMITTED.

Headers

HeaderRequiredValue
AuthorizationyesBearer <key> with transfer:create and transfer:execute
Idempotency-KeyyesA UUID you generate per logical operation, at most 255 characters
Content-Typeyesapplication/json

Request body

FieldTypeRequiredNotes
referenceIdstringyes8 to 100 characters: letters, digits, dot, underscore, dash, colon. Unique within your integration
amountMyrtstringyesPositive decimal, at most 6 decimal places
walletAddressstringyesEVM address that receives the MYRT
customerIdstringyesThe account the transfer is debited against, linked to your integration
chainIdnumbernoDefaults to the active chain
bash
curl -X POST https://sandbox-api.myrt.money/v1/transfers \
  -H "Authorization: Bearer $MYRT_API_KEY" \
  -H "Idempotency-Key: 9b2d0f6e-3c1a-4e8f-9d7b-5a6c4e2f1b0a" \
  -H "Content-Type: application/json" \
  -d '{
    "referenceId": "acme:transfer:2026-09-10:00031",
    "amountMyrt": "250.00",
    "walletAddress": "0xAbC0000000000000000000000000000000000001",
    "customerId": "cus_9f2a3b4c"
  }'
ts
import { randomUUID } from "node:crypto";

const res = await fetch("https://sandbox-api.myrt.money/v1/transfers", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.MYRT_API_KEY}`,
    "Idempotency-Key": randomUUID(),
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    referenceId: "acme:transfer:2026-09-10:00031",
    amountMyrt: "250.00",
    walletAddress: "0xAbC0000000000000000000000000000000000001",
    customerId: "cus_9f2a3b4c",
  }),
});
const order = await res.json();
python
import os, uuid, requests

res = requests.post(
    "https://sandbox-api.myrt.money/v1/transfers",
    headers={
        "Authorization": f"Bearer {os.environ['MYRT_API_KEY']}",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "referenceId": "acme:transfer:2026-09-10:00031",
        "amountMyrt": "250.00",
        "walletAddress": "0xAbC0000000000000000000000000000000000001",
        "customerId": "cus_9f2a3b4c",
    },
    timeout=30,
)
order = res.json()

Response 201 Created

json
{
  "ok": true,
  "referenceId": "acme:transfer:2026-09-10:00031",
  "status": "pending",
  "phase": "ORDER_CREATED",
  "direction": "TRANSFER",
  "chainId": 1,
  "network": "Ethereum",
  "tokenAddress": "0x...",
  "walletAddress": "0xAbC0000000000000000000000000000000000001",
  "amounts": {
    "myr": null,
    "myrt": "250.00",
    "feeMyr": "0",
    "amountRaw": "250000000",
    "decimals": 6
  },
  "blockchain": { "txHash": null, "blockNumber": null },
  "timestamps": { "createdAt": "2026-09-10T04:12:33.918Z", "updatedAt": null }
}

walletAddress is the recipient. For a transfer, amounts.myrt is the amount moved, amounts.myr is null and amounts.feeMyr is "0". See amounts.

A replay of the same Idempotency-Key and body returns this response again with X-MYRT-Idempotent-Replay: true. Posting a referenceId that already exists returns the existing order.

Errors

CodeHTTP
INVALID_JSON400
IDEMPOTENCY_KEY_REQUIRED400
INVALID_AMOUNT400
INVALID_WALLET_ADDRESS400
INVALID_REFERENCE_ID400
AMOUNT_NEGATIVE_OR_ZERO400
TRANSFER_PER_TX_CAP_EXCEEDED400
TRANSFER_DAILY_CAP_EXCEEDED400
POLICY_REJECTED400
RECIPIENT_NOT_PERMITTED403
SCOPE_DENIED403
CUSTOMER_NOT_VERIFIED403
NOT_FOUND404
IDEMPOTENCY_CONFLICT409
SETTLEMENT_FAILED502

TRANSFER_PER_TX_CAP_EXCEEDED and TRANSFER_DAILY_CAP_EXCEEDED carry meta.requestedMyrt, meta.committedTodayMyrt, meta.perTxCapMyrt and meta.dailyCapMyrt. Read the caps from meta rather than hardcoding them; they may be lowered.

See errors for the meaning of each code.

Read a transfer

GET/v1/transfers/{referenceId}transfer:read

Returns the current state of a transfer you created. An order that is not a transfer, or that another integration created, returns 404 NOT_FOUND, the same as an order that does not exist. A transfer is completed only after the chain's confirmation count; a txHash alone is not final. See order lifecycle.

Path parameters

ParameterTypeNotes
referenceIdstringThe referenceId you supplied on creation
bash
curl https://sandbox-api.myrt.money/v1/transfers/acme:transfer:2026-09-10:00031 \
  -H "Authorization: Bearer $MYRT_API_KEY"
ts
const res = await fetch(
  "https://sandbox-api.myrt.money/v1/transfers/acme:transfer:2026-09-10:00031",
  { headers: { Authorization: `Bearer ${process.env.MYRT_API_KEY}` } }
);
const order = await res.json();
python
import os, requests

res = requests.get(
    "https://sandbox-api.myrt.money/v1/transfers/acme:transfer:2026-09-10:00031",
    headers={"Authorization": f"Bearer {os.environ['MYRT_API_KEY']}"},
    timeout=30,
)
order = res.json()

Response 200 OK

json
{
  "ok": true,
  "referenceId": "acme:transfer:2026-09-10:00031",
  "status": "completed",
  "phase": "COMPLETED",
  "direction": "TRANSFER",
  "chainId": 1,
  "network": "Ethereum",
  "tokenAddress": "0x...",
  "walletAddress": "0xAbC0000000000000000000000000000000000001",
  "amounts": {
    "myr": null,
    "myrt": "250.00",
    "feeMyr": "0",
    "amountRaw": "250000000",
    "decimals": 6
  },
  "blockchain": { "txHash": "0x...", "blockNumber": "20481922" },
  "timestamps": { "createdAt": "2026-09-10T04:12:33.918Z", "updatedAt": "2026-09-10T04:19:02.441Z" }
}

Errors

CodeHTTP
INVALID_REFERENCE_ID400
NOT_FOUND404

MYRT is a 1:1 Ringgit-backed stablecoin on Ethereum.