> ## Documentation Index
> Fetch the complete documentation index at: https://docs.filexpress.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Accounts payable

> Purchases with a balance, current/overdue summary, history and supplier payment registration

| Permission | Endpoints |
| - | - |
| `payables` | `GET /payables`, `GET /payables/summary`, `GET /payables/{expense_id}/payments` |
| `payables.payments` | `POST /payables/payments`, `POST /payables/payments/{payment_id}/reverse` |

> [!NOTE]
>
> These are **explicit** permissions: they must be checked one by one in **External integrations**; existing integrations do not receive them automatically.

Query purchases with an outstanding balance and apply payments to suppliers. It uses the same logic as **Accounts payable** in FileXpress.

> [!TIP]
>
> Bank, petty cash and checkbook IDs are obtained with [Banks, petty cash funds and checkbooks](https://docs.filexpress.app/en/docs/api/tesoreria.md) (`treasury` permission).

## Pending documents

```http theme={null}
GET /payables?branch_id={branch_id}&provider_id={provider_id}
```

| Parameter | Type | Required | Description |
| - | - | - | - |
| `branch_id` | string | Yes | Branch. |
| `provider_id` | string | No | Filters by supplier. |

Includes non-deleted purchases with an outstanding balance, from the business environment.

```json theme={null}
{
  "status": true,
  "data": {
    "data": [
      {
        "expense_id": "9a10...",
        "generation_code": "DTE-03-M001P001-000000000000123",
        "document_type": "ccf",
        "issue_date": "2026-08-20",
        "due_date": "2026-09-19",
        "days_overdue": 17,
        "provider_id": "9c77...",
        "provider_name": "Distribuidora Central, S.A. de C.V.",
        "total_amount": 1130.0,
        "amount_paid": 500.0,
        "pending_amount": 630.0,
        "payment_status": "partial",
        "currency_code": "USD",
        "base_currency_code": "USD",
        "exchange_rate": null,
        "foreign_total": null,
        "foreign_balance": null
      }
    ],
    "total_pending": 630.0
  }
}
```

| Field | Description |
| - | - |
| `due_date` | Issue date + the document's credit days (30 if it has none). |
| `days_overdue` | Days elapsed since the due date (0 if it is current). |
| `provider_name` | Legal name or, if it has none, trade name. |
| `amount_paid` | Sum of applied payments (reversed ones don't count). |
| `payment_status` | `pending` (no payments) or `partial` (with partial payments). |
| `total_pending` | Sum of `pending_amount` in the list. |
| `currency_code` | Document currency. It is the base currency if the document was issued in it. |
| `base_currency_code` | The business base currency, in which `total_amount`, `amount_paid`, `pending_amount` and `total_pending` are expressed. |
| `exchange_rate` | Rate at which the document was issued (base currency units per 1 unit of `currency_code`). `null` if the document is in the base currency. |
| `foreign_total` | Document total in its currency. `null` if the document is in the base currency. |
| `foreign_balance` | Pending balance in the document currency (`pending_amount` ÷ `exchange_rate`). `null` if the document is in the base currency. |

Sorted from the oldest to the most recent document. **Errors**: `404` `Branch not found`; `422` validation.

> [!NOTE]
>
> **Document currency.** The amounts in the list (`total_amount`, `amount_paid`, `pending_amount`, `total_pending`) and the collections/payments are always in the **base currency**. The fields `currency_code`, `base_currency_code`, `exchange_rate`, `foreign_total` and `foreign_balance` are a reference added per row: for a document issued in a foreign currency (for example GTQ with a rate of `0.128`) they show how much the document was and how much remains in its currency. For documents in the base currency, `exchange_rate`, `foreign_total` and `foreign_balance` are `null`. Foreign-currency documents are issued with the [API v2](https://docs.filexpress.app/en/docs/api/v2/introduccion.md); this route remains on v1.

Example of a row for a document issued in GTQ (rate `0.128`, total 1,130.00 GTQ = 144.64 USD, no partial payments):

```json theme={null}
{
  "total_amount": 144.64,
  "amount_paid": 0.0,
  "pending_amount": 144.64,
  "currency_code": "GTQ",
  "base_currency_code": "USD",
  "exchange_rate": 0.128,
  "foreign_total": 1130.0,
  "foreign_balance": 1130.0
}
```

## Current / overdue summary

```http theme={null}
GET /payables/summary?branch_id={branch_id}
```

```json theme={null}
{
  "status": true,
  "data": {
    "total": 15420.5,
    "current": 9800.0,
    "overdue": 5620.5,
    "current_count": 14,
    "overdue_count": 6
  }
}
```

`current` adds up the documents with `days_overdue = 0`; `overdue`, the overdue ones. `branch_id` is required: without it (or from another business) it responds `404` `Branch not found`.

## Payment history

```http theme={null}
GET /payables/{expense_id}/payments
```

```json theme={null}
{
  "status": true,
  "data": [
    {
      "id": "9f20...",
      "amount": "500.00",
      "pay_date": "2026-09-05 14:12:00",
      "reference": "TRF-88231",
      "status": "applied",
      "payment_method_name": "Transferencia bancaria",
      "bank_name": "Banco Agrícola"
    }
  ]
}
```

Includes all payments of the document in date order, including reversed ones (`status` other than `applied`). **Errors**: `404` `Bill not found` (nonexistent or from another business).

## Register payment

```http theme={null}
POST /payables/payments
```

There are two ways to indicate which documents the payment applies to:

> [tab] By document (allocations)
>
> You specify each purchase and the amount to apply to it.
>
> ```json theme={null}
> {
>   "payment_method_id": "pm-uuid",
>   "bank_id": "bank-uuid",
>   "payment_date": "2026-10-06",
>   "reference_number": "TRF-90112",
>   "allocations": [
>     { "expense_id": "9a10...", "amount": 630.00 },
>     { "expense_id": "9a14...", "amount": 250.00 }
>   ]
> }
> ```

> [tab] Automatic by supplier
>
> You specify the supplier, the branch and the total amount; FileXpress distributes it **from the oldest document to the most recent** until it is used up.
>
> ```json theme={null}
> {
>   "payment_method_id": "pm-uuid",
>   "bank_id": "bank-uuid",
>   "payment_date": "2026-10-06",
>   "provider_id": "9c77...",
>   "branch_id": "9d1c5a3e-...",
>   "amount": 880.00
> }
> ```

| Field | Type | Required | Description |
| - | - | - | - |
| `payment_method_id` | string | Yes | Payment method (see [catalogs](https://docs.filexpress.app/en/docs/api/facturacion/catalogos.md)). |
| `payment_date` | date | Yes | Payment date `YYYY-MM-DD` (stored with the current time). |
| `bank_id` | string | No | Bank the payment is made from (belonging to the business). |
| `petty_cash_id` | string | No | Petty cash fund the payment is made from (belonging to the business). |
| `checkbook_id` | string | No | Checkbook (belonging to the business). |
| `check_number` | string | No | Check number (max. 50). |
| `cost_center_id` | string | No | Payment [cost center](https://docs.filexpress.app/en/docs/api/contabilidad/centros-de-costo.md) (leaf and active center). If not sent, it takes the purchase's. |
| `reference_number` | string | No | Reference (max. 255). |
| `notes` | string | No | Max. 500. |
| `allocations` | array | Yes, if `provider_id` is not sent | 1 to 200 items. |
| `allocations[].expense_id` | string | Yes, with `allocations` | Purchase of the business. |
| `allocations[].amount` | number | Yes, with `allocations` | Greater than 0 and not greater than its pending balance. |
| `provider_id` | string | Yes, if `allocations` is not sent | Supplier. |
| `branch_id` | string | Yes, with `provider_id` | Branch of the documents. |
| `amount` | number | Yes, with `provider_id` | Total amount; cannot exceed the supplier's total pending balance in the branch. |

**Rules**

* **All or nothing**: payments are applied in a single transaction. If one document fails, none is applied.
* The amount for each document cannot exceed its pending balance; when it is fully covered it becomes `payed`, otherwise `partial`.
* The bank, petty cash fund and checkbook, if sent, must belong to the business. The petty cash rules (funds) and checkbook rules are validated the same way as on the web; if they fail, it responds `422` with the corresponding message.
* `cost_center_id` is stored on each payment for reports. When posted to the books, it only passes to the lines of income statement accounts (for example, exchange differences); the bank, cash and supplier lines are left without a center. A nonexistent, inactive center or one with sub-centers responds `422` and no payment is applied.
* We recommend sending [`Idempotency-Key`](https://docs.filexpress.app/en/docs/api/introduccion#idempotency) so you don't duplicate the payment if you retry.
* Registered payments are ready to be posted in [Process documents](https://docs.filexpress.app/en/docs/contabilidad/procesar-documentos.md) (type **Pagos a proveedores**, supplier payments).

```bash theme={null}
curl -X POST https://api.filexpress.app/api/external/v1/payables/payments \
  -H "X-API-Key: fx_xxxxxxxx" \
  -H "Idempotency-Key: pago-prov-20261006-0017" \
  -H "Content-Type: application/json" \
  -d '{"payment_method_id":"pm-uuid","payment_date":"2026-10-06","provider_id":"9c77...","branch_id":"9d1c5a3e-...","amount":880.00}'
```

**Response `201`**

```json theme={null}
{
  "status": true,
  "data": {
    "payments": [
      {
        "payment_id": "9f31...",
        "expense_id": "9a10...",
        "generation_code": "DTE-03-M001P001-000000000000123",
        "amount": 630.0,
        "pending_amount": 0.0,
        "payment_status": "payed"
      },
      {
        "payment_id": "9f32...",
        "expense_id": "9a14...",
        "generation_code": "DTE-03-M001P001-000000000000131",
        "amount": 250.0,
        "pending_amount": 150.0,
        "payment_status": "partial"
      }
    ],
    "total_applied": 880.0
  }
}
```

**Errors**

| Code | Cause |
| - | - |
| `404` | `Bill <id> not found` (in `allocations`, from another business or nonexistent) / `Branch not found`. |
| `422` | Validation (`Validation errors` with `errors`). |
| `422` | `Payment method not found` / `Bank not found` / `Petty cash not found` / `Checkbook not found` (from another business or nonexistent). |
| `422` | `The amount exceeds the provider pending balance.` (automatic mode). |
| `422` | Invalid cost center: `El centro de costo no existe o no pertenece a esta empresa.` / `… está inactivo.` / `… tiene subcentros; seleccione un centro hoja.` |
| `422` | `El monto para la compra <código> excede lo pendiente. Pendiente: <monto>` / `La compra <código> ya está pagada.` |
| `409` | `Idempotency-Key` conflict. |

## Reverse payment

```http theme={null}
POST /payables/payments/{payment_id}/reverse
```

Cancels an applied payment. Requires the `payables.payments` permission. The `payment_id` is the one returned when registering the payment or the `id` from the history.

| Field | Type | Required | Description |
| - | - | - | - |
| `reason` | string | No | Reason (max. 500). It is only returned in the response; it is not stored. |

```bash theme={null}
curl -X POST https://api.filexpress.app/api/external/v1/payables/payments/9f31.../reverse   -H "X-API-Key: fx_xxxxxxxx"   -H "Idempotency-Key: reversa-pago-9f31"   -H "Content-Type: application/json"   -d '{"reason":"Pago duplicado"}'
```

**Response `200`**

```json theme={null}
{
  "status": true,
  "data": {
    "reversed_payment": {
      "payment_id": "9f31...",
      "original_amount": 630.0,
      "reversal_reason": "Pago duplicado",
      "reversed_at": "2026-10-06T15:40:12-06:00"
    },
    "expense_info": {
      "expense_id": "9a10...",
      "generation_code": "DTE-03-M001P001-000000000000123",
      "total_amount": 1130.0,
      "total_paid": 500.0,
      "pending_amount": 630.0,
      "payment_status": "partial"
    },
    "accounting": {
      "action": "reversed",
      "journal_entry_id": "b7c2...",
      "entry_code": "DIA-000145",
      "status": "PROCESADA"
    }
  }
}
```

**Rules**

* The payment is left with `status: "reversed"` and no longer counts toward the balance; the purchase's `payment_status` is recalculated (`pending`, `partial` or `payed`).
* The effect on the bank, petty cash fund or checkbook that generated the payment is offset.
* `accounting` indicates what happened to the payment's journal entry (see [Payment reversal and its journal entry](https://docs.filexpress.app/en/docs/contabilidad/procesar-documentos.md#payment-reversal-and-its-entry)): `none` (not yet posted; `journal_entry_id`, `entry_code` and `status` are `null`), `deleted` (the entry was in Draft and was marked `ELIMINADA`) or `reversed` (a mirror entry was created with reference `payment_made_reversal`, dated today; `status` according to the corresponding *Status when processing* setting).
* Without `reason`, `reversal_reason` is `Payment reversed`.
* We recommend sending [`Idempotency-Key`](https://docs.filexpress.app/en/docs/api/introduccion#idempotency).

**Errors**

| Code | Cause |
| - | - |
| `404` | `Payment not found` (nonexistent or from another business). |
| `409` | `El pago ya fue revertido.` / `Idempotency-Key` conflict. |
| `422` | Validation (`reason` longer than 500 characters) / `No se pudo revertir la partida contable del pago: …` (e.g., there is no open period for today); the payment is not reversed. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.