Document Life Cycle
🏗️ Under Construction
We’re actively refining our approach to Life Cycles support for the FR mandate.
This page and the related APIs may change over time, so integrations may need to be adjusted. Please check back regularly for updates.
Overview
A Document Life Cycle in Routty represents the sequence of business status updates that a document goes through after it has been issued, transmitted, received, processed, approved, disputed, refused, or paid.
Life Cycles are especially important for the French e-invoicing mandate, where invoice exchanges must not only be transmitted electronically through approved platforms, but also be tracked through a defined set of lifecycle statuses. Routty supports this by storing lifecycle events separately from the original invoice while linking them back to the document they belong to.
This allows customers and partners to:
send lifecycle updates into Routty for existing documents
retrieve lifecycle events from Routty for further processing
monitor the current lifecycle status of a document
maintain an audit trail of all lifecycle transitions
support French compliance scenarios involving 14 mandated statuses
Why this exists
Starting from 1 September 2026, France mandates electronic invoicing for B2B and B2G transactions. This requires companies to:
issue e-invoices in supported structured formats
transmit invoices through approved platforms
accept electronic invoices from suppliers
report required transaction data
track and communicate lifecycle statuses throughout the invoice journey
For Routty customers operating in France, this means lifecycle support is not optional. Lifecycle processing is required to support invoice exchange, visibility, compliance, and integration with approved platforms such as SOVOS.
Core Concepts
Document
A document is the original business document processed by Routty, such as an invoice.
Life Cycle
A Life Cycle is the business progression of a document over time, expressed through a sequence of status updates.
Life Cycle Event
A Life Cycle Event is an individual status update tied to an existing document. Each event contains at least:
a status code
a timestamp
optional descriptions or supporting details
a reference to the original document
Status vs Event
In Routty, a distinction is made between:
events: the full history of lifecycle updates received or generated
status: the current highest-priority lifecycle status shown on the document
A document may therefore have many lifecycle events, but only one current lifecycle status.
Original Document
A lifecycle document does not stand on its own. It is always linked to an existing original document in Routty.
Flow direction
Lifecycle events can move in different directions depending on the scenario:
from supplier platform to buyer side
from buyer side back to supplier side
from external connectors into Routty
from Routty outward to partners or platforms
Life Cycles in Routty
Routty treats lifecycle updates as a separate processing flow from regular business documents.
A lifecycle update is processed as its own document type, but with a simplified flow focused on:
identifying the lifecycle format
determining the company
determining the mapping configuration
transforming the input into Routty’s internal representation
identifying the business partner where needed
matching the lifecycle update to the original document
storing the lifecycle event
linking the event and attachments to the original document
Unlike normal invoice processing, lifecycle processing does not include the full document pipeline. For example, Routty does not route the lifecycle document as a regular business document, does not enrich it like a normal invoice, and does not export it as a standalone document.
Current status vs lifecycle history
Current lifecycle status
Each document exposes a single current lifecycle status, derived from the highest-priority lifecycle event.
Used for:
dashboards
filtering
quick status checks
Lifecycle history
Each document also contains a full lifecycle audit trail, including:
all lifecycle events
timestamps
comments
lifecycle attachments (e.g. CDAR files)
Used for:
compliance
debugging
detailed lifecycle visualization
Supported Statuses
Each lifecycle event is stored individually, and the current lifecycle status of a document is derived based on status priority.
⚠️ The current lifecycle status is not based on the latest timestamp, but on the highest-priority status received.
Status overview
Priority | Code | Name | Flow | Description |
|---|---|---|---|---|
1 | 200 | Submitted | Inbound | Document submitted by supplier |
2 | 201 | Issued by the platform | Inbound | Sent by supplier platform |
3 | 202 | Received on the platform | Inbound | Received by buyer platform |
4 | 203 | Made available | Inbound | Made available to buyer |
5 | 204 | Processed | Inbound | Processed by buyer system |
6 | 206 | Partially approved | Inbound | Partially accepted by buyer |
7 | 205 | Approved | Inbound | Fully approved by buyer |
8 | 211 | Payment sent | Inbound | Payment initiated by buyer |
9 | 212 | Payment received | Outbound | Payment received by supplier |
10 | 208 | Suspended | Inbound | Processing temporarily suspended |
11 | 209 | Completed | Outbound | Lifecycle completed |
12 | 207 | Disputed | Inbound | Invoice disputed |
13 | 210 | Refused | Inbound | Invoice refused |
14 | 213 | Rejected on issue | Inbound | Rejected by platform (technical rejection) |
Routty stores the complete history of received lifecycle events and derives the current document lifecycle status based on configured status priority.
Priority model
Routty uses a priority-based model to determine the current lifecycle status.
Each status has a fixed priority (1 → 14)
The highest priority status received becomes the current lifecycle status
Lower-priority statuses do not override higher-priority ones
Example
A document receives the following events:
200 Submitted201 Issued207 Disputed205 Approved
Even if 205 Approved was received later, the current status will be:
207 Disputed (higher priority)
Important considerations
Lifecycle events may arrive out of order
Multiple lifecycle events can exist for the same document
The full history is always preserved
The current status is derived, not directly stored as a single event
Processing
Determination phase
When a lifecycle update is received, Routty determines:
the input format
the company
the mapping configuration
the business partner, where applicable
the original document reference
Routty then attempts to match the lifecycle update to the original invoice.
If the original document cannot yet be matched because it is still being processed, Routty retries matching every hour for up to 3 days.
Processing phase
Once matched, Routty will:
parse the lifecycle status
create a lifecycle event record
link the lifecycle update to the original document
update the current lifecycle status on the original document
store relevant lifecycle files as attachments
Output phase
Routty generates lifecycle output artifacts for traceability and interoperability. These may include generated CDAR-based files and transformed lifecycle documents linked to the original document.
Lifecycle documents themselves are not exported as standalone regular documents.
Attachments and file handling
For traceability, Routty stores lifecycle-related files as attachments on the original document.
Typical attachment variants are:
input
transformed
enriched
output
Naming convention:
lifeCycle_{statusCode}_{fileType}.xml
Example:
lifeCycle_200_input.xml
These attachments are treated as lifecycle attachments and are available for lifecycle inspection and audit purposes.
Integrations
The main integration scenarios are:
Sending lifecycle events to Routty
Retrieving lifecycle events from Routty
This applies to external customers and partners, as well as Routty created connectors.
Sending Life Cycle Events to Routty
Routty supports two ways of sending lifecycle updates for existing documents:
Uploading a lifecycle document through the regular document upload flow
Posting a lifecycle event directly to an existing document through the API
For most simplified integrations, the default approach is to upload a lifecycle document in CDAR (XML) form through the regular document upload flow. For more complex integrations, Routty also supports direct API-based lifecycle updates.
Although these entry points differ, both result in the creation of a lifecycle event document that is processed through the same lifecycle pipeline and linked to the original document.
Option 1: Uploading a lifecycle document through the regular upload flow
This is the default approach for simpler integrations.
In this model, the sender uploads a lifecycle document in CDAR XML format through the same inbound flow used for regular document uploads. Routty then classifies the uploaded file as a lifecycle document and processes it through the dedicated lifecycle flow.
This approach is useful when the integrating party:
already produces lifecycle messages as CDAR XML
wants to reuse the standard upload mechanism
prefers a lower-complexity integration model
does not want to call lifecycle-specific endpoints directly
How it works
A lifecycle document is uploaded through the regular inbound document flow.
Routty classifies the upload as a lifecycle document.
Routty runs the lifecycle determination phase:
determine format
determine company
determine mapping configuration
transform to internal format
determine business partner where applicable
determine the original document
Routty links the lifecycle event to the original document.
Routty stores the lifecycle update, attachments, and derived current lifecycle status.
This is the most generic approach because Routty derives all required context from the uploaded lifecycle payload itself.
Option 2: Posting a lifecycle event directly to an existing document
For more advanced integrations, lifecycle updates can be posted directly to a known document in Routty.
POST /lifecycle/{doc-id}
How it works
In this model, the integrator already knows which Routty document the lifecycle update belongs to. Instead of uploading a standalone lifecycle XML file and letting Routty determine the target document, the update is submitted directly against that document.
The integrator posts a lifecycle update to a known Routty document ID.
Routty generates an internal lifecycle event document from the provided lifecycle data.
That generated lifecycle document is then processed through the same lifecycle pipeline as an uploaded CDAR document.
The lifecycle update is added to the document history, and the current lifecycle status is recalculated.
Important behavior
Although this is a direct API approach, Routty still mirrors the default upload-based approach internally. In other words, it does not bypass the lifecycle processing model itself. Instead, it creates the same kind of lifecycle event document that would have been created through the regular upload flow, so downstream processing remains consistent.
The main difference is that the determination phase can be skipped, because key information is already known at the time of the API call, such as:
the original Routty document
the company context
the relevant linkage to the existing document
This makes the direct API approach more efficient for advanced integrations, while still preserving one consistent internal lifecycle processing model.
Why both approaches exist
These two approaches serve different integration needs:
Regular upload of CDAR XML is best for simplified or loosely coupled integrations that want to reuse Routty’s normal upload behavior.
Direct API upload to the original document is best for tighter integrations that already know the original document ID and want to avoid unnecessary determination steps.
In both cases, Routty standardizes the lifecycle update into the same internal structure so that:
lifecycle tracking remains consistent
attachments are handled the same way
UI history and timeline behavior stay identical
downstream integrations do not need separate handling logic
Retrieving lifecycle updates from Routty
Routty provides a pull-based API for retrieving lifecycle information for existing documents.
Lifecycle data can be retrieved as:
full lifecycle history per document
lists of documents with lifecycle updates
incremental updates based on timestamp filtering
Retrieve lifecycle history for a document
GET /lifecycle/{doc-id}
Returns all lifecycle events associated with a specific document.
Response includes
lifecycle status codes
timestamps
optional descriptions
full lifecycle history
Typical use cases
displaying lifecycle timelines in external systems
synchronizing document status with ERP systems
auditing lifecycle transitions
Retrieve documents with lifecycle updates
GET /lifecycle/{flow}
Returns document IDs for which lifecycle updates are available for a given flow.
Typical use cases
polling for new lifecycle updates
batch processing of updates
identifying documents that require synchronization
Incremental retrieval (recommended)
To efficiently process lifecycle updates, integrations should use timestamp-based filtering.
This allows:
retrieving only new or updated lifecycle events
avoiding duplicate processing
implementing checkpoint-based polling
Typical pattern:
Store last processed timestamp
Call API with timestamp filter
Process new lifecycle updates
Update checkpoint
Connector API
The Connector API allows external integrations to send and retrieve lifecycle updates for documents in Routty.
For lifecycle support, Routty exposes dedicated endpoints under the /lifecycle route.
🏗️ The request and response models below describe the intended API contract for lifecycle support. Exact field names and payload details may still evolve during implementation.
Endpoints
GET /lifecycle/{doc-id}
Returns the full lifecycle history for a specific document.
Path parameters
Parameter | Type | Required | Description |
|---|---|---|---|
| guid | Yes | Routty identifier of the document |
Response
{
"documentId": "3f6f1f4e-6ed7-4a2d-aee7-4d8e927f4eb2",
"currentStatus": {
"code": 205,
"description": "Approved",
"priority": 7,
"flow": "INBOUND"
},
"events": [
{
"status": {
"code": 200,
"description": "Submitted",
"priority": 1,
"flow": "INBOUND"
},
"issuedOn": "2026-03-11T10:00:00Z",
"downloadUrl": "string",
"description": null
},
{
"status": {
"code": 205,
"description": "Approved",
"priority": 7,
"flow": "INBOUND"
},
"issuedOn": "2026-03-11T14:32:15Z",
"downloadUrl": "string",
"description": "Approved for payment"
}
]
}
Response fields
Field | Type | Description |
|---|---|---|
| string | Routty document ID |
| object | Derived lifecycle status (highest priority) |
| array | Full lifecycle event history |
Status codes
Code | Meaning |
|---|---|
200 | Success |
401 | Unauthorized |
403 | Forbidden (out of scope) |
404 | Document not found |
500 | Internal error |
GET /lifecycle/{flow}
Returns document IDs for which lifecycle updates are available for a given flow.
Path parameters
Parameter | Type | Required | Description |
|---|---|---|---|
| string | Yes |
|
Query parameters
Parameter | Type | Required | Description |
|---|---|---|---|
| datetime (ISO 8601) | No | Only return documents updated after this timestamp |
| integer | No | Items per page |
| integer | No | Page to retrieve |
Response
{
"page": 0,
"limit": 0,
"pages": 0,
"count": 0,
"_embedded": {
"_entries": [
{
"documentId": "3f6f1f4e-6ed7-4a2d-aee7-4d8e927f4eb2",
"currentStatusCode": 205,
"currentStatusDescription": "Approved",
"lastUpdated": "2026-03-11T14:32:15Z"
}
]
}
}
Response fields
Field | Type | Description |
|---|---|---|
| array | Documents with lifecycle updates |
| string | Routty document ID |
| integer | Current lifecycle status |
| datetime | Last lifecycle update timestamp |
Status codes
Code | Meaning |
|---|---|
200 | Success |
400 | Invalid request |
401 | Unauthorized |
403 | Forbidden |
500 | Internal error |
POST /lifecycle/{doc-id}
Posts a lifecycle update directly on an existing document.
Path parameters
Parameter | Type | Required | Description |
|---|---|---|---|
| string | Yes | Routty identifier of the original document |
Request body
{
"statusCode": 205,
"issuedOn": "2026-03-11T14:32:15Z",
"description": "Approved for payment"
}
Request fields
Field | Type | Required | Description |
|---|---|---|---|
| integer | Yes | Lifecycle status code |
| datetime (ISO 8601) | Yes | Event timestamp |
| string | No | Optional comment (max 255 chars) |
Response
{
"documentId": "3f6f1f4e-6ed7-4a2d-aee7-4d8e927f4eb2",
"lifecycleDocumentId": "92a8dc31-6f7d-43f6-a8e5-4f33c4eb8c50",
"statusCode": 205
}
Response fields
Field | Type | Description |
|---|---|---|
| string | Original document ID |
| string | Generated lifecycle document |
| integer | Accepted status |
Status codes
Code | Meaning |
|---|---|
200 / 202 | Accepted |
400 | Invalid payload |
401 | Unauthorized |
403 | Forbidden |
404 | Document not found |
409 | Conflict |
500 | Internal error |
Access scoping
Lifecycle retrieval is restricted based on:
connector configuration
API key type (input/output)
flow direction (inbound/outbound)
In general:
integrations only access lifecycle data within their scope
direction determines which lifecycle events are visible
API keys enforce whether the integration acts on inbound or outbound flows
Because lifecycle flows are bidirectional, integrators should validate expected access behavior for their specific configuration.