---
title: "Send USDT from your wallet to a registered destination"
method: POST
path: "/v1/usdt/sends"
tags: ["Partner API"]
---

# Send USDT from your wallet to a registered destination

`POST /v1/usdt/sends`

## Request

- Base URL: `https://sandbox.onlink.africa`
- URL: `https://sandbox.onlink.africa/v1/usdt/sends`
- Auth: API key in header `X-OnLink-Key`

Validates the destination against your wallet allowlist (only an active wallet may receive value), checks the amount against our minimum and your caps, then writes the instruction and sends a confirmation code to your registered confirmation contact, or to your webhook as confirmation.code_issued if OnLink has switched your account to webhook delivery. Nothing reaches the chain until that code is verified via POST /v1/confirmations/:id, unless OnLink has enabled confirmation waiving for your account and, in production, the API key has an IP allowlist, in which case the send is returned already confirmed and is executed immediately.

## Request body

- PartnerCreateUsdtSendDto
  - `destinationWalletId` string, required: The id of a registered, active destination wallet (see GET /v1/wallets).
  - `usdtAmount` string, required: Decimal string, USDT, up to 6 decimal places, GREATER than zero. Never a JSON number.
  - `partnerReference` string: Your own reference for this send, echoed back on every read.
  - `idempotencyKey` string, required: A key unique to your account. A retried create with the same key returns the original send rather than creating a second one.

## Response `202`

The instruction was created. Normally a confirmation code is sent and the response carries a `confirmation` object. When OnLink has enabled confirmation waiving for your account and, in production, the API key has an IP allowlist, the send is created already `confirmed`, executes immediately, and the response carries no `confirmation` object.

- PartnerUsdtSendResponseDto
  - `id` string, required: The send id.
  - `status` 'awaiting_confirmation' | 'confirmed' | 'processing' | 'settled' | 'failed' | 'expired', required: The send status.
  - `destinationWalletId` string, required: The destination wallet id you registered.
  - `usdtAmount` string, required: The amount sent, in USDT.
  - `partnerReference` string: Your own reference, echoed back.
  - `failureReason` string: A classified failure code, present only once failed.
  - `createdAt` string, date-time, required: ISO-8601 instant the send was created.
  - `confirmedAt` string, date-time: ISO-8601 instant the send was confirmed: when its confirmation code was verified, or, when confirmation is waived for your account, when the send was created already confirmed.
  - `confirmation` ConfirmationDto
    - `id` string, required: The confirmation id. POST the code your confirmation contact receives (or your webhook, as `confirmation.code_issued`, when `channel` is `webhook`) back to `/v1/confirmations/:id` to authorise the transfer.
    - `channel` 'email' | 'sms' | 'webhook', required: How the confirmation code was delivered. `webhook` means it was pushed to your webhook endpoint as `confirmation.code_issued`.
    - `deliveredTo` string, required: Masked delivery address or number. Never the raw contact.
    - `expiresAt` string, date-time, required: ISO-8601 instant the confirmation code expires.
    - `resendAvailableAt` string, date-time, required: ISO-8601 instant a resend becomes available.
    - `webhookDelivery` ConfirmationWebhookDeliveryDto
      - `status` 'pending' | 'delivered' | 'failed', required: `pending` while we are still trying, `delivered` once your endpoint acknowledged the push, `failed` once every attempt has failed.
      - `attempts` integer, required: How many push attempts have been made so far.
      - `lastAttemptAt` string, date-time, nullable, required: ISO-8601 instant of the most recent push attempt, or null before the first.
    - `waiverNotApplied` 'key_without_ip_allowlist': Present only when OnLink has enabled confirmation waiving for your account but this request still needs a confirmation code, because the API key that made it has no IP allowlist. Ask OnLink to add an IP allowlist to that API key; payouts made with it are then created already confirmed. Present on the first response only: a repeat of the same request (an idempotent replay) returns the stored payout without it. Absent in every other case.

## Other responses

- `404`: PARTNER_NOT_FOUND.
- `409`: PARTNER_SUSPENDED.
- `422`: USDT_SEND_DESTINATION_NOT_ALLOWLISTED, USDT_SEND_BELOW_MINIMUM, USDT_SEND_EXCEEDS_PER_ORDER_CAP, or USDT_SEND_EXCEEDS_DAILY_CAP.
- `503`: PARTNER_USDT_SENDS_DISABLED, MONEY_MOVEMENT_PAUSED, CONFIRMATION_CONTACT_MISSING, or CONFIRMATION_DELIVERY_UNAVAILABLE. The two CONFIRMATION_* refusals mean no confirmation code can be delivered; when the cause is a waived account whose API key has no IP allowlist, the body also carries `details.waiverNotApplied: "key_without_ip_allowlist"`. Nothing was created.

---

[API](https://skmtc.dev/onlink/apis/onlink-partner-api.md) - [All operations](https://skmtc.dev/onlink/apis/onlink-partner-api/llms.txt) - [OpenAPI document](https://skmtc.dev/onlink/apis/onlink-partner-api/revisions/1d1c6a3671f2?raw)
