Flowie
Changelog

What's new

Every change to the Flowie Exchange API, newest first. Additive changes land continuously under /v1/; deprecations are announced six months in advance and flagged with a Sunset response header.

How to read this
New additive — always safe to adopt.
Changed behavior refined — read carefully.
Deprec sunset date announced.
Break only ever in a new major (/v2/…).
Fix bug fix.

v3.7.0 — PA-to-PA portability: SIRET import, bulk import & inter-PA channel

2026-08-02
New
POST /v1/companies/import — onboard a company for portability migration from just its SIRET. A taxpayer files a portability request giving only its siret (or siren); Flowie derives the SIREN, country and Peppol id, resolves the legal name and current PA from the PPF annuaire, then provisions the company on Sovos (via the request's sovosOrganizationId or the configured SOVOS_ORGANIZATION_ID) or registers it locally as pending, and emits company.imported / company.import.pending. Supply sovosOrganizationId + sovosCompanyId instead to import an existing Sovos company.
New
POST /v1/companies/import/batch imports many companies in one call for bulk portability onboarding — concurrent, idempotent, with per-item imported/failed results in order (a per-item failure never aborts the batch).
New
PA-to-PA portability channel — POST /v1/portability/messages and POST /v1/portability/messages/parse. Build the normalised inter-plateforme message (codified subject + 18-field CSV + status code) a portability request must exchange with the losing/gaining PA, and parse inbound messages back into structured fields. The wire format is a best-guess pending the AIFE 15/07 annex; outbound dispatch is gated by PORTABILITY_DISPATCH_ENABLED (default off), so the endpoint builds and returns the message without emailing a counterparty.

v3.6.6 — New document type: purchase request (requisition)

2026-08-02
New
purchase-request is now a document type. POST /v1/documents/send accepts type: "purchase-request" for a purchase requisition — the buyer's internal request to authorise a purchase, ahead of the order. It maps to the transaction-documents PURCHASE_REQUEST document and takes the same from/to + document body as the other order-side types. The Document & invoice types page gains an Orders, quotes & requisitions section covering it alongside quote, purchase-order and sales-order (with a ready example in the tester), and how to chain them via orderReference. Localized in French and Italian.

v3.6.5 — Peppol capabilities are no longer inferred for French companies

2026-08-02
Fix
GET /v1/directory/{peppol_id} stops reporting Peppol capabilities a French company may not have. When a participant was resolved from the PPF annuaire, documentTypes was hardcoded to invoice/credit-note and smpStatus was derived from the INSEE administrative state — so any going concern in France was reported as able to receive Peppol invoices. The Peppol Directory is now queried alongside the annuaire: documentTypes, accessPoint, registeredSince and smpStatus are returned only when the company is actually on the network, and left empty otherwise. Identity, VAT and the French addressing plan are unchanged. If you branched on smpStatus for French participants, it can now be null.
Fix
Peppol participant lookups now reach the directory at all. The participant filter was sent as a bare identifier (921376265) where the Peppol Directory requires the fully-qualified form (iso6523-actorid-upis::0009:921376265); it answered HTTP 400 and the error was swallowed, so every participant looked unregistered. Registration status and document types are now returned for companies that really are on the network.

v3.6.4 — French addressing plan on directory lookups

2026-08-02
Fix
GET /v1/directory/{peppol_id} now returns the French addressing plan for any French participant. The enrichment.platformeAgree block — the routing platform an invoice must be addressed to, its addressing level and effective dates — was only attached when the participant was already registered with Flowie, so for an ordinary French company looked up straight from the PPF annuaire it was silently absent. It is now returned on both paths, under the same key. Identity and VAT enrichment are unchanged, and the two annuaire calls are made concurrently so the extra data costs no additional latency.

v3.6.3 — Download the Postman collection

2026-08-02
New
The API Reference now has a Postman collection section. One-click download of the ready-made collection (every endpoint, pre-filled with a working example body), with import instructions and the two collection variables to set — baseUrl and token (bearer auth). The openapi.json spec is offered alongside for generating your own client. The collection is regenerated on every release, so it always matches the reference.

v3.6.2 — Try any use case from the docs

2026-08-02
New
Ready-to-send example payloads for every use case. The Document & invoice types page now has a Test any use case section: an example POST /v1/documents/send body for each scenario — standard invoice, prepayment/acompte, corrected, credit & debit notes, self-billing, reverse charge, multi-party, orders, quote and event — each with Try in Playground (opens the request builder prefilled, your sandbox key loaded), Copy JSON and Copy curl. Every example uses the sandbox test identifiers, so it runs as-is. Localized in French and Italian.

v3.6.1 — Cross-tenant isolation on collection endpoints

2026-07-30
Fix
Collection endpoints now enforce your tenant on a caller-supplied companyId. On GET /v1/documents, POST /v1/documents/search and GET /v1/events, a companyId filter is validated against the organization your credentials are bound to instead of being applied as-is; naming an organization you can't access now returns 403 PERMISSION_DENIED rather than that tenant's rows. The default (unfiltered) company listing (GET /v1/companies) is scoped to your own organization, and GET /v1/companies/{id} rejects an id outside your tenant — including one reached via a vat:/peppol: alias. This closes a cross-tenant read of company records, document metadata and events. Calls that omit companyId, or pass your own organization, are unaffected.

v3.6.0 — Document & invoice types reference

2026-07-28
New
A single page for every document and invoice type. Document & invoice types lays out the seven type values (invoice, credit-note, debit-note, purchase-order, sales-order, quote, event), the four invoice subtypes rendered as the UBL InvoiceTypeCode (commercial 380, prepayment 386, corrected 384, self-billed 389), and — new — dedicated deep-dives on prepayment invoices (facture d'acompte, UNCL1001 386), self-billing (autofacturation, the selfBilled flag that flips the buyer/seller roles) and reverse-charge self-invoicing (autofattura, Italian TD16–TD29), plus a note on how employee expenses map onto the model (inbound invoice vs e-reporting). Reachable from the API Reference menu and sidebar.

v3.5.1 — Multi-column menu panels

2026-07-14
Changed
Top-menu panels with several groups now lay out as columns. Compliance shows All countries · 🇫🇷 France · 🇮🇹 Italy side by side; Guides, Sandbox and Build with AI pair their pages with their journey group. Panels that would overflow the viewport flip to right-aligned automatically.

v3.5.0 — Journey-shaped menus, deeper compliance navigation

2026-07-14

Navigation now follows the integration journey: integrate fast, test extensively, verify it works, then deep-dive the regulations — with the edge cases one click away.

Changed
Deeper top-menu dropdowns. Guides gains an Integrate fast group (send an invoice, receive, ERP webhooks, order flow, go-live checklist); Sandbox a Test extensively group (test identifiers, recipient simulators, lifecycle & compliance sims, forced errors, time travel); Build with AI a Ship faster with AI group (MCP server, docs for agents, AI tools); and Compliance now lists the full 🇫🇷 France and 🇮🇹 Italy deep-dives — including the refusal & rejection edge cases and all 45 cas d'usage — from every page.
Changed
Compliance sidebars nest the deep-dives. On every country page, the France and Italy entries in the countries list expand with their sub-pages (lifecycle explorer, refusal & rejection, use cases, integration playbook, document types), so the regulation deep-dives are reachable from anywhere in the compliance section — in all three languages.
Changed
The redundant "Exchange" chip next to the logo was removed — it appeared inconsistently and duplicated the Docs menu entry.

v3.4.2 — Richer top-menu dropdowns

2026-07-13
Changed
Top-menu dropdowns now tell you what's inside. Every entry carries a one-line insight under the page name — e.g. Errors — every error code, with the fix, Sandbox — simulators, test IDs & time travel — localized in all three languages, with a refreshed panel design (soft entrance animation, accent highlight on the current page, deeper shadow). Same links, faster orientation.

v3.4.1 — Sidebar menus aligned with the top menu

2026-07-13
Changed
Every sidebar now leads with its section. The first sidebar group on Reference, Guides, Build with AI, Sandbox and Playground pages lists the same pages as that section's top-menu dropdown (with the current page highlighted), so the side menu and the top menu never disagree — e.g. the error catalog now shows its Reference siblings (overview, data model, webhooks) instead of a lone page outline. Page outlines are uniformly titled "On this page", matching the compliance deep-dives, and the French/Italian compliance pages' sidebar titles are now translated. Compliance country pages keep their richer country directory as the section group.

v3.4.0 — Clean docs architecture: section directories + menu dropdowns

2026-07-13

The docs URL tree now mirrors the menu: every section is a directory, every page is directly reachable from the top menu, and the language suffix is unambiguous everywhere.

Changed
Every menu section became a directory. reference/ (overview, data model, errors, webhooks), guides/ (overview, onboarding kit), build-with-ai/ (overview, agent onboarding), sandbox/ (overview, API keys), playground/ (overview, request inspector) — in all three languages. Every old flat URL (e.g. reference.html, keys.html) permanently redirects to its new home, preserving query strings and anchors, so existing bookmarks, deep links and API-returned viewerUrls keep working.
Changed
France and Italy compliance deep-dives moved to per-country directories. compliance/fr-lifecycle.htmlcompliance/fr/lifecycle.html, and likewise the France overview (compliance/fr/), refusal & rejection, use cases, integration playbook, the Italy overview (compliance/it/) and document types. The old flat names read ambiguously next to the .fr.html/.it.html language suffixes; now the directory is the country and the suffix is the language. Old URLs redirect.
New
Top-menu section dropdowns. Sections that own sub-pages (API Reference, Guides, Compliance, Build with AI, Sandbox, Playground) expose them in a dropdown, so pages like the error catalog, webhook cookbook or API-keys manager are one click from anywhere — no more reliance on buried body links. Opens on hover or keyboard focus, with a caret toggle for touch.
Changed
Sitemap, search index, llms.txt/llms-full.txt exports and the OpenAPI description examples all follow the new paths; the sitemap also gained the previously-missing Build with AI and compliance sub-pages.

v3.3.0 — Update a document's lifecycle by invoice number

2026-07-06
New
Transition a document by its invoice number. POST /v1/documents/by-number/{number}/lifecycle targets a document by the human-readable invoice number instead of Flowie's internal documentId — for integration partners (e.g. ERP/iPaaS connectors) that only hold the number. Same request body, auth and response as POST /v1/documents/{documentId}/lifecycle, and it runs the identical state-machine validation, tx-docs update, PPF/SDI compliance reporting and lifecycle.updated webhook. The number is resolved scoped to your organization, so you can never transition another tenant's document. Because invoice numbers are not unique, resolution is strict: no match → 404, exactly one → the transition is applied, more than one → 409 (re-issue against the specific documentId). The existing id-based route is unchanged.

v3.2.1 — France: machine-readable lifecycle referential

2026-07-03
New
The French lifecycle referential is now published as data. /schemas/fr-lifecycle-statuses.json carries all 14 statuses (200–213) — tier, phase, emitter, terminality, motif & amount-block rules, UNTDID 1373 mapping, canonical transitions, and the exact Flowie call or webhook per status — validated by /schemas/fr-lifecycle-status.schema.json (JSON Schema draft 2020-12). Versioned with the DGFiP / AFNOR spec revisions it was verified against. See the lifecycle explorer.

v3.2.0 — France: interactive lifecycle reference & integration playbook

2026-07-03

Two new France compliance pages make the docs a full reference for the 2026–2027 reform.

New
Lifecycle explorer — the complete AFNOR XP Z12-012 status referential (codes 200–213) as an interactive, animated state machine: filter by tier (obligatoire / recommandé / libre), play the five canonical scenarios (happy path, dispute, suspension, refusal, platform reject) with a live webhook log, and click any status for its definition, transitions and the exact API call that emits or observes it. Includes the CDAR field guide (MDT-77/105/113/114, MDG-43 amount blocks), the UNTDID 1373 mapping, and a status → API cheat-sheet.
New
Integration playbook — the end-to-end French implementation path: onboarding & annuaire, receiving, sending Factur-X, the buyer/supplier status responsibility matrix, a production-grade webhook handler (idempotent, out-of-order-safe), e-reporting, the sandbox test matrix and a go-live checklist.
Changed
France overview corrected & re-tiered. Deadlines fixed (large & mid-sized companies must send from 1 September 2026, not 2027 — SMEs follow in 2027) and the lifecycle section now reflects the official three-tier classification: 4 obligatoires (200, 210, 212, 213), 5 recommandés (203–206, 211) and 5 coded libres (201, 202, 207–209). The French translation drops a legacy status-code table (302/304/309/40x) that never existed in the official referential.
New
GET /v1/documents/{id}/lifecycle now returns currentStatusReason — the failing EN 16931 / CTC-FR schematron rule ids behind a validation-driven status.

v3.1.11 — Directory-line search returns real entries

2026-06-12
Fix
POST /afnor/directory-service/v1/directory-line/search was a stub that always returned totalNumberOfResults: 0. It now forwards the filter set to the PPF annuaire (ppf-annuaire's /api/search/ligne-annuaire) and maps each entry to an AFNOR directory line (addressingIdentifier, routingIdentifier, administrativeStatus, …), so a SIRET that has annuaire lines now returns them.

v3.1.10 — Original/Converted XML for JSON-created docs

2026-06-12
Fix
Retrieving a document's Original/Converted XML (AFNOR GET /afnor/flow-service/v1/flows/{id}?docType=Original and GET /v1/documents/{id}/xml) returned 404 "XML not available… created from JSON without a stored XML file" for documents created from structured JSON. When no XML is physically stored, the UBL 2.4 is now rendered on the fly from the document's JSON (via the same converter the "Convert to UBL" flow uses), so the original/converted content is returned. A genuinely empty document still 404s.

v3.1.9 — Flow search results match the query

2026-06-12
Fix
POST /afnor/flow-service/v1/flows/search could return flows whose flowType/flowDirection didn't match the request (e.g. a CustomerInvoice/Out query surfacing SupplierInvoice/In rows), and lifecycle (…LC) searches returned plain invoices. Results are now hard-filtered to the requested flowType/flowDirection sets, so the response always matches the query (lifecycle searches return an empty set when no lifecycle flows exist rather than mislabeled invoices).

v3.1.8 — API-key creation hardening

2026-06-12

Closes privilege-escalation gaps in POST /v1/api-keys. Keys remain bound to the caller's organization and tier (no organizationId in the request).

Changed
Scopes are clamped to the caller. A new key can no longer be granted scopes the caller doesn't hold — requesting an unheld scope (or *) now returns 403. Omitting scopes inherits the caller's scopes instead of silently defaulting to *.
Changed
rateLimit.requestsPerMinute is clamped to the tier ceiling, so a key can't grant itself a higher request rate than its tier allows.
Fix
name must be non-empty and expiresAt, if given, must be in the future (a past value now returns 400 instead of minting a dead key). Keys with no expiresAt remain permanent.

v3.1.7 — Company PATCH fix

2026-06-12
Fix
PATCH /v1/companies/{id} returned 500 when only capabilities or compliance were patched — the response was built from a detached DB row after the session closed. It is now built inside the session.

v3.1.6 — AFNOR SIREN search pagination

2026-06-11
Fix
SIREN search pagination. POST /afnor/directory-service/v1/siren/search only fetched limit rows then sliced, so pages past the first (ignore > 0) came back empty and totalNumberOfResults reflected only the fetched window. Pages now resolve correctly with an accurate total.
Fix
Bounded ignore. ignore was unbounded; a very large value forced an oversized upstream fetch. It is now capped (max 10000) and the upstream fetch is bounded regardless.

v3.1.5 — Deterministic directory ordering

2026-06-11
Fix
Directory search results are now ordered deterministically. The local-registration fallback used a bare LIMIT with no ORDER BY, so identical GET /v1/directory/search calls could return rows in a different order. All AFNOR directory-service lookups are read-only and idempotent.

v3.1.4 — Directory by SIREN, list direction, recoverable number lookup

2026-06-10
Fix
Directory search by SIREN/SIRET in q. A bare 9-digit SIREN (or 14-digit SIRET) typed into GET /v1/directory/search?q=… now routes to the SIREN/SIRET lookup instead of the name search, which never matched a number. The AFNOR endpoints also stop deriving the wrong SIREN from the VAT number.
Fix
Per-row direction in document listings. GET /v1/documents now stamps each row incoming/outgoing (previously always null). An invalid direction now returns 400 instead of silently returning both.
Fix
Recoverable lookup by invoice number. When a number matches more than one document, GET /v1/documents/{number} now returns the candidate ids in the 409 body instead of a dead-end error.

v3.1.3 — Lifecycle history shows real statuses

2026-06-10
Fix
GET /v1/documents/{id}/lifecycle returned currentStatus and every history[].status as "unknown" (and setBy null) for all real documents. The history now reads the upstream audit-log's real fields (action, actionBy), and currentStatus/allowedTransitions resolve from the document's authoritative per-party lifecycle status rather than the most recent audit action.

Docs — Unified navigation

2026-06-04

Documentation-site improvements only — no API surface change. The top navigation is now generated from a single source of truth, so every page (including the per-country compliance pages) carries the same complete, consistent set of links.

Docs
Top navigation is now consistent across every page. Pages that were missing the API Keys or Playground links (e.g. Build with AI, agent onboarding) now carry the full set, and the per-country compliance pages use the same generated nav.
Docs
Active-link highlighting now works on the French and Italian pages even with JavaScript disabled (their nav hrefs point at the English asset, so the old runtime filename match never fired).
Docs
Browser-storage keys used by the docs site (theme, cached tokens, saved playground vars) are now sourced from a single window.FLW registry loaded on every page, removing drift between the individual scripts.

v3.1.2 — Agent handoff link

2026-05-08

Hand a single URL to your LLM and it does the integration. The user pre-approves a scope set bound to their org; the agent redeems the embedded token for an API key in one POST. No PKCE round-trip, no consent UI — the issued key acts on the user's real organization, not a fresh sandbox.

New
POST /v1/oauth/handoff (authenticated) — mints a single-use, scope-and-org-bound handoff token and returns a ready-to-paste URL. Default 10-min TTL (60s–60min configurable). Default scopes: send, receive, documents.read, companies.read, stats. Caller cannot pre-approve scopes their own token doesn't hold.
New
POST /v1/oauth/handoff/exchange (no auth) — single-use redemption. Returns an flw_test_… (or flw_live_… for paid tiers) key bound to the original user's organization, company, and tier.
New
Home-page widget under "Building with an AI agent?" — copy the anonymous link, or paste an existing API key to generate a personalized handoff URL in-browser. The pasted key never leaves the page.
Docs
Agent onboarding documents three paths now: handoff (fastest), sandbox bootstrap (no auth), OAuth consent (PKCE). LLM discovery surface (llms.txt) updated.

v3.1.1 — Belgium HERMES retired

2026-05-04

Belgium's regulator-side reporting hub HERMES was decommissioned by FPS Finance on 2025-12-31 (consultation-only access expired 2026-03-31). Flowie's HermesAdapter and the BE branch of the compliance dispatcher have been removed. Belgian invoices are now pure Peppol — the delivery itself is the compliance event.

Changed
No compliance.reported events fire for Belgian invoices. If your webhook router branches on data.platform == "HERMES", drop the branch — see migration guide for the full diff.
Changed
BE-CIUS validation now surfaces synchronously: POST /v1/documents/send returns 422 with the BE-CIUS schematron rule code in error.details[].code + the failing XPath. Replaces the old deferred compliance.reported.failed + HER-* path. Same checks, faster feedback.
Deprec
HERMES_REPORT_URL / HERMES_REPORT_TOKEN environment variables are no longer read. simulateCompliance: "reject_HER_001" sandbox value is also retired. Historical compliance_reports rows with platform=HERMES are retained for audit; new ones won't be created.
Docs
Belgium compliance page (compliance/be.html) rewritten with sourced timeline (2024-02-06 → 2028-01-01), 4-corner Peppol diagram, end-to-end send example, lifecycle table comparing FR/IT/BE, BR-BE-* error catalog, sandbox tests, and HERMES → Peppol migration table.

v3.1.0 — AI agents & multi-org

2026-05-03

First-class Model Context Protocol surface for AI agents, plus organization switching for JWT users in multiple orgs.

New
MCP servers. /exchange/mcp (curated, 34 tools across Documents / Directory / Companies / Lifecycle / Compliance / Partners) and /exchange/mcp/full (every documented operation, 94 tools). Same Bearer token as REST, same quotas, same sandbox. Full guide →
New
POST /v1/documents/send accepts type: "event" — pure audit-trail records, persisted as documents but never routed over Peppol. Useful for ERP-side notifications you want to keep alongside real invoices.
New
Organization switching for multi-org JWT users: switch the active organization without re-login. Existing flw_* API keys are unaffected (single-tenant by design).
Changed
MCP transport upgraded from legacy SSE to streamable-HTTP (MCP spec 2025-06-18). Reconfigure existing clients as "transport": "streamable-http".

v3.0.0 — Unified surface

2026-04-13

First stable cut of the Exchange API. The legacy /api/… endpoints continue to work but are deprecated.

New
Resource-oriented surface under /v1/: companies, documents, partners, webhooks, events, compliance, platform, api-keys, stats.
New
Lifecycle state machine with auto-reporting to PPF (FR), SDI (IT), HERMES (BE).
New
Idempotency-Key is accepted on every POST with a 24h TTL.
New
Cursor-based pagination everywhere (limit, cursor, hasMore).
New
Platform keys with X-Flowie-Company for tenant-scoped calls.
New
AFNOR XP Z12-013 adapter under /afnor/flow-service and /afnor/directory-service.
New
cXML PunchOut callback at /document/callback.
Deprec
All /api/… endpoints. Sunset date: 2027-04-01. Mapping table in the migration guide.

v2.9.0

2026-03-28
New
POST /v1/documents/search accepts compound AND/OR/NOT filter trees.
New
Webhook deliveries now include X-Flowie-Attempt header.
Changed
Directory verify latency dropped from p95 420ms → 90ms via SMP cache.

v2.8.0

2026-03-10
New
AI tag recommendation: POST /v1/categorization/objects/tags/auto.
New
Structured document view at GET /v1/documents/{id}/structured — all scalars flattened, ready for warehouses.
Fix
VAT normalization now strips all whitespace (was only stripping leading/trailing).

v2.7.0

2026-02-14
New
Company identifier resolution: vat: and peppol: prefixes accepted in any {company_id} / {partner_id} path param.
New
Batch lifecycle update: POST /v1/documents/lifecycle/batch, up to 500 per call.
Changed
HERMES (BE) reporting enabled by default for newly created BE companies. Existing companies untouched.

v2.6.0

2026-01-22
New
Circuit-breaker visibility at GET /health/readiness. Per-upstream state.
New
Webhook secret rotation: PATCH /v1/webhooks/{id} with {"rotateSecret": true}. Old secret stays valid for 60 minutes.
Fix
Idempotency cache correctly distinguishes requests differing only in a query param.

v2.5.0

2025-12-05
New
PPF (FR) adapter graduated from beta. Registered PDP status confirmed by DGFiP.
New
ISO 20022 / SEPA export at POST /v1/payments/export/iso20022.

v2.4.0

2025-10-18
New
Events API (/v1/events) — durable twin of every webhook, replayable.
New
Rate-limit headers (X-RateLimit-*) added to every response.
Changed
Free tier rate limit raised from 30 to 60 req/min.