Trigger an invoice lifecycle transition
PATCH/api/v1/invoices/:id/transition
Trigger a lifecycle state transition for an invoice.
The event is one of the AASM events exposed in the invoice's
lifecycle_available_transitions. Available transitions depend on the
current lifecycle state:
- draft →
deposit - deposited →
receive,reject,cancel - received →
make_available,cancel - available →
take_in_charge,approve,dispute,refuse,send_payment,cancel - taken_in_charge →
approve,dispute,refuse,send_payment,cancel - disputed →
approve,refuse,cancel - approved →
send_payment - payment_sent →
collect
For a purchase invoice under the approval workflow, send_payment is only
offered from approved.
Request
Responses
- 200
- 401
- 403
- 404
- 422
The invoice after the transition, reflecting its new lifecycle_state.
The request carries no OAuth bearer token, or the token is invalid or expired.
The access token lacks the write scope required to trigger a lifecycle transition.
No invoice exists with the given ID, or the invoice belongs to a workspace the token's application cannot access - both cases return this same response so cross-workspace existence is never revealed.
The requested event is not a valid transition from the invoice's current lifecycle state, is missing or unrecognized, or - for a CDV-reporting status such as dispute - omits the required normalized reason_code, or - for a refusal (status 210, refuse) - omits the free-text reason that must motivate it, which the reason_code does not replace, or sends a requested_action_code or requested_action with an event other than dispute (status 207), or a requested_action_code outside the BR-FR-CDV-CL-10 list. The error body reports error: "unprocessable_entity" with a message describing the specific failure. details is field-keyed whenever the refusing guard names the attributes to fix - the deposit guard lists the missing mandatory legal mentions there - and an empty object when the refusal is about the invoice as a whole. A deposit refused by the Schematron gate names its cause in code: schematron_engine_unavailable (the engine owed a verdict and could not produce one - transient, retry, nothing is wrong with the invoice) and schematron_profile_unsupported (the reform admits no rule set for this profile - deterministic, send a different one) use this same envelope, while schematron_fatal uses a distinct body carrying only a field-keyed errors object and code, with no error, message or details. A deposit of an invoice billed in a currency other than EUR is refused with code: "operation_failed" and an empty details when no exchange rate is available for its issue_date: the VAT total must be carried in EUR beside the invoice currency, which requires a published rate, so the invoice stays a draft - retry once the rates have been synchronised. A deposit is also refused, ahead of the Schematron gate, when a party states no country: details is keyed on seller.address.country_code or buyer.address.country_code. Scribee no longer substitutes FR for a country nobody declared, so a party's country_code can read null in a response and BT-40 / BT-55 must be filled in before the deposit. Only the flux 1 obligation carries that presence rule; a sale whose buyer owes an e-reporting declaration (flux 10) is not refused for it.