Developer guide
VEXPay siteAPI reference
Browse documentation

Reconcile your balance

List every movement of your VES balance, rebuild it exactly, and handle card chargebacks automatically.

Balance movements

GET /v1/balance/transactions lists every movement of your VES balance, newest first: payments, fees, payouts, reversals, card chargebacks, adjustments, seller transfers and conversions. Each movement has a stable id, a type, a signed amountVes (negative = money out) and the linked paymentId / payoutId / chargebackId.

curlbash
curl "${API_URL}/v1/balance/transactions?limit=100" \
  --header "x-api-key: ${VEXPAY_API_KEY}"
Node SDKjavascript
let total = 0;
for await (const m of vexpay.balance.transactions.list({ limit: 100 })) {
  total += Number(m.amountVes);
}
const balance = await vexpay.balance.retrieve();
// total === Number(balance.ledgerNetVes)
Responsejson
{
  "items": [
    { "id": "6b1f…", "type": "chargeback", "amountVes": "-4000.00", "paymentId": "a3c9…", "chargebackId": "c71e…", "externalRef": "order-1042", "description": "Card chargeback (fraud)", "createdAt": "2026-10-08T14:02:11.000Z" },
    { "id": "5e0a…", "type": "fee", "amountVes": "-140.00", "paymentId": "a3c9…", "description": "Platform fee", "createdAt": "2026-10-01T10:00:00.000Z" }
  ],
  "nextCursor": "MjAyNi0xMC0wMVQxMDowMDowMC4wMDBafDVlMGE…"
}
  • Pass nextCursor as cursor for older movements; nextCursor: null is the last page. New movements never shift the pages you are walking.
  • Filter with type (repeat or comma-separate), paymentId, payoutId, from (inclusive) and to (exclusive).
  • The sum of amountVes over all movements equals ledgerNetVes from GET /v1/balance; minus reserveVes and heldVes it equals availableVes. Movements still under the 24h balance hold carry availableAt. If your ledger disagrees, the movement you are missing is in this list.

Card chargebacks

When a cardholder disputes a card (VPOS) payment, the bank charges it back. VEXPay debits the charged-back amount — plus a chargeback fee, when there is one — from your available VES balance and sends payment.chargeback (see Chargeback events below). The platform fee of the original payment is not returned. A chargeback for the full amount also marks the payment REVERSED and sends payment.reversed with reversalType: "chargeback".

  • ledgerEntryIds are the ids of the movements the event created — find them in GET /v1/balance/transactions?paymentId=… to book the debit without guessing.
  • Your balance can go negative. While it is negative, payouts and conversions answer insufficient_balance until new collections cover it.
  • When the dispute is decided you receive payment.chargeback_closed: outcome: "won" returns the amount and fee (new chargeback_reversal movements, payment back to COMPLETED); outcome: "lost" changes nothing more.
  • Partial chargebacks are possible; a payment can have several, never more than its amount.

Chargeback events

Both events use the standard signed envelope (VexPay-Signature, VexPay-Event-Id) and are only delivered to endpoints that list them. data has the same fields in both; payment.chargeback_closed adds outcome and closedAt.

FieldTypeMeaning
chargebackIdstring (uuid)Stable id of the chargeback. Same value in both events.
paymentId / externalRefstringThe card payment that was charged back and your reference for it.
method"VPOS"Card payments only.
status"open" | "won" | "lost"State of the chargeback when the event was sent.
outcome"won" | "lost"Only in payment.chargeback_closed.
amountVesstring, 2 decimalsCharged-back amount (positive). Partial chargebacks are possible.
feeVesstring, 2 decimalsChargeback fee debited on top of the amount ("0.00" when none).
reasonstringfraud | not_recognized | not_received | duplicate | other.
bankDebitedAtISO 8601When the bank debited the chargeback.
paymentStatusstringPayment status after the event: REVERSED for a full chargeback (open or lost), COMPLETED for a partial one or after a won dispute.
vesAmount / usdAmountstring, 2 decimalsAmounts of the original payment.
ledgerEntryIdsstring[]Ids of the balance movements this event created (empty when closed as lost). Match them in GET /v1/balance/transactions.
createdAt / closedAtISO 8601When the chargeback was recorded / decided.
livemodebooleanfalse for test-mode deliveries.

Example bodies

A full Bs 4,000.00 chargeback with a Bs 50.00 fee on payment order-1042, then the dispute closed. livemode is added to every data object.

payment.chargebackjson
{
  "event": "payment.chargeback",
  "data": {
    "chargebackId": "c71e2f4a-8d1b-4c3e-9a6f-2b5d7e9c1a03",
    "paymentId": "a3c9b8d2-5e4f-4a1b-8c7d-6e5f4a3b2c10",
    "externalRef": "order-1042",
    "method": "VPOS",
    "status": "open",
    "amountVes": "4000.00",
    "feeVes": "50.00",
    "reason": "fraud",
    "bankDebitedAt": "2026-10-07T00:00:00.000Z",
    "paymentStatus": "REVERSED",
    "vesAmount": "4000.00",
    "usdAmount": "100.00",
    "ledgerEntryIds": [
      "6b1f0c2e-3d4a-4b5c-8d9e-0f1a2b3c4d5e",
      "7c2a1d3f-4e5b-4c6d-9e0f-1a2b3c4d5e6f"
    ],
    "createdAt": "2026-10-08T14:02:11.000Z",
    "livemode": true
  },
  "timestamp": "2026-10-08T14:02:11.412Z"
}
payment.chargeback_closed (won)json
{
  "event": "payment.chargeback_closed",
  "data": {
    "chargebackId": "c71e2f4a-8d1b-4c3e-9a6f-2b5d7e9c1a03",
    "paymentId": "a3c9b8d2-5e4f-4a1b-8c7d-6e5f4a3b2c10",
    "externalRef": "order-1042",
    "method": "VPOS",
    "status": "won",
    "outcome": "won",
    "amountVes": "4000.00",
    "feeVes": "50.00",
    "reason": "fraud",
    "bankDebitedAt": "2026-10-07T00:00:00.000Z",
    "paymentStatus": "COMPLETED",
    "vesAmount": "4000.00",
    "usdAmount": "100.00",
    "ledgerEntryIds": [
      "8d3b2e4a-5f6c-4d7e-0f1a-2b3c4d5e6f70",
      "9e4c3f5b-6a7d-4e8f-1a2b-3c4d5e6f7081"
    ],
    "createdAt": "2026-10-08T14:02:11.000Z",
    "closedAt": "2026-10-22T09:30:00.000Z",
    "livemode": true
  },
  "timestamp": "2026-10-22T09:30:00.518Z"
}
payment.chargeback_closed (lost)json
{
  "event": "payment.chargeback_closed",
  "data": {
    "chargebackId": "c71e2f4a-8d1b-4c3e-9a6f-2b5d7e9c1a03",
    "paymentId": "a3c9b8d2-5e4f-4a1b-8c7d-6e5f4a3b2c10",
    "externalRef": "order-1042",
    "method": "VPOS",
    "status": "lost",
    "outcome": "lost",
    "amountVes": "4000.00",
    "feeVes": "50.00",
    "reason": "fraud",
    "bankDebitedAt": "2026-10-07T00:00:00.000Z",
    "paymentStatus": "REVERSED",
    "vesAmount": "4000.00",
    "usdAmount": "100.00",
    "ledgerEntryIds": [],
    "createdAt": "2026-10-08T14:02:11.000Z",
    "closedAt": "2026-10-22T09:30:00.000Z",
    "livemode": true
  },
  "timestamp": "2026-10-22T09:30:00.518Z"
}
payment.reversed (full chargeback)json
{
  "event": "payment.reversed",
  "data": {
    "paymentId": "a3c9b8d2-5e4f-4a1b-8c7d-6e5f4a3b2c10",
    "externalRef": "order-1042",
    "status": "REVERSED",
    "method": "VPOS",
    "usdAmount": 100,
    "vesAmount": 4000,
    "bcvRate": 40,
    "feeVes": 140,
    "netVes": 3860,
    "cardLast4": "4242",
    "reversedAt": "2026-10-08T14:02:11.000Z",
    "reversalRef": "chargeback:c71e2f4a-8d1b-4c3e-9a6f-2b5d7e9c1a03",
    "reversalType": "chargeback",
    "chargebackId": "c71e2f4a-8d1b-4c3e-9a6f-2b5d7e9c1a03",
    "chargebacks": [
      { "chargebackId": "c71e2f4a-8d1b-4c3e-9a6f-2b5d7e9c1a03", "status": "open", "amountVes": "4000.00", "feeVes": "50.00", "reason": "fraud", "bankDebitedAt": "2026-10-07T00:00:00.000Z" }
    ],
    "createdAt": "2026-10-01T10:00:00.000Z",
    "livemode": true
  },
  "timestamp": "2026-10-08T14:02:11.430Z"
}
GET /v1/balance/transactions?paymentId=…json
{
  "items": [
    {
      "id": "7c2a1d3f-4e5b-4c6d-9e0f-1a2b3c4d5e6f",
      "type": "chargeback_fee",
      "amountVes": "-50.00",
      "paymentId": "a3c9b8d2-5e4f-4a1b-8c7d-6e5f4a3b2c10",
      "chargebackId": "c71e2f4a-8d1b-4c3e-9a6f-2b5d7e9c1a03",
      "externalRef": "order-1042",
      "description": "Chargeback fee",
      "createdAt": "2026-10-08T14:02:11.000Z"
    },
    {
      "id": "6b1f0c2e-3d4a-4b5c-8d9e-0f1a2b3c4d5e",
      "type": "chargeback",
      "amountVes": "-4000.00",
      "paymentId": "a3c9b8d2-5e4f-4a1b-8c7d-6e5f4a3b2c10",
      "chargebackId": "c71e2f4a-8d1b-4c3e-9a6f-2b5d7e9c1a03",
      "externalRef": "order-1042",
      "description": "Card chargeback (fraud)",
      "createdAt": "2026-10-08T14:02:11.000Z"
    },
    {
      "id": "5e0a9b8c-7d6e-4f5a-8b9c-0d1e2f3a4b5c",
      "type": "fee",
      "amountVes": "-140.00",
      "paymentId": "a3c9b8d2-5e4f-4a1b-8c7d-6e5f4a3b2c10",
      "externalRef": "order-1042",
      "description": "Platform fee",
      "createdAt": "2026-10-01T10:00:00.000Z"
    },
    {
      "id": "4d9f8a7b-6c5d-4e4f-9a8b-7c6d5e4f3a2b",
      "type": "payment",
      "amountVes": "4000.00",
      "paymentId": "a3c9b8d2-5e4f-4a1b-8c7d-6e5f4a3b2c10",
      "externalRef": "order-1042",
      "description": "Payment collected",
      "createdAt": "2026-10-01T10:00:00.000Z"
    }
  ],
  "nextCursor": null
}

ledgerEntryIds of payment.chargeback are the chargeback and chargeback_fee movements above. When the dispute is won, payment.chargeback_closed carries the ids of two new chargeback_reversal movements (+4,000.00 and +50.00). When it is lost, ledgerEntryIds is empty and nothing else moves.