Book draft invoice
/v1/invoices/{id}/bookBooks a draft invoice to the ledger and assigns its number. Each call is your own approval of the invoice: Numina does not review it, so make sure a person at your company has checked it or has approved the rules your system books by. Booking is final and cannot be undone through this API. It does not send the invoice; use POST /v1/invoices/{id}/send.
Not available to Fuld Service customers (403 booking_not_available), whose books Numina's bookkeepers keep.
Returns 400 validation_error for a date in a closed accounting year or before the first accounting date, VAT on a company that is not VAT registered, an e-invoice that cannot be sent, or an invoice that is not complete. Returns 400 payment_details_required for an invoice with no payment details when the company has no default bank account to fill them from (see is_invoice_default on GET /v1/bank-accounts); create the invoice again with bank_account_id. A foreign-currency invoice uses the latest exchange rate Numina has on or before its issue date; see currency_rate on POST /v1/invoices.
Safe to retry: booking an invoice that is already booked returns it unchanged with 200. Credit notes and offers cannot be booked here and return 409.
Requires one ofinvoices:bookwrite:ledger
Path parameters
- Invoice ID
Errors
400Invalid input or validation failed401Invalid or missing authentication403Missing scope, the company is archived, or the company is on Fuld Service404The resource does not exist in this company409This is a credit note or offer, or the invoice is being updated429Rate limit exceeded500Internal Server Error
Every error has the same shape. See Errors.
curl -X POST https://api.numina.app/v1/invoices/550e8400-e29b-41d4-a716-446655440000/book \
-H "Authorization: Bearer numi_YOUR_API_KEY"const response = await fetch("https://api.numina.app/v1/invoices/550e8400-e29b-41d4-a716-446655440000/book", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.NUMINA_API_KEY}`,
},
});
const data = await response.json();import os
import requests
response = requests.post(
"https://api.numina.app/v1/invoices/550e8400-e29b-41d4-a716-446655440000/book",
headers={
"Authorization": f"Bearer {os.environ['NUMINA_API_KEY']}",
},
)
data = response.json(){
"id": "550e8400-e29b-41d4-a716-446655440000",
"invoice_number": 1001,
"type": "invoice",
"credited_invoice_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "sent",
"issue_date": "2026-01-15",
"due_date": "2026-02-15",
"contact_id": "550e8400-e29b-41d4-a716-446655440001",
"contact_name": "Acme ApS",
"currency": "DKK",
"subtotal": 10000,
"vat": 2500,
"vat_rate": 25,
"total": 12500,
"has_mixed_vat": false,
"outstanding_balance": 12500,
"outstanding_balance_currency": "DKK",
"currency_rate": 0,
"delivery_status": "sent",
"email_delivery_status": "string",
"email_sent_at": "string",
"e_invoice_sent_at": "string",
"is_overdue": false,
"payment_state": "open",
"unmatched_payments_note": "string",
"items": [
{
"unit": "string",
"vat_account_id": "string",
"vat_code": "string",
"sales_account_number": 0,
"vat_rate": 0,
"id": "550e8400-e29b-41d4-a716-446655440002",
"description": "Consulting services",
"quantity": 10,
"unit_price": 1000
}
],
"memo": "Project Q1 delivery",
"payment_details": {
"bank_name": "Danske Bank",
"scheme": "dk-registration-number",
"clearing_code": "3409",
"account_number": "0012345678",
"iban": "DK5030000012345678",
"swift_bic": "DABADKKK"
},
"created_at": "2026-01-15T10:30:00Z"
}