Deze referentie is alleen in het Engels. Naar het Nederlandse REST API-overzicht

Diese Referenz gibt es nur auf Englisch. Zur deutschen REST-API-Übersicht

Cette référence existe uniquement en anglais. Aller à la présentation de l'API REST en français

Esta referencia solo está en inglés. Ir a la introducción de la API REST en español

POST/invoices

Create an invoice

POSThttps://<your-url>/api/v2/invoices

MCP id invoices.storeAlso on this path: GET List invoices

View as Markdown openapi.json

Creates a legacy invoice against one project and returns it in the detail view with a Location header.

Access

Token scope
api:write:invoices

Without it: 403 insufficient-token-scope.

Permission
invoices::create

Without it: 403 insufficient-permission.

Feature
Needs the billing feature on your organisation.

Without it: 404 endpoint-not-found.

Rate cost
1 unit, write bucket. A write costs the same whatever view you ask for.
Also
Accepts Idempotency-Key. Never cached: private, no-store. Unknown body keys are refused, never dropped.

Both are checked, scope first. A token never does more than its user. How access is checked

All four body fields are required: none has a default. The invoice is attributed to the authenticated user; user_id is not writable and there is no on-behalf-of field, so an API-created invoice reads differently from the historical invoices, which carry the project manager instead. project_id is validated across into the projects prefix, so creating an invoice additionally requires the projects::read permission and a token scope covering the projects prefix; without either, project_id is refused as if it did not exist. Creating one bumps the project's updated_at and lands in the project's activity timeline. It has no line items and no way to add them (invoice rows are not part of this API), so the project's billed figure is unaffected.

Query parameters

Unknown parameters are refused with 400, naming the parameter.

viewstring

Which field set to render.

summarydetaildefault

Request headers

X-Request-Idstringpattern

A correlation id of your own. It is recorded in our logs next to the server's request id but never returned: the response header always carries the server's id. A value that does not match the pattern is discarded silently, never rejected.

Idempotency-Keystring≤ 255

A caller-chosen key that makes this POST safe to retry. Replaying it returns the original response with Idempotency-Replayed: true.

Request body

Unknown keys are refused with 422, naming the key.

project_idinteger → Project.idRequired

Project this invoice was raised for.

descriptionstringRequired

What was invoiced, as free text. This is the field ?q= searches.

datedate (YYYY-MM-DD)Required

Invoice date, a zone-free calendar date. Newest first is the default sort.

hourly_ratedecimal (2 dp)0 to 999999.99Required

Hourly rate this invoice was billed at, as a decimal string with two places. Never rounded or rescaled.

2 decimal places, not negative

At least 0. At most 999999.99.

Response 201

Returns a Invoice in the detail view.

Headers

ETag
A strong validator of exactly this representation.
Idempotency-Replayed
true when this response was replayed from a stored Idempotency-Key rather than produced by a new write.
Location
The absolute URL of the created or queued resource.
RateLimit
The IETF httpapi-ratelimit-headers form of your remaining allowance on the tightest bucket this request touched.
RateLimit-Policy
The ceiling and window of that bucket, as <limit>;w=<seconds>.
X-Request-Id
The server-generated ULID correlating this response with our logs.

Every response also carries Cache-Control, Vary, X-Content-Type-Options, X-Plnnrly-Api-Version, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset. Headers and versioning

Errors

7 errors every operation can return: 400, 401, 404, 406, 429, 500, 503

This path allows GET, POST. Anything else answers 405.