Customer Knowledge base

Document Life Cycle

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

ram:TestIndicator/udt:Indicator

Mapped from the lifecycle document test flag

ram:BusinessProcessSpecifiedDocumentContextParameter/ram:ID

REGULATED

ram:GuidelineSpecifiedDocumentContextParameter/ram:ID

urn.cpro.gouv.fr:1p0:CDV:invoice

Exchanged Document

The generated exchanged document contains:

XML path

Value

ram:ID

ACK-{lifecycleDocumentId}

ram:TypeCode

916

ram:IssueDateTime

Lifecycle event issuedOn

ram:SenderTradeParty

Resolved from the original document flow and lifecycle flow

ram:RecipientTradeParty

Resolved from the original document flow and lifecycle flow

Referenced Document

The generated referenced document contains:

XML path

Value

ram:IssuerAssignedID

Original document reference

ram:TypeCode

380

ram:ReceiptDateTime

Original document received timestamp

ram:FormattedIssueDateTime

Original document creation timestamp

ram:ProcessConditionCode

Posted lifecycle statusCode

ram:ProcessCondition

Posted lifecycle description, when provided

ram:IssuerTradeParty

Seller or invoice issuer

ram:SpecifiedDocumentStatus

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:SpecifiedDocumentCharacteristic blocks.

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:

  1. Sending lifecycle events to Routty

  2. 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:

  1. Uploading a lifecycle document through the regular document upload flow

  2. 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
  1. A lifecycle document is uploaded through the regular inbound document flow.

  2. Routty classifies the upload as a lifecycle document.

  3. 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

  4. Routty links the lifecycle event to the original document.

  5. 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.

  1. The integrator posts a lifecycle update to a known Routty document ID.

  2. Routty generates an internal lifecycle event document from the provided lifecycle data.

  3. That generated lifecycle document is then processed through the same lifecycle pipeline as an uploaded CDAR document.

  4. 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:

  1. Store last processed timestamp

  2. Call API with timestamp filter

  3. Process new lifecycle updates

  4. 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

GET

/lifecycle-api/{doc-id}

Returns the full lifecycle history for a specific document.

GET

/lifecycle-api

Returns documents that have lifecycle updates.

GET

/lifecycle-api/{flow}

Returns documents that have lifecycle updates for a given flow.

POST

/lifecycle-api/{doc-id}

Posts a lifecycle update directly on an existing document.

POST

/lifecycle-api/events/{lifeCycleEventId}/error

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

doc-id

guid

Yes

Routty identifier of the document

Query parameters:

Parameter

Type

Required

Description

issuedOnAfter

datetime

No

Only return lifecycle events issued after this timestamp.

Response
JSON
{
  "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

documentId

string

Routty document ID

currentStatus

object

Derived lifecycle status (highest priority)

events

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

flow

string

No

inbound or outbound

Query parameters

Parameter

Type

Required

Description

updatedAfter

datetime (ISO 8601)

No

Only return documents updated after this timestamp

limit

integer

No

Items per page

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

_entries

array

Documents with lifecycle updates

items[].documentId

string

Routty document ID

items[].currentStatusCode

integer

Current lifecycle status

items[].lastUpdated

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

doc-id

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

statusCode

integer

Yes

Lifecycle status code.

issuedOn

datetime

Yes

Event timestamp.

description

string

No

Optional comment, max 1000 characters.

specifiedDocumentStatus

object

No

Optional CDAR ram:SpecifiedDocumentStatus detail/history block. This does not replace the primary lifecycle status.

specifiedDocumentStatus.referenceDateTime

datetime

No

Optional status detail timestamp written as ram:ReferenceDateTime.

specifiedDocumentStatus.conditionCode

string

No

Optional status detail condition code written as ram:ConditionCode.

specifiedDocumentStatus.reasonCode

string

No

Optional status detail reason code written as ram:ReasonCode.

specifiedDocumentStatus.reason

string

No

Optional status detail reason text written as ram:Reason.

specifiedDocumentStatus.condition

string

No

Optional status detail condition text written as ram:Condition.

specifiedDocumentStatus.requestedActionCode

string

No

Optional requested action code written as ram:RequestedActionCode.

specifiedDocumentStatus.requestedAction

string

No

Optional requested action text written as ram:RequestedAction.

specifiedDocumentStatus.sequenceNumeric

decimal

No

Optional sequence number written as ram:SequenceNumeric.

specifiedDocumentStatus.includedNotes

array

No

Optional notes written as repeatable ram:IncludedNote elements.

specifiedDocumentStatus.specifiedDocumentCharacteristics

array

No

Optional repeatable detail blocks written as ram:SpecifiedDocumentCharacteristic elements.

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

documentId

guid

Original document ID

lifecycleDocumentId

guid

Generated lifecycle document

statusCode

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

lifeCycleEventId

guid

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.