
# Create a transfer

## Submit a crypto transaction

Use a secret API key and a unique idempotency key. Set `MYAZA_API_BASE_URL` to the versioned API base, such as `http://localhost:32101/api/v1` locally:

```bash
curl -X POST "$MYAZA_API_BASE_URL/transactions" \
  -H "Authorization: Bearer $MYAZA_SECRET_KEY" \
  -H "Idempotency-Key: crypto-transfer-1042-v1" \
  -H "Content-Type: application/json" \
  -d '{
    "externalActivityId": "activity-1042",
    "subject": { "type": "individual", "externalUserId": "customer-42" },
    "occurredAt": "2026-08-25T20:00:00.000Z",
    "transaction": {
      "externalTransactionId": "transfer-1042",
      "assetClass": "crypto",
      "direction": "outbound",
      "amount": "2500",
      "currency": "USDT",
      "transactionType": "crypto_transfer",
      "blockchain": "TRON",
      "travelRule": {
        "sourceJurisdiction": "NG",
        "destinationJurisdiction": "GB",
        "counterpartyType": "vasp",
        "walletType": "hosted",
        "originator": {
          "partyType": "individual",
          "data": {
            "legalName": "Originator name",
            "accountIdentifier": "customer-account-reference"
          }
        },
        "beneficiary": {
          "partyType": "individual",
          "data": { "legalName": "Beneficiary name", "accountIdentifier": "beneficiary-account-reference" }
        },
        "counterpartyVasp": {
          "partyType": "business",
          "data": {
            "legalName": "Counterparty VASP",
            "jurisdiction": "GB"
          }
        }
      }
    }
  }'
```

Do not send regulated party information in generic metadata. Use the dedicated `travelRule` party fields so Myaza can minimise, encrypt, retain and purge the evidence under the Travel Rule privacy controls.

### Node.js SDK

The same request is available from the server-side Trust SDK:

```js
const transaction = await myaza.transactions.create({
  externalActivityId: 'activity-1042',
  subject: { type: 'individual', externalUserId: 'customer-42' },
  occurredAt: '2026-08-25T20:00:00.000Z',
  transaction: {
    externalTransactionId: 'transfer-1042',
    assetClass: 'crypto',
    direction: 'outbound',
    amount: '2500',
    currency: 'USDT',
    transactionType: 'crypto_transfer',
    blockchain: 'TRON',
    travelRule: {
      sourceJurisdiction: 'NG',
      destinationJurisdiction: 'GB',
      counterpartyType: 'vasp',
      walletType: 'hosted',
      originator: {
        partyType: 'individual',
        data: { legalName: 'Originator name', accountIdentifier: 'customer-account-reference' },
      },
      beneficiary: { partyType: 'individual', data: { legalName: 'Beneficiary name', accountIdentifier: 'beneficiary-account-reference' } },
      counterpartyVasp: {
        partyType: 'business',
        data: { legalName: 'Counterparty VASP', jurisdiction: 'GB' },
      },
    },
  },
}, { idempotencyKey: 'crypto-transfer-1042-v1' });

if (transaction.travelRule) {
  console.log(transaction.travelRule.summary.title, transaction.travelRule.summary.nextAction);
}
```



## What happens next?

This example includes both parties for the standard information package. Your published policy can require additional fields or evidence. Read the returned summary, then follow its next action. You do **not** need to submit the same information again.

Use the returned `activityId` for later requests, not a guessed identifier. A read retrieves the current assessment; it does not create another transaction. If information is missing, use [Supply missing information](https://trust.myaza.co/documentation/travel-rule-information/markdown). For institutional messaging and the wallet gate, continue to [Exchange and authorise](https://trust.myaza.co/documentation/travel-rule-execution/markdown).

These are ordinary API requests and use your configured pricing. For labelled, non-billable scenario traffic, use [Test in Sandbox](https://trust.myaza.co/documentation/travel-rule-testing/markdown).
