Issue purchase invoice
POST /api/v1/facturas-compra
Issues an electronic purchase invoice (type 08), also called a self-invoice (autofactura): the document that the law requires the buyer to issue when purchasing from a supplier under a special regime — farmers, artisanal fishers, informal collectors, and other regimes that Hacienda (Costa Rica’s tax authority) does not require to issue their own FE.
It is the only document in the API that doesn’t record a sale by the tenant. The tenant is the one issuing it, but the emisor object sent in the body identifies the supplier, not a recipient of the tenant.
In terms of asynchrony it works the same as POST /facturas: the response is immediate with status procesando, and the final status arrives via webhook or by polling GET /facturas-compra/{clave}.
Authentication and permissions
| Attribute | Value |
|---|---|
| Scheme | API key (X-Api-Key) |
| Required scope | facturas-compra:write |
| Idempotent | Yes (with the Idempotency-Key header) |
| Rate limit | 120 req/min per API key |
Headers
POST /api/v1/facturas-compra HTTP/1.1
Host: api.pos.lxsyscr.com
X-Api-Key: lxs_live_a1b2c3d4_001122...
Content-Type: application/json
Idempotency-Key: 9c2a1234-5678-4b5e-9c2a-4f1c8a8a2c4f
Accept: application/jsonRequest body
See FacturaCompraApiRequestDto for the complete schema.
Example — existing supplier, line from the purchase catalog:
{
"idUsuario": 7,
"emisor": { "idEmisor": 15 },
"condicionVenta": "01",
"medioPago": "01",
"moneda": "CRC",
"lineas": [
{ "idProducto": 8, "cantidad": 100 }
]
}Example — new supplier (registered on the fly) and an ad-hoc line:
{
"idUsuario": 7,
"emisor": {
"identificacion": "1-0234-0567",
"tipoIdentificacion": "01",
"nombre": "Juan",
"apellidos": "Pérez Solano",
"correo": "juan.perez@correo.cr",
"telefono": "88001122",
"codigoActividadEmisor": "011101"
},
"condicionVenta": "01",
"medioPago": "01",
"moneda": "CRC",
"comentario": "Compra de café en fruta — cosecha agosto",
"lineas": [
{
"descripcion": "Café en fruta",
"codigoCabys": "8511200000100",
"unidadMedida": "Kg",
"cantidad": 250,
"precioUnitario": 450.00
}
]
}Responses
201 Created
HTTP/1.1 201 Created
Location: /api/v1/facturas-compra/50615012600310112345600100001080000000123456789012
Content-Type: application/json{
"clave": "50615012600310112345600100001080000000123456789012",
"numeroConsecutivo": "00100001080000000123",
"tipoDocumento": "08",
"estadoHacienda": "procesando",
"totalComprobante": 112500.00,
"moneda": "CRC",
"fechaEmision": "2026-08-05T14:10:00Z"
}Same shape as FacturaApiResponseDto — there is no separate response DTO for purchases.
400 Bad Request
{ "error": "Debe incluir al menos una línea." }{ "error": "Debe indicar idEmisor o identificacion del proveedor." }{ "error": "tipoIdentificacion y nombre son obligatorios para dar de alta al proveedor." }{ "error": "descripcion y codigoCabys son obligatorios para dar de alta la línea." }{ "error": "El teléfono del proveedor no tiene un formato válido." }401 Unauthorized / 403 Forbidden
Same behavior as POST /facturas, with the facturas-compra:write scope.
{ "error": "La API key no tiene el scope requerido para esta operación." }409 Conflict / 413 Payload Too Large / 429 Too Many Requests / 500 Internal Server Error
Identical to those of POST /facturas.
Business rules
- 0% exempt tax rate. The purchase invoice carries no VAT, discounts, tax exemptions, or other charges — those fields must not be sent and are ignored if included.
totalComprobanteis the simple sum ofcantidad × precioUnitariofor each line. - The line catalog is its own, separate catalog.
lineas[].idProductopoints to the purchase invoice catalog (producto_factura_compra), which is not the inventory catalog used by sales. AnidProductothat exists in Sales might not exist here, and vice versa — it should not be reused without verifying it first. If the id isn’t available, senddescripcion+codigoCabysand the line is resolved or created: seeFacturaCompraApiLineaDto. - The supplier’s phone and email are validated and normalized with the same rules as the POS. An invalid format returns
400, not a document issued with garbage data. - Hacienda validates the supplier’s ID number. If the ID number doesn’t exist in its registry, the document is still accepted by the tenant’s system (it goes
procesando→recibido), but Hacienda rejects it. If the supplier is new, verify the ID number before issuing.