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

# Sales

> Issue and query electronic sales documents

**Required permission:** `sales`

## Create sale

```http theme={null}
POST /sales
```

Issues a sales document and transmits it to the Ministry of Finance (Hacienda) when applicable (El Salvador's electronic invoicing).

> [!WARNING]
>
> The external system must **calculate the tax breakdowns** per line and the document totals. FileXpress does not recalculate them: it validates and issues with the amounts received.

```json theme={null}
{
  "branch_id": "uuid",
  "customer_id": "uuid",
  "document_type": "fc",
  "date": "2026-10-01T10:00:00",
  "observation": "Entrega en bodega central",
  "is_credit": false,
  "credit_days": 0,
  "cost_center_id": "c3a1...",
  "cost_center_distribution_id": null,
  "payment_details": [
    { "code": "01", "payment_method": "Efectivo", "amount": 22.60, "reference": "" }
  ],
  "products": [
    {
      "id": "uuid-del-producto",
      "sku": "PRD-001",
      "name": "Producto A",
      "quantity": 2,
      "price_before_taxes": 10.00,
      "sale_not_suject": 0,
      "sale_exent": 0,
      "sale_taxed": 20.00,
      "subtotal": 20.00,
      "discount": 0,
      "type": "phisical",
      "cost_center_id": null
    }
  ],
  "totals": {
    "netTotals": 20.00,
    "saleTotalNotSuject": 0,
    "saleTotalExent": 0,
    "saleTotalTax": 20.00,
    "totalTax": 2.60,
    "totalRetein": 0,
    "totalRent": 0,
    "freight": 0,
    "insurance": 0,
    "saleTotalToPayment": 22.60
  }
}
```

### Fields

| Field | Type | Required | Description |
| - | - | - | - |
| `branch_id` | uuid | Yes | Issuing branch. See `GET /branches`. |
| `customer_id` | uuid | Yes | Receiving customer. See [Customers](https://docs.filexpress.app/en/docs/api/facturacion/clientes.md). |
| `document_type` | string | Yes | El Salvador: `fc` (Factura Consumidor Final, consumer invoice), `ccf` (Comprobante de Crédito Fiscal, tax credit invoice), `fex` (export invoice), `nc` (credit note), `nd` (debit note), `nr` (delivery note). United States: `inv` (Invoice), `cm` (Credit Memo), `dm` (Debit Memo). |
| `date` | datetime | No | Issue date and time (ISO 8601). Defaults to the moment of the request. |
| `observation` | string | No | Document remarks. |
| `is_credit` | boolean | No | Credit sale. Defaults to `false`. |
| `credit_days` | integer | No | Credit days when `is_credit` is `true`. |
| `payment_details` | array | Yes | Payment methods (minimum 1). |
| `products` | array | Yes | Document lines (minimum 1). |
| `totals` | object | Yes | Document totals. |
| `point_of_sale_id` | uuid | No | [Point of sale](https://docs.filexpress.app/en/docs/api/puntos-de-venta.md) that issues the document. It must belong to the branch and be active. If omitted, the branch's default (`P001`) is used. |
| `cost_center_id` | uuid | No | Sale's [cost center](https://docs.filexpress.app/en/docs/api/contabilidad/centros-de-costo.md) (leaf and active center). Used on the income lines when posting. |
| `cost_center_distribution_id` | uuid | No | Active [distribution](https://docs.filexpress.app/en/docs/api/contabilidad/centros-de-costo.md#distributions) of the sale: the income is split among its centers by percentage. Mutually exclusive with `cost_center_id` at the same level. |
| `project_id` | uuid | No | Project the sale is associated with. |
| `incoterm_id` | uuid | No | Incoterm (exports). See `GET /incoterms`. |
| `related_documents` | array | No | Related documents (credit/debit notes). |

### `payment_details[]`

| Field | Type | Description |
| - | - | - |
| `code` | string | Payment method code (`GET /payment-methods`). Defaults to `01` (cash). |
| `payment_method` | string | Payment method name. |
| `amount` | number | Amount paid with this method. |
| `reference` | string | Reference (check number, card authorization, etc.). |

### `products[]`

| Field | Type | Description |
| - | - | - |
| `id` | uuid | Product ID in FileXpress (recommended for deducting inventory). |
| `sku` | string | Product code. |
| `name` | string | Description as it appears on the document. |
| `quantity` | number | Quantity. |
| `price_before_taxes` | number | Unit price before taxes. |
| `sale_not_suject` | number | Line's non-subject amount. |
| `sale_exent` | number | Line's exempt amount. |
| `sale_taxed` | number | Line's taxable amount. |
| `subtotal` | number | Line total before taxes. |
| `discount` | number | Line discount (amount). |
| `type` | string | `phisical` (goods) or `service` (service). |
| `cost_center_id` | uuid | Optional. Line's cost center; if not sent, the sale's is used. |
| `cost_center_distribution_id` | uuid | Optional. Line's [distribution](https://docs.filexpress.app/en/docs/api/contabilidad/centros-de-costo.md#distributions). Mutually exclusive with `cost_center_id` at the same level. If the line has neither center nor distribution, the sale's is used. |

**Point of sale and control number**

* Each point of sale keeps its own numbering. In El Salvador the control number is built from the branch's establishment code and the point of sale's code: `DTE-01-M001P002-000000000000001`. In other countries the format is defined by each country's tax authority.
* Priority: if the sale belongs to a cash shift, the shift's point of sale is used; otherwise, the `point_of_sale_id` sent; otherwise, the default.
* A point of sale from another branch or an inactive one responds `422` (`point_of_sale_id`: `El punto de venta no pertenece a la sucursal o está inactivo.`) and the sale is not transmitted.

**Cost center**

* A line's effective center is the line's own or, if it has none, the sale's.
* Centers are validated **before** issuing the document: a nonexistent, inactive or sub-center-bearing center responds `422` (`Centro de costo inválido`, with details in `errors`) and the sale is not transmitted.
* When posting, the center only reaches the income lines (income statement accounts); receivables, cash and VAT (IVA) lines have no center. If the lines have different centers, the income is split in proportion to each line's amount.

### `totals`

| Field | Description |
| - | - |
| `netTotals` | Sum of subtotals before taxes. |
| `saleTotalNotSuject` | Total non-subject. |
| `saleTotalExent` | Total exempt. |
| `saleTotalTax` | Total taxable (tax base). |
| `totalTax` | Total VAT. |
| `totalRetein` | Withheld VAT (0 if not applicable). |
| `totalRent` | Withheld income tax (0 if not applicable). |
| `freight` | Freight (export). |
| `insurance` | Insurance (export). |
| `saleTotalToPayment` | Total to pay. |

### `200` response

```json theme={null}
{
  "status": true,
  "message": "Invoice created successfully",
  "data": {
    "sale_id": "uuid",
    "generation_code": "6F1E2D3C-...",
    "control_number": "DTE-01-M001P001-000000000000001",
    "status": "PROCESADO",
    "issue_time": "2026-10-01 10:30:00",
    "stamp": "2026A1B2...",
    "point_of_sale_id": "uuid",
    "establishment_code": "M001",
    "point_of_sale_code": "P001",
    "total": 22.60
  }
}
```

`establishment_code` and `point_of_sale_code` are the codes with which the document was issued. They do not change even if the point of sale is later renamed or the branch is edited.

If issuance fails (for example, a rejection from the Ministry of Finance (Hacienda)), the issuance process error is returned with its HTTP code and the `message` field.

## Get sale

```http theme={null}
GET /sales/{sale_id}
```

```json theme={null}
{
  "status": true,
  "data": {
    "sale_id": "uuid",
    "generation_code": "6F1E2D3C-...",
    "control_number": "DTE-01-M001P001-000000000000001",
    "document_type": "fc",
    "status": "PROCESADO",
    "issue_time": "2026-10-01 10:30:00",
    "stamp": "2026A1B2...",
    "payment_status": "payed",
    "is_credit": false,
    "customer": { "id": "uuid", "legal_name": "Razón Social S.A. de C.V.", "customer_name": "Nombre Comercial" },
    "totals": { "sale_total": 22.60, "sale_to_payment": 22.60 },
    "products": [
      { "name": "Producto A", "quantity": 2, "individual_price": 10.00, "subtotal": 20.00 }
    ]
  }
}
```

## List sales

List of a branch's documents within a date range, designed for reconciling with an ERP.

```http theme={null}
GET /sales?branch_id={branch_id}&start_date=2026-10-01&end_date=2026-10-06
```

| Parameter | Type | Required | Description |
| - | - | - | - |
| `branch_id` | string | Yes | Branch. |
| `start_date` | date | Yes | Issue date from (`YYYY-MM-DD`). |
| `end_date` | date | Yes | Issue date to; not earlier than `start_date`. Maximum range: 93 days. |
| `document_type` | string | No | Document type (for example `fc`, `ccf`). |
| `status` | string | No | Document status. |
| `payment_status` | string | No | `pending`, `partial` or `payed`. |
| `customer_id` | string | No | Customer. |
| `per_page` | integer | No | 1 to 500. Defaults to 100. |
| `page` | integer | No | Page. |

```bash theme={null}
curl "https://api.filexpress.app/api/external/v1/sales?branch_id=9d1c5a3e-...&start_date=2026-10-01&end_date=2026-10-06&payment_status=pending"   -H "X-API-Key: fx_xxxxxxxx"
```

```json theme={null}
{
  "status": true,
  "data": {
    "data": [
      {
        "sale_id": "9a10...",
        "generation_code": "6F1E2D3C-...",
        "control_number": "DTE-03-M001P001-000000000000123",
        "document_type": "ccf",
        "status": "PROCESADO",
        "issue_time": "2026-10-05T10:30:00-06:00",
        "payment_status": "pending",
        "is_credit": true,
        "nullified": false,
        "customer": { "id": "9c77...", "name": "Grupo Alfa, S.A. de C.V." },
        "totals": { "sale_total": 1130.0, "sale_to_payment": 1130.0 }
      }
    ],
    "pagination": { "current_page": 1, "last_page": 3, "per_page": 100, "total": 248 }
  }
}
```

| Field | Description |
| - | - |
| `customer` | Legal name or, if it has none, trade name. `null` if the sale has no customer. |
| `nullified` | `true` if the document was invalidated. |

* It only includes sales from the business's environment (test or production), sorted from most recent to oldest.
* It does not include the DTE JSON or the lines: for details use [Get sale](#get-sale).

**Errors**

| Code | Cause |
| - | - |
| `404` | `Branch not found` (nonexistent or belonging to another business). |
| `422` | Validation (`Validation errors` with `errors`) / `The date range cannot exceed 93 days.` |


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