Emitir facturas por la API

POST /invoices con Idempotency-Key, IVA en porcentaje, además de listado, rectificativa y marcar como pagada.

POST /invoices con Idempotency-Key, IVA en porcentaje, además de listado, rectificativa y marcar como pagada.

← Volver a la documentación de la API

Tu primera factura en 6 pasos

  1. Envía POST /v1/invoices con un objeto buyer y al menos una entrada en lines.
  2. Añade la cabecera Idempotency-Key: es obligatoria, una clave por operación lógica.
  3. Envía vat_rate como porcentaje (21) y unit_price como precio unitario NETO.
  4. La respuesta 201 incluye id, number, series, los totales neto/IVA/bruto y los metadata que enviaste.
  5. Descarga el documento con GET /v1/invoices/{id}/pdf o el XML UBL con GET /v1/invoices/{id}/xml.

Todos los endpoints

MétodoEndpointScopeIdempotency-KeyPeticiones / minuto
POST/invoices
Emitir una factura o proforma
invoices:writeobligatorio30
GET/invoices
Listar facturas (paginación por cursor)
invoices:read—120
POST/invoices/preview-totals
Calcular totales sin crear nada
invoices:read—120
GET/invoices/{invoice_id}
Obtener una factura
invoices:read—120
GET/invoices/{invoice_id}/pdf
Descargar el PDF de la factura
invoices:read—120
POST/invoices/{invoice_id}/storno
Emitir un abono que anula esta factura
invoices:writeobligatorio30
POST/invoices/{invoice_id}/payments
Marcar la factura como pagada
invoices:write—30
DELETE/invoices/{invoice_id}/payments
Marcar la factura como no pagada
invoices:write—30

Qué es la API de 4invoices

bash
curl -sS -X POST https://api.4invoices.net/v1/invoices \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: order-10457-invoice' \
  -d '{
    "buyer": {
      "name": "Exemplu Comert SRL",
      "tax_id": "RO12345678",
      "address": "Str. Fabricii 12",
      "city": "Cluj-Napoca",
      "county": "Cluj",
      "country": "RO",
      "email": "[email protected]"
    },
    "lines": [
      { "description": "Abonament SaaS, iulie", "quantity": 1, "unit_price": 400, "vat_rate": 21, "unit": "buc" },
      { "description": "Implementare", "quantity": 6, "unit_price": 250, "vat_rate": 21, "unit": "ora" }
    ],
    "currency": "RON",
    "document_kind": "factura",
    "due_date": "2026-08-15",
    "metadata": { "order_id": "10457" }
  }'
bash
# Paginación por cursor: sigue next_cursor hasta que has_more sea false.
curl -sS "https://api.4invoices.net/v1/invoices?limit=50&status=issued&issued_from=2026-07-01" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

# → {"object":"list","data":[...],"has_more":true,"next_cursor":"inv_01J..."}

curl -sS "https://api.4invoices.net/v1/invoices?limit=50&cursor=inv_01J..." \
  -H "Authorization: Bearer $ACCESS_TOKEN"
bash
curl -sS -X POST https://api.4invoices.net/v1/invoices/inv_01J7ABC/storno \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Idempotency-Key: storno-inv_01J7ABC-1'

# El abono recibe SU PROPIO número fiscal; el número del original nunca se reutiliza.
bash
# Marcar como pagada
curl -sS -X POST https://api.4invoices.net/v1/invoices/inv_01J7ABC/payments \
  -H "Authorization: Bearer $ACCESS_TOKEN"

# Deshacer
curl -sS -X DELETE https://api.4invoices.net/v1/invoices/inv_01J7ABC/payments \
  -H "Authorization: Bearer $ACCESS_TOKEN"

https://api.4invoices.net/v1 · https://api.4invoices.net/v1/openapi.json

Errores

EstadoTipoCódigo
422invalid_request_errorissuer_profile_incomplete
422invalid_request_errorcannot_storno_draft
422invalid_request_errornothing_to_storno

Errores frecuentes

  • El listado se pagina por cursor: sigue next_cursor hasta que has_more sea false. Los filtros incluyen status, document_kind, buyer_tax_id, issued_from, issued_to y q.
  • Una anulación (storno) es POST /v1/invoices/{id}/storno y recibe su propio número fiscal: el número original nunca se reutiliza.
  • Una proforma (document_kind proforma) no consume ningún número fiscal y no se puede presentar en el sistema nacional de facturación electrónica.
  • metadata se devuelve en las lecturas: guarda ahí el id de tu pedido y ya no necesitarás una tabla de correspondencias aparte.
  • POST /v1/invoices/preview-totals ejecuta el mismo cálculo sin efectos secundarios: práctico para mostrar los totales en tu propio carrito.

Preguntas y respuestas para desarrolladores

¿Cuántas líneas puede tener una factura?

Entre 1 y 400. description está limitado a 1024 caracteres y quantity debe ser estrictamente positivo.

¿Qué ocurre si reenvío la misma petición tras un timeout?

Con la misma Idempotency-Key recibes la factura original más una cabecera Idempotency-Replayed: true. No se emite ningún segundo documento.

¿Cómo marco una factura como pagada?

POST /v1/invoices/{id}/payments la marca como pagada y DELETE sobre la misma ruta lo deshace. Ambos requieren el scope invoices:write.