Ir al contenido
Documentación

Operaciones de cuenta

Estos endpoints abarcan los saldos, los reembolsos, los retiros y las respuestas a disputas. Utilizan las mismas claves y funciones auxiliares de solicitud que los endpoints de pago.

EndpointFinalidad
GET /api/account/balanceSaldo
GET /api/account/available-balanceSaldo retirable
POST /api/account/refundsReembolsar o anular un pago
GET /api/account/refunds[/{id}]Listar o consultar reembolsos
POST /api/account/withdrawalsSolicitar un retiro en USDT
GET /api/account/withdrawals[/{id}]Listar o consultar retiros
GET /api/account/disputes[/{id}]Listar o consultar disputas
POST /api/account/disputes/{id}/evidenceResponder a una disputa

Convenciones

  • La firma, los encabezados y el Idempotency-Key funcionan como se describe en Autenticación.
  • Un elemento individual se devuelve como un objeto JSON simple; las listas se devuelven como { "data": [...], "meta": {...} }.
  • Los identificadores de pago, reembolso, retiro y disputa usan LUVEI-ABCD-123456. Guarde el identificador completo.
  • Los saldos y los retiros utilizan la moneda principal del sistema; los reembolsos y las disputas utilizan la moneda del pago.
  • 201 o 202 significa que la solicitud se aceptó, no que se completó. Haga un seguimiento del estado o de los webhooks.
  • Para probar resultados con una clave de sandbox, consulte Sandbox y tarjetas de prueba.

Paginación

CampoTipoObligatorioDescripción
pageinteger · queryOpcionalNúmero de página, a partir de 1.
per_pageinteger · queryOpcionalElementos por página, de 1 a 100. Valor predeterminado: 20.
statusstring · queryOpcionalDevuelve solo los elementos con este estado.
CampoTipoDescripción
pageintegerPágina actual.
per_pageintegerElementos por página.
totalintegerNúmero de elementos coincidentes.
total_pagesintegerNúmero de páginas (0 si la lista está vacía).

Los elementos se ordenan del más reciente al más antiguo. Una página posterior a la última devuelve 200 con data vacío. Un page inferior a 1, un per_page fuera del intervalo 1–100, un status desconocido o un parámetro desconocido devuelve 422 1000001. No se admiten filtros por fecha.

Respuesta de lista · Ejemplo

{
  "data": [
    {
      "id": "LUVEI-RFND-100001",
      "operation": "refund",
      "status": "requested",
      "amount": "100.00",
      "currency": "USD",
      "reason": "Customer requested a full refund",
      "provider_reference": null,
      "provider_refunded_at": null,
      "created_at": "2026-11-02T09:00:00.000Z",
      "updated_at": null,
      "payment_id": "LUVEI-PAYN-123456",
      "environment": "live"
    }
  ],
  "meta": {
    "page": 1,
    "per_page": 20,
    "total": 1,
    "total_pages": 1
  }
}
GET/api/account/balance

Saldo

Consulte su saldo y el importe disponible actualmente para retiro. Ambas llamadas son de solo lectura e informan sobre su billetera API, que contiene los fondos cobrados a través de esta API. Las demás billeteras de su panel no se muestran ni se incluyen.

CampoTipoDescripción
currency_codestringMoneda de todos los importes: la moneda principal del sistema.
available_amountstringFondos liquidados de su billetera API disponibles para su uso inmediato. Se excluyen los importes sin liquidar y los retenidos.
pending_settlement_amountstringFondos de pagos que aún no se han liquidado. Siempre 0.00 en sandbox.
environmentstringsandbox o live.
./payniko.sh GET '/api/account/balance'
import {api} from './payniko.mjs';

const balance = await api('GET', '/api/account/balance');
console.log(balance);
<?php
require __DIR__ . '/payniko.php';

$balance = payniko_api('GET', '/api/account/balance');
print_r($balance);
from payniko import api

balance = api("GET", "/api/account/balance")
print(balance)

Respuesta · Ejemplo

{
  "currency_code": "USD",
  "available_amount": "1250.00",
  "pending_settlement_amount": "300.00",
  "environment": "live"
}

Los pagos en otras monedas se convierten a la moneda principal. Las comisiones y las fechas de liquidación no se incluyen en esta respuesta.

GET/api/account/available-balance

Saldo retirable

CampoTipoDescripción
currency_codestringLa moneda principal del sistema.
withdrawable_amountstringFondos liquidados de su billetera API que pueden retirarse ahora. Es exactamente el importe que POST /api/account/withdrawals le permite retirar.
can_withdrawbooleanfalse mientras alguno de sus saldos sea negativo, en cuyo caso no es posible ningún retiro. true no garantiza un retiro.
environmentstringsandbox o live.
./payniko.sh GET '/api/account/available-balance'
import {api} from './payniko.mjs';

const available = await api('GET', '/api/account/available-balance');
console.log(available);
<?php
require __DIR__ . '/payniko.php';

$available = payniko_api('GET', '/api/account/available-balance');
print_r($available);
from payniko import api

available = api("GET", "/api/account/available-balance")
print(available)

Respuesta · Ejemplo

{
  "currency_code": "USD",
  "withdrawable_amount": "1250.00",
  "can_withdraw": true,
  "environment": "live"
}

Se excluyen los importes reservados para retiros abiertos, los fondos sin liquidar y las retenciones. El saldo se vuelve a comprobar cuando solicita un retiro, por lo que la solicitud aún puede fallar con 409 9000020.

POST/api/account/refundsRequiere Idempotency-Key

Solicitar un reembolso o una anulación

Devuelva al pagador el importe completo de un pago completado correctamente. Payniko revisa y procesa cada solicitud; 202 solo confirma que la solicitud se aceptó.

Cuerpo de la solicitud

CampoTipoObligatorioDescripciónEjemplo
payment_idstring · LUVEI-ABCD-123456ObligatorioUn pago en succeeded creado mediante /api/payments en el mismo entorno. Cualquier otro ID devuelve 404 9000009.LUVEI-PAYN-123456
operation_typestringObligatorioLa operación solicitada.
refundvoid
refund
reasonstringObligatorioDe 3 a 500 caracteres. Lo revisa el equipo de operaciones de Payniko.Customer requested a full refund

No existe un campo de importe; se devuelve el importe completo del pago. Un pago solo puede tener un reembolso o una anulación a la vez. Mientras uno esté abierto o completado, o mientras el pago tenga una disputa que no se haya ganado, una nueva solicitud devuelve 409 9000014.

KEY="$(openssl rand -hex 16)"  # store with the order before sending; reuse it after network errors
./payniko.sh POST '/api/account/refunds' '{
  "payment_id": "LUVEI-PAYN-123456",
  "operation_type": "refund",
  "reason": "Customer requested a full refund"
}' "$KEY"
import {api, randomUUID} from './payniko.mjs';

const key = randomUUID(); // Store this key with the order before sending; reuse it after network errors.
const refund = await api('POST', '/api/account/refunds', {
  "payment_id": "LUVEI-PAYN-123456",
  "operation_type": "refund",
  "reason": "Customer requested a full refund"
}, key);
console.log(refund);
<?php
require __DIR__ . '/payniko.php';

$key = bin2hex(random_bytes(16)); // store with the order; reuse it after network errors
$refund = payniko_api('POST', '/api/account/refunds', [
    "payment_id" => 'LUVEI-PAYN-123456',
    "operation_type" => 'refund',
    "reason" => 'Customer requested a full refund',
], $key);
print_r($refund);
from payniko import api
import uuid

key = str(uuid.uuid4())  # store with the order; reuse it after network errors
refund = api("POST", "/api/account/refunds", {
    "payment_id": "LUVEI-PAYN-123456",
    "operation_type": "refund",
    "reason": "Customer requested a full refund"
}, key)
print(refund)

Respuesta · Ejemplo

{
  "id": "LUVEI-RFND-100001",
  "operation": "refund",
  "status": "requested",
  "amount": "100.00",
  "currency": "USD",
  "reason": "Customer requested a full refund",
  "provider_reference": null,
  "provider_refunded_at": null,
  "created_at": "2026-11-02T09:00:00.000Z",
  "updated_at": null,
  "payment_id": "LUVEI-PAYN-123456",
  "environment": "live"
}

Respuesta · 202

Devuelve el reembolso. Si se reenvían la misma clave y el mismo cuerpo, se devuelve 202 con el mismo reembolso.

Posibles errores

Listar y consultar reembolsos

./payniko.sh GET '/api/account/refunds?status=completed&page=1&per_page=20'
import {api} from './payniko.mjs';

const refunds = await api('GET', '/api/account/refunds?status=completed&page=1&per_page=20');
console.log(refunds);
<?php
require __DIR__ . '/payniko.php';

$refunds = payniko_api('GET', '/api/account/refunds?status=completed&page=1&per_page=20');
print_r($refunds);
from payniko import api

refunds = api("GET", "/api/account/refunds?status=completed&page=1&per_page=20")
print(refunds)
CampoTipoObligatorioDescripción
pageinteger · queryOpcionalNúmero de página, a partir de 1.
per_pageinteger · queryOpcionalElementos por página, de 1 a 100. Valor predeterminado: 20.
statusstring · queryOpcionalDevuelve solo los reembolsos con este estado.
operation_typestring · queryOpcionalrefund o void.

GET /api/account/refunds/{id} devuelve un único reembolso (404 9000009 si no existe). La lista contiene los reembolsos solicitados a través de la API.

Objeto de reembolso

CampoTipoDescripción
idstring · LUVEI-ABCD-123456ID del reembolso.
operationstringrefund o void, tal como se envió en operation_type.
statusstringConsulte la tabla más abajo.
amountstringImporte completo del pago.
currencystringMoneda del pago.
reasonstringEl motivo indicado en la solicitud.
provider_referencestring | nullReferencia del reembolso procesado, una vez disponible.
provider_refunded_atstring · date-time | nullFecha y hora en que se procesó el reembolso, si se conoce.
created_atstring · date-timeFecha y hora de la solicitud.
updated_atstring · date-time | nullFecha y hora del último cambio.
payment_idstring · LUVEI-ABCD-123456 | nullEl pago reembolsado.
environmentstringsandbox o live.
EstadoSignificado
requestedAceptado, pero aún no procesado.
processingEn proceso.
awaiting_provider_manualSe está completando manualmente; puede tardar más.
completedCompletado. Estado final.
rejectedRechazado. Estado final.
failedFallido. Estado final.
cancelledCancelado. Estado final.

GET /api/account/refunds/{id} siempre devuelve el estado actual. El resultado también se notifica mediante un webhook.

POST/api/account/withdrawalsRequiere Idempotency-Key

Solicitar un retiro

Retire fondos de su billetera API en USDT a través de la red TRON (TRC20). El importe se reserva y se envía tras una revisión.

Cuerpo de la solicitud

CampoTipoObligatorioDescripciónEjemplo
amountstringObligatorioDos decimales, por ejemplo 50.00; no puede ser 0.00 y debe ser igual o superior a su importe mínimo. Sumado a los retiros solicitados y enviados en el día, no debe superar su límite diario."50.00"
addressstringObligatorioDirección TRC20: 34 caracteres, que empieza por T y con una suma de comprobación válida.YOUR_VERIFIED_TRC20_ADDRESS
address_acknowledgedbooleanObligatorioDebe ser true, lo que confirma que la dirección es correcta.true
webhook_urlstring · uriObligatorioEndpoint que recibe los webhooks de este retiro. Se aplican las mismas reglas que para los pagos.https://merchant.example/webhooks/withdrawals

success_url y fail_url no están permitidos en esta solicitud.

# Replace YOUR_VERIFIED_TRC20_ADDRESS with the address you confirmed with its owner.
KEY="$(openssl rand -hex 16)"  # store with the order before sending; reuse it after network errors
./payniko.sh POST '/api/account/withdrawals' '{
  "amount": "50.00",
  "address": "YOUR_VERIFIED_TRC20_ADDRESS",
  "address_acknowledged": true,
  "webhook_url": "https://merchant.example/webhooks/withdrawals"
}' "$KEY"
import {api, randomUUID} from './payniko.mjs';

// Replace YOUR_VERIFIED_TRC20_ADDRESS with the address you confirmed with its owner.
const key = randomUUID(); // Store this key with the order before sending; reuse it after network errors.
const withdrawal = await api('POST', '/api/account/withdrawals', {
  "amount": "50.00",
  "address": "YOUR_VERIFIED_TRC20_ADDRESS",
  "address_acknowledged": true,
  "webhook_url": "https://merchant.example/webhooks/withdrawals"
}, key);
console.log(withdrawal);
<?php
require __DIR__ . '/payniko.php';

// Replace YOUR_VERIFIED_TRC20_ADDRESS with the address you confirmed with its owner.
$key = bin2hex(random_bytes(16)); // store with the order; reuse it after network errors
$withdrawal = payniko_api('POST', '/api/account/withdrawals', [
    "amount" => '50.00',
    "address" => 'YOUR_VERIFIED_TRC20_ADDRESS',
    "address_acknowledged" => true,
    "webhook_url" => 'https://merchant.example/webhooks/withdrawals',
], $key);
print_r($withdrawal);
from payniko import api
import uuid

# Replace YOUR_VERIFIED_TRC20_ADDRESS with the address you confirmed with its owner.
key = str(uuid.uuid4())  # store with the order; reuse it after network errors
withdrawal = api("POST", "/api/account/withdrawals", {
    "amount": "50.00",
    "address": "YOUR_VERIFIED_TRC20_ADDRESS",
    "address_acknowledged": True,
    "webhook_url": "https://merchant.example/webhooks/withdrawals"
}, key)
print(withdrawal)

Respuesta · Ejemplo

{
  "id": "LUVEI-WTHD-100002",
  "status": "requested",
  "amount": "50.00",
  "currency": "USD",
  "asset": "USDT",
  "network": "TRC20",
  "address": "YOUR_VERIFIED_TRC20_ADDRESS",
  "usdt_amount": "49.950000",
  "tx_hash": null,
  "rejection_reason": null,
  "requested_at": "2026-11-02T10:00:00.000Z",
  "processed_at": null,
  "created_at": "2026-11-02T10:00:00.000Z",
  "environment": "live"
}

Respuesta · 201

Devuelve el retiro con su estado, normalmente requested. Si se reenvían la misma clave y el mismo cuerpo, se devuelve 201 con el mismo retiro.

Posibles errores

Listar y consultar retiros

./payniko.sh GET '/api/account/withdrawals?status=requested&page=1&per_page=20'
import {api} from './payniko.mjs';

const withdrawals = await api('GET', '/api/account/withdrawals?status=requested&page=1&per_page=20');
console.log(withdrawals);
<?php
require __DIR__ . '/payniko.php';

$withdrawals = payniko_api('GET', '/api/account/withdrawals?status=requested&page=1&per_page=20');
print_r($withdrawals);
from payniko import api

withdrawals = api("GET", "/api/account/withdrawals?status=requested&page=1&per_page=20")
print(withdrawals)

Filtre por status. GET /api/account/withdrawals/{id} devuelve un único retiro (404 9000023 si no existe).

Objeto de retiro

CampoTipoDescripción
idstring · LUVEI-ABCD-123456ID del retiro.
statusstringConsulte la tabla más abajo.
requestedsentrejected
amountstringImporte solicitado en la moneda principal.
currencystringLa moneda principal.
assetstringSiempre USDT.
networkstringSiempre TRC20.
addressstringDirección de destino.
usdt_amountstringImporte en USDT que se enviará (seis decimales).
tx_hashstring | nullHash de la transacción en la cadena de bloques, una vez conocido.
rejection_reasonstring | nullMotivo del rechazo.
requested_atstring · date-timeFecha y hora de la solicitud.
processed_atstring · date-time | nullFecha y hora en que el retiro se envió o se rechazó.
created_atstring · date-timeFecha y hora de creación.
environmentstringsandbox o live.
EstadoSignificado
requestedCreado; el importe está reservado, pero aún no se ha enviado.
sentEnviado. Estado final. tx_hash puede ser null inicialmente y se añade más tarde.
rejectedNo enviado; el importe reservado se reintegra a su saldo disponible. Consulte rejection_reason. Estado final.

El equipo de Payniko envía o rechaza cada retiro y, a continuación, establece processed_at junto con tx_hash o rejection_reason. Durante un mantenimiento, una nueva solicitud de retiro puede devolver 503 1000014.

GET/api/account/disputes

Listar y consultar disputas

Una disputa (contracargo) se abre cuando el titular de una tarjeta impugna un pago ante su banco. Al abrirse la disputa, normalmente el importe se deduce de su saldo; se le reintegra si gana la disputa y permanece deducido si la pierde. Responda antes del plazo.

./payniko.sh GET '/api/account/disputes?status=open&page=1&per_page=20'
import {api} from './payniko.mjs';

const disputes = await api('GET', '/api/account/disputes?status=open&page=1&per_page=20');
console.log(disputes);
<?php
require __DIR__ . '/payniko.php';

$disputes = payniko_api('GET', '/api/account/disputes?status=open&page=1&per_page=20');
print_r($disputes);
from payniko import api

disputes = api("GET", "/api/account/disputes?status=open&page=1&per_page=20")
print(disputes)

Respuesta · Ejemplo

{
  "data": [
    {
      "id": "LUVEI-DSPT-100003",
      "service": "api",
      "amount": "100.00",
      "currency": "USD",
      "status": "open",
      "reason": "product_not_delivered",
      "reason_note": null,
      "occurred_on": "2026-11-03",
      "evidence_due_at": "2026-11-10T09:00:00.000Z",
      "evidence_submitted_at": null,
      "merchant_evidence_note": null,
      "merchant_evidence_submitted_at": null,
      "resolved_at": null,
      "created_at": "2026-11-03T09:00:00.000Z",
      "payment_id": "LUVEI-PAYN-123456",
      "environment": "sandbox"
    }
  ],
  "meta": {
    "page": 1,
    "per_page": 20,
    "total": 1,
    "total_pages": 1
  }
}

Filtre por status. GET /api/account/disputes/{id} devuelve una única disputa (404 9000015 si no existe). La lista contiene todas las disputas de su cuenta; payment_id está definido cuando la disputa corresponde a un pago de la API.

Objeto de disputa

CampoTipoDescripción
idstring · LUVEI-ABCD-123456ID de la disputa.
servicestringOrigen del pago, por ejemplo api.
amountstringImporte en disputa, en la moneda del pago.
currencystringMoneda del pago.
statusstringConsulte la tabla más abajo.
openunder_reviewwonlost
reasonstringMotivo indicado por el banco. Su integración debe gestionar también valores desconocidos.
fraudunauthorizedproduct_not_deliveredduplicateamount_mismatchother
reason_notestring | nullNota del banco, si la hay.
occurred_onstring · dateFecha de la disputa (YYYY-MM-DD).
evidence_due_atstring · date-time | nullPlazo para enviar su respuesta.
evidence_submitted_atstring · date-time | nullFecha y hora en que se presentó la defensa ante el banco.
merchant_evidence_notestring | nullSu respuesta más reciente.
merchant_evidence_submitted_atstring · date-time | nullFecha y hora en que envió su respuesta.
resolved_atstring · date-time | nullFecha y hora en que se resolvió la disputa.
created_atstring · date-timeFecha y hora de creación.
payment_idstring · LUVEI-ABCD-123456 | nullEl pago de la API en disputa; en caso contrario, null.
environmentstringsandbox o live.
EstadoSignificado
openDisputa nueva. Puede responder hasta evidence_due_at.
under_reviewLa defensa se ha presentado ante el banco y la decisión está pendiente. Aún puede responder hasta que venza el plazo.
wonResuelta a su favor. Estado final.
lostResuelta en su contra. Estado final.
POST/api/account/disputes/{id}/evidenceRequiere Idempotency-Key

Responder a una disputa

Cuerpo de la solicitud

CampoTipoObligatorioDescripción
notestringObligatorioSu respuesta, de 3 a 4000 caracteres: datos de la entrega, comunicaciones con el cliente y las pruebas de las que dispone.
KEY="$(openssl rand -hex 16)"  # store with the order before sending; reuse it after network errors
./payniko.sh POST '/api/account/disputes/LUVEI-DSPT-100003/evidence' '{
  "note": "The order was delivered on 2026-10-28; tracking number and signed receipt are available."
}' "$KEY"
import {api, randomUUID} from './payniko.mjs';

const key = randomUUID(); // Store this key with the order before sending; reuse it after network errors.
const dispute = await api('POST', '/api/account/disputes/LUVEI-DSPT-100003/evidence', {
  "note": "The order was delivered on 2026-10-28; tracking number and signed receipt are available."
}, key);
console.log(dispute);
<?php
require __DIR__ . '/payniko.php';

$key = bin2hex(random_bytes(16)); // store with the order; reuse it after network errors
$dispute = payniko_api('POST', '/api/account/disputes/LUVEI-DSPT-100003/evidence', [
    "note" => 'The order was delivered on 2026-10-28; tracking number and signed receipt are available.',
], $key);
print_r($dispute);
from payniko import api
import uuid

key = str(uuid.uuid4())  # store with the order; reuse it after network errors
dispute = api("POST", "/api/account/disputes/LUVEI-DSPT-100003/evidence", {
    "note": "The order was delivered on 2026-10-28; tracking number and signed receipt are available."
}, key)
print(dispute)

Respuesta · Ejemplo

{
  "id": "LUVEI-DSPT-100003",
  "service": "api",
  "amount": "100.00",
  "currency": "USD",
  "status": "open",
  "reason": "product_not_delivered",
  "reason_note": null,
  "occurred_on": "2026-11-03",
  "evidence_due_at": "2026-11-10T09:00:00.000Z",
  "evidence_submitted_at": null,
  "merchant_evidence_note": "The order was delivered on 2026-10-28; tracking number and signed receipt are available.",
  "merchant_evidence_submitted_at": "2026-11-04T08:00:00.000Z",
  "resolved_at": null,
  "created_at": "2026-11-03T09:00:00.000Z",
  "payment_id": "LUVEI-PAYN-123456",
  "environment": "sandbox"
}

Respuesta · 200

Devuelve la disputa, incluida su nota.

  • Solo se acepta mientras la disputa está en open o under_review y antes de evidence_due_at; en caso contrario, la solicitud devuelve 409 9000016.
  • Una nueva solicitud con un Idempotency-Key nuevo sustituye a su nota anterior.
  • La API no admite la carga de archivos. Describa en la nota las pruebas disponibles.

Posibles errores

Para probar las disputas con una clave de sandbox, cree una con POST /api/sandbox/disputes.