Create & Book Invoice
Issuing an invoice is two stages: create it (status CREATED), then
activate it. Activation posts the invoice into the ledger and is what
“booked” means - the invoice reaches status ACTIVATED with a bookedDate.
Factoring adds a credit-decision step on top of the same path.
POST /invoices takes the structured createInvoice object (nested debtor,
dates, articleRows, currency), not a flat amount. Required right:
CreateInvoices. There is also a machine-to-machine variant,
POST /invoices/integration (permission invoice:create), for token-based
integrations.
Request payload
Section titled “Request payload”Top level
Section titled “Top level”| Field | Required | Notes |
|---|---|---|
invoiceNumber | yes | Your invoice number. |
articleRows | yes | List of line items (see below). |
debtor | yes | Nested debtor object (see below). The debtor is matched/created automatically - no separate debtor call. |
dates | yes | Nested object with invoiceDate and expireDate. |
clientId | conditional | Top-level. Required with a system token (scopes the invoice to a client). Omit it with a client token - it is taken from the token. |
currency | no | Nested object; see Currency below. Defaults to the tenant’s configured currency. |
type | no | INVOICE, CREDIT_INVOICE, etc. Defaults to a standard invoice. |
serviceProviderCode | no | Which installed service provider administers the invoice. |
productCode is not set here - it is chosen at activation (step 2).
debtor (matched by customerNumber)
Section titled “debtor (matched by customerNumber)”| Field | Required | Notes |
|---|---|---|
customerNumber | yes | Your customer number for the debtor. This is the matching key - Quiddly maps it to an existing debtor or creates one. |
name | yes | Person or company name. |
type | yes | COMPANY or PERSON. |
identificationNumber | no | Org/SSN. Recommended; improves matching and is needed for collection. |
email, phone, invoiceAddress, deliveryAddress, peppolId, … | no | Contact and routing details. |
| Field | Required |
|---|---|
invoiceDate | yes |
expireDate | yes |
deliveryDate | no |
articleRows
Section titled “articleRows”The list is required. Individual rows have no single mandatory field - send the
ones you have (description, quantity, unit, price, vatPercentage,
articleNumber, accountNumber, …). Alternatively set
articleRowsGenerate: true to let Quiddly compute the rows/totals from the
invoice data.
Currency
Section titled “Currency”Currency is set inside the nested currency object, not at the top level:
"currency": { "invoiceCurrency": "SEK", "baseCurrency": "SEK" }invoiceCurrency is what the PDF shows; baseCurrency (optional) is the
currency the invoice is handled in. If no baseCurrency is sent
Quiddly defaults to the system currency. baseCurrency will decide which client
account it will be handled in. Totals (totals) and VAT breakdown
(vats) are normally derived by Quiddly - you do not have to send them.
Status model
Section titled “Status model”The response marshals the created invoice; the main status surfaces under
statuses.main (and ledger progress under statuses.ledger).
statuses.main | When |
|---|---|
CREATED | Freshly created, not yet activated. |
PENDING_AUTHORIZATION | Held for authorization before activation (tenant-dependent). |
PENDING | Activation accepted, queued. |
ACTIVATING | Activation running (documents, ledger, financial events). |
ACTIVATED | Booked. bookedDate is set. |
DENIED_FINANCING | Factoring decision denied. |
PAUSED / DISPUTED / STOPPED / CLOSED / ARCHIVED | Later lifecycle states. |
CREATED ──activate──> PENDING ──> ACTIVATING ──> ACTIVATED (booked) │ request factoring + decision ├── approved ─> ACTIVATED (financed, product INVOICE_FACTORING_SELL) └── denied ──> DENIED_FINANCINGEnd-to-end flow
Section titled “End-to-end flow”-
Create the invoice.
Terminal window curl -X POST "https://$HOST/invoices" \-H "Authorization: Bearer $JWT" -H "Content-Type: application/json" \-d '{"clientId": "C.100100","invoiceNumber": "2026-0001","debtor": {"customerNumber": "CUST-42","name": "Acme AB","type": "COMPANY","identificationNumber": "5560000001"},"dates": { "invoiceDate": "2026-06-01", "expireDate": "2026-06-30" },"currency": { "invoiceCurrency": "SEK" },"articleRows": [{ "description": "Consulting", "quantity": "1", "unit": "h", "price": "1250.00", "vatPercentage": 25 }]}'Returns the created invoice with
statuses.main = CREATED. OmitclientIdif you authenticate with a client token. Add?returnResource=falseto get just{ "id": "I...." }back. -
Activate it. Requires
ActivateInvoices. Choose the product here -INVOICE_SERVICEfor a plain service invoice.Terminal window curl -X PUT "https://$HOST/invoices/$INVOICE_ID/activate" \-H "Authorization: Bearer $JWT" -H "Content-Type: application/json" \-d '{ "productCode": "INVOICE_SERVICE" }'The call returns quickly with
PENDING; activation finishes asynchronously (document generation, ledger and financial events) and the invoice lands onACTIVATEDwithbookedDateset. Subscribe to theINVOICE/INVOICE_BALANCEwebhooks instead of polling. -
(Factoring only) Request factoring on the activated service invoice.
Terminal window curl -X PUT "https://$HOST/factoring-decisions/$INVOICE_ID/factoring" \-H "Authorization: Bearer $JWT" -H "Content-Type: application/json" -d '{}'Requires
UpdateCreditDecisionStatus. Guards: the invoice must beACTIVATEDand productINVOICE_SERVICE, and the debtor must not be blocked for factoring. See the factoring decision flow below.
Factoring decision flow
Section titled “Factoring decision flow”The credit decision is tracked by a credit-decision status separate from
the invoice main status. Values: PENDING, READY_FOR_DECISION, WAITING,
REFINANCE, DECIDED (plus tenant-specific groupings/sub-statuses).
Quiddly distinguishes internal decisions (made inside Quiddly, by the engine rule or an operator) from external decisions (made by an external financing provider):
| Action | Endpoint | Right | Use |
|---|---|---|---|
| Request factoring | PUT /factoring-decisions/<invoiceId>/factoring | UpdateCreditDecisionStatus | Ask to factor an activated service invoice. |
| Move internal decision | PUT /factoring-decisions/<id>/move | UpdateCreditDecisionStatus | Advance the internal credit-decision status (+ optional sub-status grouping). |
| Record external decision | PUT /factoring-decisions/<id>/move-external | UpdateExternalFactoringDecision | Record an external provider’s decision: APPROVED, DENIED, or DENIED_SERVICE. |
The decision resolves to one of FinanceDecision = APPROVED, DENIED,
DENIED_SERVICE, REFINANCE:
- Approved: the product switches to
INVOICE_FACTORING_SELL, financed financial events are generated, the invoice is re-booked as financed, and the credit-decision status becomesDECIDED. The invoice staysACTIVATED. - Denied: main status becomes
DENIED_FINANCING.
Track the decision with GET /factoring-decisions/invoice/<id> and the
FACTORING_STATUS webhook.