> ## 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 receivable

> Invoices with balance, current/overdue summary, history and payment registration

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

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

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

Query customer invoices with an outstanding balance and apply payments. It uses the same logic as **Accounts Receivable** in FileXpress.

## Pending documents

```http theme={null}
GET /receivables?branch_id={branch_id}&customer_id={customer_id}
```

| Parameter | Type | Required | Description |
| - | - | - | - |
| `branch_id` | string | Yes | Branch. |
| `customer_id` | string | No | Filters by customer. |

Includes **processed** invoices of type CCF, FC and FEX with an outstanding balance, from the business's environment, excluding those invalidated by a related document.

```json theme={null}
{
  "status": true,
  "data": {
    "data": [
      {
        "sale_id": "9a10...",
        "generation_code": "DTE-03-M001P001-000000000000123",
        "document_type": "ccf",
        "issue_date": "2026-08-20",
        "due_date": "2026-09-19",
        "days_overdue": 17,
        "customer_id": "9c77...",
        "customer_name": "Grupo Alfa, 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). |
| `customer_name` | Legal name or, if it has none, trade name. |
| `amount_paid` | Sum of applied payments (reversed ones do not 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's base currency, in which `total_amount`, `amount_paid`, `pending_amount` and `total_pending` are expressed. |
| `exchange_rate` | Rate at which the document was issued (units of base currency 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` | Outstanding balance in the document's currency (`pending_amount` ÷ `exchange_rate`). `null` if the document is in the base currency. |

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

> [!NOTE]
>
> **Document currency.** The amounts in the list (`total_amount`, `amount_paid`, `pending_amount`, `total_pending`) and payments always remain 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 rate `0.128`) they show what the document amounted to and how much remains in its currency. For documents in the base currency, `exchange_rate`, `foreign_total` and `foreign_balance` come as `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 /receivables/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 documents with `days_overdue = 0`; `overdue` adds up the overdue ones. `branch_id` is required: without it (or with one from another business) it responds `404` `Branch not found`.

## Payment history

```http theme={null}
GET /receivables/{sale_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",
      "petty_cash_id": null,
      "cost_center_id": "c3a1...",
      "payment_method_name": "Transferencia bancaria",
      "bank_name": "Banco Agrícola"
    }
  ]
}
```

`petty_cash_id` indicates the petty cash that received the payment (if applicable) and `cost_center_id` the payment's cost center.

Includes all of the document's payments in date order, also reversed ones (`status` other than `applied`). **Errors**: `404` `Invoice not found` (nonexistent or belonging to another business).

## Register payment

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

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

> [tab] By document (allocations)
>
> You specify each invoice 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": [
>     { "sale_id": "9a10...", "amount": 630.00 },
>     { "sale_id": "9a14...", "amount": 250.00 }
>   ]
> }
> ```

> [tab] Automatic by customer
>
> You specify the customer, the branch and the total amount; FileXpress distributes it **from the oldest document to the most recent** until it runs out.
>
> ```json theme={null}
> {
>   "payment_method_id": "pm-uuid",
>   "bank_id": "bank-uuid",
>   "payment_date": "2026-10-06",
>   "customer_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 where the payment is deposited (belonging to the business). |
| `petty_cash_id` | string | No | Petty cash that receives the payment (belonging to the business). Only with a cash payment method and without `bank_id`. |
| `cost_center_id` | string | No | Payment's [cost center](https://docs.filexpress.app/en/docs/api/contabilidad/centros-de-costo.md) (leaf and active center). If not sent, it takes the sale's. |
| `reference_number` | string | No | Reference (max. 255). |
| `notes` | string | No | Max. 500. |
| `allocations` | array | Yes, if `customer_id` is not sent | 1 to 200 elements. |
| `allocations[].sale_id` | string | Yes, with `allocations` | Business invoice (sale). |
| `allocations[].amount` | number | Yes, with `allocations` | Greater than 0 and not greater than its outstanding balance. |
| `customer_id` | string | Yes, if `allocations` is not sent | Customer. |
| `branch_id` | string | Yes, with `customer_id` | Branch of the documents. |
| `amount` | number | Yes, with `customer_id` | Total amount; it cannot exceed the customer's total outstanding balance in the branch. |

**Rules**

* **All or nothing**: payments are applied in a single transaction. If one document fails, none is applied.
* Each document's amount cannot exceed its outstanding balance; when it is fully covered it becomes `payed`, otherwise `partial`.
* If you send `bank_id`, the bank must belong to the business; the deposit is recorded.
* If you send `petty_cash_id`, the payment enters that petty cash: an income is recorded that increases its balance and, when posted, the journal entry debits the petty cash's ledger account. Bank and petty cash are mutually exclusive.
* `cost_center_id` is stored on each payment for reports; when posted, it only carries over to income statement account lines (bank, cash and receivables lines have no center).
* We recommend sending [`Idempotency-Key`](https://docs.filexpress.app/en/docs/api/introduccion#idempotency) so the payment is not duplicated if you retry.
* Registered payments are ready to be posted in [Process documents](https://docs.filexpress.app/en/docs/contabilidad/procesar-documentos.md) (type **Customer payments**).

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

**`201` response**

```json theme={null}
{
  "status": true,
  "data": {
    "payments": [
      {
        "payment_id": "9f31...",
        "sale_id": "9a10...",
        "generation_code": "DTE-03-M001P001-000000000000123",
        "amount": 630.0,
        "pending_amount": 0.0,
        "payment_status": "payed"
      },
      {
        "payment_id": "9f32...",
        "sale_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` | `Invoice <id> not found` (in `allocations`, belonging to 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` (belonging to another business or nonexistent). |
| `422` | `Indique banco o caja chica, no ambos.` / `La caja chica solo aplica a cobros en efectivo.` |
| `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` | `The amount exceeds the customer pending balance.` (automatic mode). |
| `422` | `El monto para la factura <código> excede lo pendiente. Pendiente: <monto>` / `La factura <código> ya está pagada.` |
| `409` | `Idempotency-Key` conflict. |

## Reverse payment

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

Voids an applied payment. Requires the `receivables.payments` permission. The `payment_id` is the one returned when the payment was registered or the history's `id`.

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

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

**`200` response**

```json theme={null}
{
  "status": true,
  "data": {
    "reversed_payment": {
      "payment_id": "9f31...",
      "original_amount": 630.0,
      "reversal_reason": "Cobro duplicado",
      "reversed_at": "2026-10-06T15:40:12-06:00"
    },
    "sale_info": {
      "sale_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 invoice's `payment_status` is recalculated (`pending`, `partial` or `payed`).
* The bank deposit that the payment generated is offset or, if it entered a petty cash, an adjustment is recorded that deducts that amount from its balance.
* `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_received_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 belonging to another business). |
| `409` | `El cobro ya fue revertido.` / `Idempotency-Key` conflict. |
| `422` | Validation (`reason` longer than 500 characters) / `No se pudo revertir la partida contable del cobro: …` (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.