Skip to main content
POST
/
invoices
Create an invoice
curl --request POST \
  --url https://api.openfiskal.com/v1/invoices \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "organization_id": "<string>",
  "jurisdiction": "<string>",
  "document_type": "invoice",
  "seller": {
    "legal_name": "Acme S.r.l.",
    "tax_id": "IT12345678901",
    "tax_id_type": "partita_iva",
    "address": {
      "line1": "Friedrichstraße 42",
      "line2": "<string>",
      "city": "Berlin",
      "state": "<string>",
      "postal_code": "10117",
      "country": "DE"
    },
    "sdi_code": "ABC1234",
    "pec_address": "recipient@pec.example.it"
  },
  "buyer": {
    "legal_name": "Acme S.r.l.",
    "tax_id": "IT12345678901",
    "tax_id_type": "partita_iva",
    "address": {
      "line1": "Friedrichstraße 42",
      "line2": "<string>",
      "city": "Berlin",
      "state": "<string>",
      "postal_code": "10117",
      "country": "DE"
    },
    "sdi_code": "ABC1234",
    "pec_address": "recipient@pec.example.it"
  },
  "line_items": [
    {
      "description": "Software development services — March 2026",
      "quantity": 8,
      "unit_price_net": 15000,
      "tax": {
        "rate": "0.19",
        "category": "standard",
        "included_in_price": true
      },
      "unit": "hours",
      "discount": {
        "source": "manual",
        "type": "percentage",
        "label": "Happy Hour",
        "rate": "0.10",
        "amount": 200
      },
      "product_ref": "<string>",
      "nature_code": "N4"
    }
  ],
  "object": "<string>",
  "submit": true,
  "series": "A",
  "issue_date": "2023-12-25",
  "payment_terms": {
    "method": "already_paid",
    "due_date": "2023-12-25",
    "iban": "IT60X0542811101000000123456",
    "installments": [
      {
        "due_date": "2023-12-25",
        "amount": 123
      }
    ]
  },
  "routing": {
    "codice_destinatario": "ABC1234",
    "pec_address": "jsmith@example.com"
  },
  "notes": [
    "<string>"
  ],
  "references": {
    "operation_id": "<string>",
    "original_invoice_id": "<string>",
    "delivery_date": "2023-12-25",
    "purchase_order_ref": "<string>",
    "contract_ref": "<string>"
  },
  "metadata": {}
}
'
{
  "organization_id": "<string>",
  "jurisdiction": "<string>",
  "document_type": "invoice",
  "seller": {
    "legal_name": "Acme S.r.l.",
    "tax_id": "IT12345678901",
    "tax_id_type": "partita_iva",
    "address": {
      "line1": "Friedrichstraße 42",
      "line2": "<string>",
      "city": "Berlin",
      "state": "<string>",
      "postal_code": "10117",
      "country": "DE"
    },
    "sdi_code": "ABC1234",
    "pec_address": "recipient@pec.example.it"
  },
  "buyer": {
    "legal_name": "Acme S.r.l.",
    "tax_id": "IT12345678901",
    "tax_id_type": "partita_iva",
    "address": {
      "line1": "Friedrichstraße 42",
      "line2": "<string>",
      "city": "Berlin",
      "state": "<string>",
      "postal_code": "10117",
      "country": "DE"
    },
    "sdi_code": "ABC1234",
    "pec_address": "recipient@pec.example.it"
  },
  "line_items": [
    {
      "description": "Software development services — March 2026",
      "quantity": 8,
      "unit_price_net": 15000,
      "tax": {
        "rate": "0.19",
        "category": "standard",
        "included_in_price": true
      },
      "unit": "hours",
      "discount": {
        "source": "manual",
        "type": "percentage",
        "label": "Happy Hour",
        "rate": "0.10",
        "amount": 200
      },
      "product_ref": "<string>",
      "nature_code": "N4",
      "line_total_net": 123,
      "line_total_tax": 123,
      "line_total_gross": 123
    }
  ],
  "object": "<string>",
  "submit": true,
  "series": "A",
  "issue_date": "2023-12-25",
  "payment_terms": {
    "method": "already_paid",
    "due_date": "2023-12-25",
    "iban": "IT60X0542811101000000123456",
    "installments": [
      {
        "due_date": "2023-12-25",
        "amount": 123
      }
    ]
  },
  "routing": {
    "codice_destinatario": "ABC1234",
    "pec_address": "jsmith@example.com"
  },
  "notes": [
    "<string>"
  ],
  "references": {
    "operation_id": "<string>",
    "original_invoice_id": "<string>",
    "delivery_date": "2023-12-25",
    "purchase_order_ref": "<string>",
    "contract_ref": "<string>"
  },
  "metadata": {},
  "id": "inv_01HXYZ",
  "state": "draft",
  "invoice_number": "A/2026/00042",
  "totals": {
    "subtotal_gross": 123,
    "total_line_discounts": 123,
    "subtotal_after_line_discounts": 123,
    "total_cart_discounts": 123,
    "subtotal_after_all_discounts": 123,
    "rounding_adjustment": 123,
    "total_gross": 123,
    "total_net": 123,
    "total_tax": 123,
    "tax_breakdown": [
      {
        "rate": "<string>",
        "category": "<string>",
        "taxable_amount": 123,
        "tax_amount": 123,
        "total_gross": 123
      }
    ],
    "net_payable": 123
  },
  "fiscal": {
    "jurisdiction": "IT",
    "transmission_status": "pending",
    "delivery_status": "pending",
    "authority_identifier": "TBAI-12345678A-261226-jBsGMnPmXM-3",
    "chain_hash": "aSDinaTvuI8gbWludGxpZnk=",
    "transmitted_at": "2023-11-07T05:31:56Z",
    "delivered_at": "2023-11-07T05:31:56Z",
    "verification": {
      "url": "https://ticketbai.gipuzkoa.eus/tbai/qr?id=TBAI-...",
      "qr_data": "<string>"
    },
    "jurisdiction_data": {},
    "fiscal_errors": [
      {
        "code": "00159",
        "message": "Codice fiscale acquirente non valido"
      }
    ]
  },
  "created_at": "2023-11-07T05:31:56Z",
  "submitted_at": "2023-11-07T05:31:56Z",
  "cancelled_at": "2023-11-07T05:31:56Z"
}

Authorizations

Authorization
string
header
required

Platform API key sent as Authorization: Bearer ofk_platform_.... Platform integrators also pass OpenFiskal-Organization: org_xxx to act on behalf of a merchant.

Headers

OpenFiskal-Organization
string

Merchant organization ID. Required for platform integrators acting on behalf of a specific merchant. Omit when using an organization-scoped API key directly.

Idempotency-Key
string<uuid>

Unique key to make the request idempotent. If a request with this key was already processed, the original response is returned without re-executing the operation. Strongly recommended on all start and complete actions — these are fiscal events and must not be duplicated.

Body

application/json
organization_id
string
required

The merchant issuing the invoice

jurisdiction
string
required

ISO 3166-1 alpha-2 or ISO 3166-2 subdivision code for the fiscal jurisdiction. Use subdivision codes for sub-national systems.

Examples:

"IT"

"ES-PV-VI"

"ES-PV-SS"

"ES-PV-BI"

"ES"

document_type
enum<string>
required

OpenFiskal document type, mapped to jurisdiction-specific codes at submission time. See the E-Invoicing tag description for the full mapping table.

Available options:
invoice,
simplified_invoice,
credit_note,
debit_note,
deferred_invoice,
self_invoice
seller
object
required

Usually derived from the organization's registered details. Pass explicitly to override (e.g. for multi-brand setups).

buyer
object
required

Buyer details. All fields mandatory for B2B invoicing. For B2C simplified invoices, tax_id may be omitted.

line_items
object[]
required
Minimum array length: 1
object
string
Allowed value: "invoice"
submit
boolean
default:true

If false, the invoice is created in draft status and not submitted to the authority. Call POST /invoices/:id/submit when ready. Useful for Italy's deferred invoicing window.

series
string | null

Invoice series identifier. Used to maintain separate sequential numbering for different document types or business units. If omitted, OpenFiskal assigns the default series for the jurisdiction and document type.

Example:

"A"

issue_date
string<date>

Invoice issue date. Defaults to today. For deferred invoices (Italy TD24), this is the invoice date — the delivery date is in references.delivery_date.

payment_terms
object

Payment terms block. Required by FatturaPA even for already-paid invoices — use method: already_paid in that case.

routing
object

Italy only. How SDI should route the invoice to the recipient. If omitted, SDI will attempt delivery via the recipient's registered codice destinatario.

notes
string[]

Free-text notes (Causale in FatturaPA). Appear on the human-readable document. Max 200 characters per entry.

references
object

Links to related resources

metadata
object

Response

Invoice created (and submitted unless submit: false)

organization_id
string
required

The merchant issuing the invoice

jurisdiction
string
required

ISO 3166-1 alpha-2 or ISO 3166-2 subdivision code for the fiscal jurisdiction. Use subdivision codes for sub-national systems.

Examples:

"IT"

"ES-PV-VI"

"ES-PV-SS"

"ES-PV-BI"

"ES"

document_type
enum<string>
required

OpenFiskal document type, mapped to jurisdiction-specific codes at submission time. See the E-Invoicing tag description for the full mapping table.

Available options:
invoice,
simplified_invoice,
credit_note,
debit_note,
deferred_invoice,
self_invoice
seller
object
required

Usually derived from the organization's registered details. Pass explicitly to override (e.g. for multi-brand setups).

buyer
object
required

Buyer details. All fields mandatory for B2B invoicing. For B2C simplified invoices, tax_id may be omitted.

line_items
object[]
required
Minimum array length: 1
object
string
Allowed value: "invoice"
submit
boolean
default:true

If false, the invoice is created in draft status and not submitted to the authority. Call POST /invoices/:id/submit when ready. Useful for Italy's deferred invoicing window.

series
string | null

Invoice series identifier. Used to maintain separate sequential numbering for different document types or business units. If omitted, OpenFiskal assigns the default series for the jurisdiction and document type.

Example:

"A"

issue_date
string<date>

Invoice issue date. Defaults to today. For deferred invoices (Italy TD24), this is the invoice date — the delivery date is in references.delivery_date.

payment_terms
object

Payment terms block. Required by FatturaPA even for already-paid invoices — use method: already_paid in that case.

routing
object

Italy only. How SDI should route the invoice to the recipient. If omitted, SDI will attempt delivery via the recipient's registered codice destinatario.

notes
string[]

Free-text notes (Causale in FatturaPA). Appear on the human-readable document. Max 200 characters per entry.

references
object

Links to related resources

metadata
object
id
string
Example:

"inv_01HXYZ"

state
enum<string>
  • draft: Created but not yet submitted to the authority.
  • submitted: Submitted to the authority, awaiting acknowledgment.
  • transmitted: Authority confirmed receipt. For TicketBAI/Verifactu, this is the terminal success state. For SDI, delivery to recipient still pending.
  • delivered: SDI only. Invoice delivered to the recipient's inbox. Recipient has 15 days to accept or reject.
  • accepted: SDI only. Recipient explicitly accepted the invoice. Implicit acceptance occurs after 15 days with no rejection.
  • undeliverable: SDI only. SDI could not deliver to the recipient (invalid codice_destinatario or PEC address). Invoice is fiscally valid but the vendor must contact the recipient directly.
  • rejected_by_authority: Authority rejected the document due to format or validation errors. Check fiscal_errors. Must correct and resubmit as a new invoice.
  • cancellation_requested: Full cancellation initiated, awaiting authority acknowledgment.
  • cancelled: Invoice fully cancelled. A corrective document has been issued and accepted.
Available options:
draft,
submitted,
transmitted,
delivered,
accepted,
undeliverable,
rejected_by_authority,
cancellation_requested,
cancelled
invoice_number
string | null

Sequential invoice number assigned by OpenFiskal on submission. Format: <series>/<year>/<sequence> or jurisdiction-specific.

Example:

"A/2026/00042"

totals
object

Order-level totals, derived from line items. All fields are positive integers in minor currency units. net_payable is the only field that can be negative (on refunds).

Derivation: subtotal_gross − total_line_discounts = subtotal_after_line_discounts subtotal_after_line_discounts − total_cart_discounts = subtotal_after_all_discounts subtotal_after_all_discounts + rounding_adjustment = total_gross total_gross → total_net + total_tax

fiscal
object

Authority-specific output populated after submission. Treat jurisdiction_data as opaque — store it, do not parse it.

created_at
string<date-time>
submitted_at
string<date-time> | null
cancelled_at
string<date-time> | null