Skip to main content
Skip table of contents

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

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:

  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 Life Cycle 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.

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

  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

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

CODE
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

CODE
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:

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

doc-id

guid

Yes

Routty identifier of the document

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

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/{flow}

Returns document IDs for which lifecycle updates are available for a given flow.

Path parameters

Parameter

Type

Required

Description

flow

string

Yes

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
CODE
{
  "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/{doc-id}

Posts a lifecycle update directly on an existing document.

Path parameters

Parameter

Type

Required

Description

doc-id

string

Yes

Routty identifier of the original document

Request body
CODE
{
  "statusCode": 205,
  "issuedOn": "2026-03-11T14:32:15Z",
  "description": "Approved for payment"
}
Request fields

Field

Type

Required

Description

statusCode

integer

Yes

Lifecycle status code

issuedOn

datetime (ISO 8601)

Yes

Event timestamp

description

string

No

Optional comment (max 255 chars)

Response
CODE
{
  "documentId": "3f6f1f4e-6ed7-4a2d-aee7-4d8e927f4eb2",
  "lifecycleDocumentId": "92a8dc31-6f7d-43f6-a8e5-4f33c4eb8c50",
  "statusCode": 205
}
Response fields

Field

Type

Description

documentId

string

Original document ID

lifecycleDocumentId

string

Generated lifecycle document

statusCode

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.

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.