Issuing invoices over the API

POST /invoices with an Idempotency-Key, VAT as percents, plus listing, storno and marking paid.

POST /invoices with an Idempotency-Key, VAT as percents, plus listing, storno and marking paid.

← Back to the API documentation

Your first invoice in 6 steps

  1. Send POST /v1/invoices with a buyer object and at least one entry in lines.
  2. Add the Idempotency-Key header — it is required, one key per logical operation.
  3. Send vat_rate as a percent (21) and unit_price as the NET unit price.
  4. The 201 response carries id, number, series, totals net/vat/gross and the metadata you sent.
  5. Fetch the document with GET /v1/invoices/{id}/pdf or the UBL XML with GET /v1/invoices/{id}/xml.

Every endpoint

MethodEndpointScopeIdempotency-KeyRequests / minute
POST/invoices
Issue an invoice or proforma
invoices:writerequired30
GET/invoices
List invoices (cursor-paginated)
invoices:read—120
POST/invoices/preview-totals
Compute totals without creating anything
invoices:read—120
GET/invoices/{invoice_id}
Retrieve one invoice
invoices:read—120
GET/invoices/{invoice_id}/pdf
Download the invoice PDF
invoices:read—120
POST/invoices/{invoice_id}/storno
Issue a credit note reversing this invoice
invoices:writerequired30
POST/invoices/{invoice_id}/payments
Mark the invoice as paid
invoices:write—30
DELETE/invoices/{invoice_id}/payments
Mark the invoice as unpaid
invoices:write—30

What the 4invoices API is

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
# Cursor pagination: follow next_cursor until has_more is 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'

# The credit note gets its OWN fiscal number; the original number is never reused.
bash
# Mark paid
curl -sS -X POST https://api.4invoices.net/v1/invoices/inv_01J7ABC/payments \
  -H "Authorization: Bearer $ACCESS_TOKEN"

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

Errors

StatusTypeCode
422invalid_request_errorissuer_profile_incomplete
422invalid_request_errorcannot_storno_draft
422invalid_request_errornothing_to_storno

Common mistakes

  • Listing is cursor-based: follow next_cursor until has_more is false. Filters include status, document_kind, buyer_tax_id, issued_from, issued_to and q.
  • A storno is POST /v1/invoices/{id}/storno and gets its own fiscal number — the original number is never reused.
  • A proforma (document_kind proforma) consumes no fiscal number and cannot be filed in the national e-invoicing system.
  • metadata is echoed back on reads: put your order id there and you no longer need a separate mapping table.
  • POST /v1/invoices/preview-totals runs the same arithmetic with no side effects — handy for showing totals in your own cart.

Developer questions and answers

How many lines can one invoice have?

Between 1 and 400. description is capped at 1024 characters, and quantity must be strictly positive.

What happens if I resend the same request after a timeout?

With the same Idempotency-Key you get the original invoice plus an Idempotency-Replayed: true header. No second document is issued.

How do I mark an invoice as paid?

POST /v1/invoices/{id}/payments marks it paid and DELETE on the same path undoes it. Both need the invoices:write scope.