Sign in
Pagos y retiros/Payout API

API de retiros

Envía retiros desde tu saldo de comerciante a cualquier dirección blockchain.

La API de retiros te permite retirar fondos mediante programación desde tu saldo de comerciante hacia cualquier dirección blockchain.

Para todos los endpoints de retiro debes utilizar una Payout API key independiente para generar la firma sign. Esta clave es distinta de tu API key habitual y debe generarse en la configuración de tu proyecto.

Crear retiro

Crea una solicitud de retiro desde tu saldo de comerciante.

POST/v1/payout

Parámetros de la solicitud

CampoTipoRequeridoDescripción
currencystringDivisa de retiro (consulta References)
networkstringCódigo de red (consulta References)
amountstringMonto del retiro
to_addressstringDirección blockchain del destinatario
order_idstringnoClave de idempotencia — única dentro de un proyecto. Un POST repetido con el mismo order_id no crea un nuevo retiro — se devuelve el existente
url_callbackstringnoURL para los webhooks de retiro. Omítela para deshabilitar webhooks de este retiro
memostring | nullnoDestination tag / memo. Actualmente lo usan únicamente las redes TON y SOL; máx. 255 caracteres
from_currencystringnoSaldo de origen del que debitar y convertir automáticamente a currency en el momento del retiro. Te permite pagar en activos volátiles (BTC, ETH, …) manteniendo tu saldo en una stablecoin como USDT — no tienes que mantener tú mismo la cripto volátil. Pasa "USDT" para debitar el saldo USDT
fee_optionstringnoCómo se cobran las comisiones. deduct (por defecto) — las comisiones de red + plataforma se restan de amount, el destinatario recibe amount - fees. add — las comisiones se añaden por encima, al comerciante se le debita amount + fees y el destinatario recibe exactamente amount

Idempotencia. Dentro de un proyecto, un retiro es único por order_id. Reenviar el mismo POST con el mismo order_id es seguro — la API devuelve el retiro existente en lugar de crear un duplicado. Pasa siempre un order_id para los retiros en producción.

Ejemplos de solicitud

Shell
curl -X POST https://api.2328.io/api/v1/payout \
  -H "Content-Type: application/json" \
  -H "User-Agent: MyShop/1.0 (+https://myshop.example)" \
  -H "project: YOUR_PROJECT_UUID" \
  -H "sign: YOUR_HMAC_SIGNATURE" \
  -d '{"currency":"TRX","network":"TRX-TRC20","amount":"1.00","to_address":"TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t","order_id":"9ed25264-8be4-439f-acf5-2a8732538d27","url_callback":"https://your-site.com/webhook/payout","memo":null,"fee_option":"deduct"}'

Ejemplo de respuesta

JSON
{
  "state": 0,
  "result": {
    "uuid": "019dea62-1727-72aa-ac2c-eaf2ade193ef",
    "order_id": "9ed25264-8be4-439f-acf5-2a8732538d27",
    "status": "pending",
    "currency": "TRX",
    "network": "TRX-TRC20",
    "amount": "1.00",
    "merchant_amount": "1",
    "network_amount": "0.89",
    "amount_usd": "0.33",
    "to_address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
    "memo": null,
    "txid": null,
    "block_number": null,
    "error_type": null,
    "created_at": "2026-05-02T23:29:50+03:00",
    "updated_at": "2026-05-02T23:29:50+03:00"
  }
}

Comisiones. Por defecto fee_option: deduct — las comisiones de red + plataforma se restan de amount (el destinatario recibe amount - fees). Pasa fee_option: add para cobrar las comisiones por encima — el destinatario recibe exactamente amount y al comerciante se le debita amount + fees.

Calcular retiro

Estima los importes y comisiones del retiro sin crear un retiro ni cargar tu saldo. Úsalo para mostrar al usuario el importe exacto que recibirá (o pagará) antes de confirmar.

POST/v1/payout/calc

Parámetros de la solicitud

Idénticos a Crear retiro — mismos campos, misma firma. order_id, url_callback, to_address y memo se aceptan pero se ignoran: no se persiste ningún retiro y no se envían callbacks.

Ejemplo de solicitud

Shell
curl -X POST https://api.2328.io/api/v1/payout/calc \
  -H "Content-Type: application/json" \
  -H "User-Agent: MyShop/1.0 (+https://myshop.example)" \
  -H "project: YOUR_PROJECT_UUID" \
  -H "sign: YOUR_HMAC_SIGNATURE" \
  -d '{"currency":"USDT","network":"TRX-TRC20","amount":"100","fee_option":"add"}'

Ejemplo de respuesta

JSON
{
  "state": 0,
  "result": {
    "currency": "USDT",
    "network": "TRX-TRC20",
    "amount": "100",
    "fee_option": "add",
    "merchant_amount": "103.00000000",
    "network_amount": "100",
    "total_fee": "3.00000000",
    "total_fee_usd": "3.00000000"
  }
}

Solo vista previa. Este endpoint es de solo lectura — no se carga ningún saldo ni se crea ningún registro de retiro. Llámalo todas las veces que necesites para mostrar el desglose de comisiones en tu interfaz.

Estado del retiro

Obtén el estado de una solicitud de retiro.

GET/v1/payout/status/{uuid}

Parámetros de ruta

CampoTipoRequeridoDescripción
uuidstringUUID del retiro (de result.uuid al crearlo)

Ejemplo de respuesta

JSON
{
  "state": 0,
  "result": {
    "uuid": "019dff1f-0dbd-7277-8d45-271e7775388f",
    "order_id": "4dfdcc84402b1185b71cbe399321533e",
    "status": "completed",
    "currency": "TRX",
    "network": "TRX-TRC20",
    "amount": "3.00",
    "merchant_amount": "3.00",
    "network_amount": "3.00",
    "amount_usd": "1.04",
    "to_address": "THauRv5tcucQRohXg8NiyGTk16DX1XQG5x",
    "memo": null,
    "txid": "9242e533703704ef3eaba840f70b4a26333e72c943377ee375fea17badb53def",
    "block_number": null,
    "error_type": null,
    "created_at": "2026-05-07T00:08:38+03:00",
    "updated_at": "2026-05-07T00:08:54+03:00",
    "from_currency": "USDT",
    "debited_amount": "1.050735",
    "debited_currency": "USDT"
  }
}

Para esta solicitud GET la firma se calcula sobre un cuerpo vacío: hash_hmac('sha256', base64_encode(''), $apiKey)

Campos de la respuesta

Campos devueltos en result por POST /v1/payout y GET /v1/payout/status/{uuid}:

CampoTipoDescripción
uuidstringUUID del retiro asignado por el sistema
order_idstringTu identificador interno de retiro (único dentro del proyecto)
statusstringEstado actual del retiro (ver más abajo)
currencystringDivisa de retiro
networkstringCódigo de red
amountstringMonto de retiro tal como se solicitó
merchant_amountstringMonto debitado del saldo del comerciante
network_amountstringMonto realmente enviado en la blockchain (después de las comisiones de red + plataforma)
amount_usdstringEquivalente en USD del monto de retiro
to_addressstringDirección blockchain del destinatario
memostring | nullDestination tag / memo (TON, SOL). null en caso contrario
txidstring | nullHash de la transacción en la blockchain. null hasta que se envíe la transacción
block_numberint | nullNúmero de bloque donde se incluyó la transacción. null hasta que se incluya
error_typestring | nullMotivo del fallo cuando status = failed (ver Tipos de error más abajo). null en caso contrario
created_atstring (ISO 8601)Hora de creación del retiro
updated_atstring (ISO 8601)Hora del último cambio de estado
from_currencystring | nullSaldo de origen del que se debitó el retiro cuando se usó conversión automática (p. ej., USDT para un retiro en BTC). null si no hubo conversión
debited_amountstring | nullMonto realmente debitado del saldo de origen tras la conversión. Solo presente cuando se usa conversión automática
debited_currencystring | nullDivisa de debited_amount — el saldo del que se debitaron los fondos

Estados de retiro

El campo status puede tomar los siguientes valores:

EstadoDescripción
pendingCreado, pendiente de procesamiento
completedCompletado correctamente — txid está definido
failedError de envío — consulta error_type
cancelledCancelado

Tipos de error

Cuando status = failed, el campo error_type describe la causa:

CódigoDescripción
aml_riskRetiro bloqueado por verificaciones de riesgo AML (la dirección destinataria fue marcada como de alto riesgo)

Notificaciones por webhook

Cuando cambia el estado de un retiro, el sistema envía un webhook POST a la URL url_callback indicada al crear el retiro. Si no se proporcionó url_callback, no se envían webhooks para ese retiro.

  • Método: POST
  • Content-Type: application/json
  • Firma: campo sign en el cuerpo de la solicitud, calculado con la Payout API key (la misma clave usada para firmar las solicitudes de retiro).

El payload refleja el objeto result de GET /v1/payout/status/{uuid} más un campo sign para la verificación.

Payload

JSON
{
  "uuid": "019dff1f-0dbd-7277-8d45-271e7775388f",
  "order_id": "4dfdcc84402b1185b71cbe399321533e",
  "status": "completed",
  "currency": "TRX",
  "network": "TRX-TRC20",
  "amount": "3.00",
  "merchant_amount": "3.00",
  "network_amount": "3.00",
  "amount_usd": "1.04",
  "to_address": "THauRv5tcucQRohXg8NiyGTk16DX1XQG5x",
  "memo": null,
  "txid": "9242e533703704ef3eaba840f70b4a26333e72c943377ee375fea17badb53def",
  "block_number": null,
  "error_type": null,
  "created_at": "2026-05-07T00:08:38+03:00",
  "updated_at": "2026-05-07T00:08:54+03:00",
  "from_currency": "USDT",
  "debited_amount": "1.050735",
  "debited_currency": "USDT",
  "sign": "925ad7bf3d6841864101f7cc2c7e30652e70a06cdb04dbe07a0129480000ce4a"
}

Verificar la firma. Usa el mismo algoritmo que para los webhooks de pago, pero firma con tu Payout API key en lugar de la API key habitual. Quita el campo sign, codifica en JSON el resto del payload, codifícalo en Base64 y luego calcula hash_hmac('sha256', $base64, $payoutApiKey) y compáralo con el sign recibido.