---
title: "Flowie Exchange API — developer portal"
description: "Entry point for developers: base URLs, authentication, the OpenAPI contract, the MCP server, SDKs and the sandbox."
canonical: "https://docs.get-flowie.com/developers.md"
---

# Flowie Exchange API — developer portal

One REST API for compliant electronic invoicing across **47 countries** and every
major network: Peppol, France PA/PPF, Italy SDI, Saudi Fatoora, Israel ITA,
India GST IRP, Malaysia MyInvois.

HTML version of this page: <https://docs.get-flowie.com/developers/>

## Get a key with no signup

One unauthenticated call. No form, no sales conversation, no human in the loop —
this is the intended path for an agent integrating on its own.

```bash
curl -X POST https://back.flowie.ink/exchange/v1/sandbox/bootstrap \
  -H "Content-Type: application/json" -d '{}'
```

Returns `apiKey`, `organizationId`, a seeded `company`, `nextSteps` and
`expiresAt`. Sandbox data is synthetic and never reaches a real network — do not
put real personal data in it.

## Base URLs

| Environment | Base URL |
|---|---|
| Sandbox | `https://back.flowie.ink/exchange` |
| Production | `https://back.p2p-flowie.com/exchange` |

## SDK

The JavaScript/TypeScript SDK is published on npm as **`flowie-exchange`**
(unscoped — there is no `@flowie/exchange` package):

```bash
npm install flowie-exchange
```

- Registry: <https://www.npmjs.com/package/flowie-exchange>
- Node 18+ (uses the built-in `fetch`)

```js
import { FlowieExchange } from "flowie-exchange";

const flowie = await FlowieExchange.bootstrapSandbox();

const doc = await flowie.sendDocument({
  type: "invoice",
  from: flowie.bootstrap.company.peppolId,
  to: flowie.bootstrap.company.peppolId,
  document: {
    number: "INV-001",
    issueDate: "2026-08-06",
    currency: "EUR",
    lines: [{ description: "Consulting", quantity: 1, unitPrice: 1000, vatRate: 20 }],
  },
});

await flowie.setLifecycle(doc.id, "approved");
```

For other languages, generate a client from the OpenAPI 3.1 contract at
<https://docs.get-flowie.com/openapi.json> (112 operations), or call the REST
endpoints directly.

## Core endpoints

| Task | Call |
|---|---|
| Send a document | `POST /v1/documents/send` |
| List documents | `GET /v1/documents` |
| Read one document | `GET /v1/documents/{document_id}` |
| Read lifecycle history | `GET /v1/documents/{document_id}/lifecycle` |
| Advance lifecycle | `POST /v1/documents/{document_id}/lifecycle` |
| Validate without sending | `POST /v1/documents/validate` |
| Check reachability | `POST /v1/directory/verify` |
| Search the directory | `GET /v1/directory/search` |
| Register on Peppol | `POST /v1/companies/{company_id}/register` |
| Country mandate rules | `GET /v1/compliance/status` |

## Gotchas that will cost you a debugging cycle

- **The invoice field is `number`, not `invoiceNumber`.** The API validates on
  `document.number` and returns `400 INVALID_REQUEST` naming the field.
- **`to` is required** for every document type except `event`.
- **Keep the `X-Request-Id`** from any 4xx/5xx. Every failure is replayable by
  that id through the request inspector — far faster than reconstructing it from
  logs, and the first thing support will ask for.
- **`POST /v1/documents/send` is not idempotent by default.** Pass an
  `Idempotency-Key` header when retrying.
- **Lifecycle transitions are not bookkeeping.** In several countries the
  transition *is* the receiver's statutory reporting obligation and is forwarded
  to the national platform. Do not fire them speculatively.
- **Multi-organization callers** must send `X-Flowie-Organization-Id`.
- **`search=` on `/v1/documents` is accepted but currently ignored.** Use the
  explicit filters (`companyId`, `type`, `status`, `from`, `to`, `amountMin`,
  `amountMax`) instead.

## Versioning and deprecation

Full policy: <https://docs.get-flowie.com/deprecation-policy>

The API is versioned in the URL path. `/v1` is current and stable; breaking
changes ship as a new path version rather than mutating an existing one, so a
client pinned to `/v1` keeps working. Additive changes (new optional fields, new
endpoints) land within a version — parse defensively and ignore fields you do
not recognise.

## Rate limits

Responses carry `X-RateLimit-Limit` and `X-RateLimit-Remaining`. On `429`,
honour `Retry-After` rather than retrying on a fixed timer. Sandbox bootstrap is
deliberately tighter than the rest of the API.

## Agent protocols

| Surface | URL |
|---|---|
| MCP — product, 40 tools | `https://back.flowie.ink/exchange/mcp` |
| MCP — documentation | `https://docs.get-flowie.com/mcp` |
| A2A — JSON-RPC 2.0 | `https://back.flowie.ink/exchange/a2a` |
| Agent Card | <https://docs.get-flowie.com/.well-known/agent-card.json> |
| Agent Skills index | <https://docs.get-flowie.com/.well-known/agent-skills/index.json> |
| AI catalog (ARD) | <https://docs.get-flowie.com/.well-known/ai-catalog.json> |
| API catalog (RFC 9727) | <https://docs.get-flowie.com/.well-known/api-catalog> |

## Machine-readable documentation

| Surface | URL |
|---|---|
| Page index for agents | <https://docs.get-flowie.com/llms.txt> |
| Full corpus, one file | <https://docs.get-flowie.com/llms-full.txt> |
| OpenAPI 3.1 | <https://docs.get-flowie.com/openapi.json> |
| Markdown twin of any page | append `.md` to its URL |
| Agent JSON view of any page | append `?mode=agent` |

## Authentication

Full walkthrough, including the OAuth 2.0 PKCE flow and the agent handoff:
<https://docs.get-flowie.com/auth.md>

To let an agent act on your account without handing over your API key, mint a
single-use, scoped, expiring link at <https://docs.get-flowie.com/share-access>.

## Support

Integration questions: support@flowie.fr (include the `X-Request-Id`).
Security disclosure: security@flowie.fr.
Status: <https://flowie.betteruptime.com/>
