Overview
A Document Lifecycle 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 documents 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.
Lifecycle
A Lifecycle is the business progression of a document over time, expressed through a sequence of status updates.
Lifecycle Event
A Lifecycle 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
Lifecycles 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 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 Submitted -
201 Issued -
207 Disputed -
205 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.
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. For direct API-created lifecycle events, Routty generates a CDAR-based (CDAR Definition) XML document and stores the generated lifecycle files for the lifecycle document.
Lifecycle documents themselves are not exported as standalone regular documents, they are directly moved to the SUCCESS status once the events were successfully extracted and the output artifacts have been created.
Generated CDAR Structure
When Routty generates CDAR XML from a posted lifecycle event, the source code currently emits rsm:CrossDomainAcknowledgementAndResponse using the UN/CEFACT :100 namespaces.
The generated root contains:
-
rsm:ExchangedDocumentContext -
rsm:ExchangedDocument -
rsm:AcknowledgementDocument
Document Context
The generated document context contains:
|
XML path |
Value |
|---|---|
|
|
Mapped from the lifecycle document test flag |
|
|
|
|
|
|
Exchanged Document
The generated exchanged document contains:
|
XML path |
Value |
|---|---|
|
|
|
|
|
|
|
|
Lifecycle event |
|
|
Resolved from the original document flow and lifecycle flow |
|
|
Resolved from the original document flow and lifecycle flow |
Referenced Document
The generated referenced document contains:
|
XML path |
Value |
|---|---|
|
|
Original document reference |
|
|
|
|
|
Original document received timestamp |
|
|
Original document creation timestamp |
|
|
Posted lifecycle |
|
|
Posted lifecycle |
|
|
Seller or invoice issuer |
|
|
Optional detail data, when provided |
ram:SpecifiedDocumentStatus is not the primary lifecycle status in generated CDAR. The primary status is written directly on ram:ReferenceReferencedDocument as ram:ProcessConditionCode and ram:ProcessCondition.
The optional ram:SpecifiedDocumentStatus block is reserved for status detail and history data such as:
-
Reference date.
-
Condition and reason fields.
-
Included notes.
-
Requested action.
-
Sequence number.
-
Repeatable
ram:SpecifiedDocumentCharacteristicblocks.
For seller identification in ram:ReferenceReferencedDocument/ram:IssuerTradeParty:
-
An outbound original document uses the original document company as seller.
-
An inbound original document uses the original document business partner as seller.
Lifecycle extraction accepts both the current direct status location and older nested status locations when parsing incoming CDAR.
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 Lifecycle 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-api/{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
-
The direct API approach still mirrors the default upload-based approach internally.
-
It does not bypass the lifecycle processing model itself.
-
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-api/{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-api
GET /lifecycle-api/{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-api route.
Endpoints
|
Method |
Path |
Description |
|---|---|---|
|
|
|
Returns the full lifecycle history for a specific document. |
|
|
|
Returns documents that have lifecycle updates. |
|
|
|
Returns documents that have lifecycle updates for a given flow. |
|
|
|
Posts a lifecycle update directly on an existing document. |
|
|
|
Marks a lifecycle event as failed after it has been created. |
GET /lifecycle-api/{doc-id}
Returns the full lifecycle history for a specific document.
Path parameters
|
Parameter |
Type |
Required |
Description |
|---|---|---|---|
|
|
guid |
Yes |
Routty identifier of the document |
Query parameters:
|
Parameter |
Type |
Required |
Description |
|---|---|---|---|
|
|
|
No |
Only return lifecycle events issued after this timestamp. |
Response
{
"documentId": "3f6f1f4e-6ed7-4a2d-aee7-4d8e927f4eb2",
"currentStatus": {
"code": 205,
"description": "Approved",
"priority": 7,
"flow": "INBOUND"
},
"events": [
{
"id": "d1b4aa0e-4c6a-4d68-a2f9-8e6f7e04c9a1",
"lifecycleDocumentId": "92a8dc31-6f7d-43f6-a8e5-4f33c4eb8c50",
"status": {
"code": 200,
"description": "Submitted",
"priority": 1,
"flow": "INBOUND"
},
"processingStatus": "SUCCESS",
"latestErrorMessage": null,
"issuedOn": "2026-03-11T10:00:00Z",
"downloadUrl": "string",
"description": null
},
{
"id": "e4d97ff2-37d2-4ef2-8efb-83f5cce41af8",
"lifecycleDocumentId": "92a8dc31-6f7d-43f6-a8e5-4f33c4eb8c50",
"status": {
"code": 205,
"description": "Approved",
"priority": 7,
"flow": "INBOUND"
},
"processingStatus": "SUCCESS",
"latestErrorMessage": null,
"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-api and /lifecycle-api/{flow}
Returns document IDs for which lifecycle updates are available. When flow is provided, only lifecycle updates for that flow are returned.
Path parameters
|
Parameter |
Type |
Required |
Description |
|---|---|---|---|
|
|
string |
No |
|
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-api/{doc-id}
Posts a lifecycle update directly on an existing document.
Path parameters
|
Parameter |
Type |
Required |
Description |
|---|---|---|---|
|
|
guid |
Yes |
Routty identifier of the original document |
Request body
{
"statusCode": 205,
"issuedOn": "2026-03-11T14:32:15Z",
"description": "Approved for payment",
"specifiedDocumentStatus": {
"referenceDateTime": "2026-03-11T14:32:15Z",
"conditionCode": "PAYMENT",
"reasonCode": "NONE",
"reason": "No blocking reason",
"condition": "Payment information accepted",
"requestedActionCode": "NONE",
"requestedAction": "No action required",
"sequenceNumeric": 1,
"includedNotes": [
{
"contentCode": "INFO",
"subjectCode": "AAI",
"content": "Approved for payment"
}
],
"specifiedDocumentCharacteristics": [
{
"id": "BT-115",
"typeCode": "MEN",
"valueAmount": 100.00,
"valueAmountCurrencyId": "EUR",
"valuePercent": 20.00
}
]
}
}
Request fields
|
Field |
Type |
Required |
Description |
|---|---|---|---|
|
|
|
Yes |
Lifecycle status code. |
|
|
|
Yes |
Event timestamp. |
|
|
|
No |
Optional comment, max 1000 characters. |
|
|
|
No |
Optional CDAR |
|
|
|
No |
Optional status detail timestamp written as |
|
|
|
No |
Optional status detail condition code written as |
|
|
|
No |
Optional status detail reason code written as |
|
|
|
No |
Optional status detail reason text written as |
|
|
|
No |
Optional status detail condition text written as |
|
|
|
No |
Optional requested action code written as |
|
|
|
No |
Optional requested action text written as |
|
|
|
No |
Optional sequence number written as |
|
|
|
No |
Optional notes written as repeatable |
|
|
|
No |
Optional repeatable detail blocks written as |
Each specifiedDocumentCharacteristics item can include:
-
id -
typeCode -
valueChangeIndicator -
name -
description -
location -
value -
valueAmount -
valueAmountCurrencyId -
valueMeasure -
valueMeasureUnitCode -
valueDateTime -
valueCode -
valueQuantity -
valueNumeric -
valuePercent
Response
{
"documentId": "3f6f1f4e-6ed7-4a2d-aee7-4d8e927f4eb2",
"lifecycleDocumentId": "92a8dc31-6f7d-43f6-a8e5-4f33c4eb8c50",
"statusCode": 205
}
Response fields
|
Field |
Type |
Description |
|---|---|---|
|
|
guid |
Original document ID |
|
|
guid |
Generated lifecycle document |
|
|
integer |
Accepted status |
Status codes
|
Code |
Meaning |
|---|---|
|
202 |
Accepted |
|
400 |
Invalid payload |
|
401 |
Unauthorized |
|
403 |
Forbidden |
|
404 |
Document not found |
|
409 |
Conflict |
|
500 |
Internal error |
POST /lifecycle-api/events/{lifeCycleEventId}/error
Marks a lifecycle event as failed after it has been created.
Path parameters:
|
Parameter |
Type |
Required |
Description |
|---|---|---|---|
|
|
|
Yes |
Lifecycle event identifier. |
Request body:
{
"errorType": "VALIDATION_ERROR",
"errorMessage": "The lifecycle event could not be processed"
}
The endpoint writes the error on the lifecycle document, marks lifecycle event processing as ERROR, and audits both the lifecycle document and the original document where applicable.
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.