Withdrawals

Withdrawal statuses
StatusWhat it means
PROCESSINGThe request was confirmed with a correct code and is being sent out. It can no longer be cancelled.
COMPLETEDThe payout is confirmed on-chain and an external transaction hash is recorded. An internal hash on its own does not complete a withdrawal.
CANCELEDCancelled before confirmation, the code expired, or five wrong codes were entered. The reserve went back to your available balance, exactly once.
Withdrawal fields
FieldTypeDescription
idstring (UUID)The request identifier; used as :id in the confirm, cancel, and get paths.
requestIdstring (UUID)The idempotency key you sent on create.
currencyIdstring (UUID)The cryptocurrency you asked to withdraw.
blockchainstringThe network the payout goes out on, taken from that currency.
tokenstringThe token symbol on that network.
walletAddressstringThe main payout wallet for that network, frozen into the request when it was created.
statusstringThe state of the request — see Statuses above.
providerStatusstring | nullThe payout provider’s own status. The set of values it can hold is not published here, so do not branch on it — branch on status.
reviewRequiredbooleanTrue when the request needs an operational reconciliation against the transaction hashes — either because the provider reported a failure that may still be reprocessed, or because automatic attempts stopped.
failReasonstring | nullWhy the payout failed, once it has.
internalTxIdstring | nullThe provider-side transfer identifier.
externalTxIdstring | nullThe on-chain transaction hash. A withdrawal only reaches COMPLETED with one.
amountstringThe whole reserved amount.
serviceFeestringThe TEDR Pay service fee — see Amounts and fees.
providerAmountstringamount minus serviceFee: the sum handed to the payout provider.
receivedAmountstring | nullNull. The provider’s exact fee and the sum that lands on the address are outside the contract, so this stays empty.
Creation, confirmation and processing timestamps, and the confirmation code’s expirydatetimeThe response carries all four. Their exact field names are not published here — read them from the response body rather than hard-coding them.

Create a withdrawal request

POST/merchants/me/withdrawals

Auth: Session JWT only — how to get a JWT.

Reserves the amount on your balance and emails a confirmation code. The request is not sent anywhere until you confirm it.

Body parameters
NameTypeRequiredDefaultDescription
requestIdstring (UUID)RequiredAn idempotency key you generate once per withdrawal. Retry a timed-out create with the same value and the same parameters.
currencyIdstring (UUID)RequiredThe cryptocurrency to withdraw. The network and the payout address follow from it.
amountstringRequiredA positive decimal string without an exponent, or all for the available balance.
POST/merchants/me/withdrawals
curl -X POST 'https://dev-app.tedr.com/api/merchants/me/withdrawals' \
  -H 'Authorization: Bearer YOUR_SESSION_JWT' \
  -H 'Content-Type: application/json' \
  -d '{"requestId": "e2c1f5a8-1d3b-4a61-9a0c-7f5b2c84d90e", "currencyId": "8a4d2f7c-5b21-4f0e-9c63-1ab8e2d47f95", "amount": "100"}'

Response: 201

Errors
CodeStatusWhen
—409The same requestId was reused with different parameters. Repeating it with identical parameters returns the existing request instead.

The body carries the withdrawal request, with the fields listed above under Response fields. The status a request holds before it is confirmed is not published here — read it from the response instead of hard-coding it. Creating a request needs a confirmed email address on your profile, and is limited to one new request per minute and five requests awaiting confirmation at a time.

Confirm a withdrawal request

POST/merchants/me/withdrawals/:id/confirm

Auth: Session JWT only — how to get a JWT.

Confirms the request with the code emailed to your profile address and hands it over for processing.

Path parameters
NameTypeRequiredDefaultDescription
idstring (UUID)RequiredThe request's id, from the create or list response.
Body parameters
NameTypeRequiredDefaultDescription
codestringRequiredThe code from the confirmation email.
POST/merchants/me/withdrawals/:id/confirm
curl -X POST 'https://dev-app.tedr.com/api/merchants/me/withdrawals/3f0f6c61-9e8a-4f44-9a3f-6d2a5f5ee2b1/confirm' \
  -H 'Authorization: Bearer YOUR_SESSION_JWT' \
  -H 'Content-Type: application/json' \
  -d '{"code": "012345"}'

Response: 200

A correct code moves the request to PROCESSING. The code is valid for 10 minutes and allows at most five wrong attempts; the fifth wrong attempt, or the code expiring, cancels the request and returns the reserved funds. There is no resend with a new code — cancel the request and create a new one. Confirming again does not send the money twice. The shape of the response body is not specified here — read the updated request with Get a withdrawal if you need its fields.

Cancel a withdrawal request

POST/merchants/me/withdrawals/:id/cancel

Auth: Session JWT only — how to get a JWT.

Cancels a request that has not been confirmed yet and releases its reserve. Takes no request body.

Path parameters
NameTypeRequiredDefaultDescription
idstring (UUID)RequiredThe request's id, from the create or list response.
POST/merchants/me/withdrawals/:id/cancel
curl -X POST 'https://dev-app.tedr.com/api/merchants/me/withdrawals/3f0f6c61-9e8a-4f44-9a3f-6d2a5f5ee2b1/cancel' \
  -H 'Authorization: Bearer YOUR_SESSION_JWT'

Response: 200

Only before confirmation: once the request is confirmed, cancelling is no longer allowed. Cancelling moves the request to CANCELED and returns the reserve to your available balance exactly once. The shape of the response body is not specified here — read the request with Get a withdrawal if you need its fields.

Get a withdrawal request

GET/merchants/me/withdrawals/:id

Auth: Session JWT only — how to get a JWT.

Returns the current state of one of your own requests.

Path parameters
NameTypeRequiredDefaultDescription
idstring (UUID)RequiredThe request's id, from the create or list response.
GET/merchants/me/withdrawals/:id
curl 'https://dev-app.tedr.com/api/merchants/me/withdrawals/3f0f6c61-9e8a-4f44-9a3f-6d2a5f5ee2b1' \
  -H 'Authorization: Bearer YOUR_SESSION_JWT'

Response: 200

{
  "id": "3f0f6c61-9e8a-4f44-9a3f-6d2a5f5ee2b1",
  "requestId": "e2c1f5a8-1d3b-4a61-9a0c-7f5b2c84d90e",
  "currencyId": "8a4d2f7c-5b21-4f0e-9c63-1ab8e2d47f95",
  "blockchain": "<network of the selected currency>",
  "token": "<token symbol on that network>",
  "walletAddress": "<your main payout wallet on that network>",
  "status": "PROCESSING",
  "providerStatus": null,
  "reviewRequired": false,
  "failReason": null,
  "internalTxId": "<provider transfer id>",
  "externalTxId": "<on-chain hash, once the transfer is confirmed>",
  "amount": "100",
  "serviceFee": "1",
  "providerAmount": "99",
  "receivedAmount": null
}

Values in angle brackets depend on your currency and payout wallet. The body also carries the creation, confirmation and processing timestamps and the expiry of the confirmation code.

List withdrawal requests

GET/merchants/me/withdrawals

Auth: Session JWT only — how to get a JWT.

Returns your withdrawal requests, page by page.

Query parameters
NameTypeRequiredDefaultDescription
limitintegerOptional20How many requests to return, from 1 to 100.
offsetintegerOptional0How many requests to skip before the page starts.
GET/merchants/me/withdrawals
curl 'https://dev-app.tedr.com/api/merchants/me/withdrawals?limit=20&offset=0' \
  -H 'Authorization: Bearer YOUR_SESSION_JWT'

Response: 200

{
  "items": [
    {
      "id": "3f0f6c61-9e8a-4f44-9a3f-6d2a5f5ee2b1",
      "requestId": "e2c1f5a8-1d3b-4a61-9a0c-7f5b2c84d90e",
      "currencyId": "8a4d2f7c-5b21-4f0e-9c63-1ab8e2d47f95",
      "blockchain": "<network of the selected currency>",
      "token": "<token symbol on that network>",
      "walletAddress": "<your main payout wallet on that network>",
      "status": "PROCESSING",
      "providerStatus": null,
      "reviewRequired": false,
      "failReason": null,
      "internalTxId": "<provider transfer id>",
      "externalTxId": "<on-chain hash, once the transfer is confirmed>",
      "amount": "100",
      "serviceFee": "1",
      "providerAmount": "99",
      "receivedAmount": null
    }
  ],
  "total": 1,
  "limit": 20,
  "offset": 0
}

The envelope of this list is { items, total, limit, offset } — the other list endpoints of the API use different envelopes, so read this one on its own terms.