API REFERENCE — REST v1

API Reference

Manage PostgreSQL databases, branches, computes, and more via REST. Base URL: https://api.lampion.cloud/v1/

Every request requires:

Authorization: Bearer lmp_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Create a key in Settings > API Keys.

CLI lampion projects list MCP AI Agents (Claude, Cursor)

§ 01 — Core

Authentication

All API requests require a Bearer token. Create an API key from Settings > API Keys in the console. Keys are scoped to your organization with developer permissions. Keys expire after 90 days by default. RBAC roles hierarchy: analyst < viewer < developer < admin/owner. Analysts can only access branches where anonymization is enabled and receive a dedicated connection string with masked data.

Projects

A project is a PostgreSQL database with branching, monitoring, and auto-suspend. Creating a project provisions a compute and returns a ready-to-use connection string. Deleting a project destroys nothing right away: it can be restored during a 7-day grace period, then it is permanently erased.

GET /v1/projects

List all projects.

Request

curl -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects

Response

[{"id":"abc123","name":"my-app","region":"fr-par-1"}]
POST /v1/projects

Create a project. Returns connection string, endpoint, password.

Request

curl -X POST -H "Authorization: Bearer $TOKEN"   -H "Content-Type: application/json" \
  -d '{"name":"my-app","region":"fr-par-1"}' https://api.lampion.cloud/v1/projects

Response

{"id":"abc123","name":"my-app","endpoint_id":"ep-abc",
 "connection_string":"postgresql://cloud_admin:[email protected]:5432/ep-abc.postgres?sslmode=require",
 "pg_password":"YaQYfbg...","host":"db.lampion.cloud","port":5432}
GET /v1/projects/{project_id}

Get a project by ID.

Request

curl -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}

Response

{"id":"abc123","name":"my-app","region":"fr-par-1"}
PATCH /v1/projects/{project_id}

Update a project (rename, change settings).

Request

curl -X PATCH -H "Authorization: Bearer $TOKEN"   -H "Content-Type: application/json" -d '{"name":"my-new-name"}' https://api.lampion.cloud/v1/projects/{id}

Response

{"id":"abc123","name":"my-new-name","region":"fr-par-1"}
DELETE /v1/projects/{project_id}

Delete a project (admin role). Deletion is not immediate: the project moves to `pending_deletion` for a 7-day grace period. During that period its computes are stopped, connections are refused, and the project disappears from listings (its routes return 404); it can still be restored. Once `purge_after` is reached, an hourly job permanently erases it: computes, branches, storage and related data. Returns 202 Accepted. Audit log: `project.deletion_requested`, then `project.deleted` on permanent erasure.

Request

curl -X DELETE -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}

Response

202 Accepted
{"id":"abc123","status":"pending_deletion",
 "deleted_at":"2026-10-14T09:12:00+00:00","purge_after":"2026-10-21T09:12:00+00:00"}
GET /v1/projects/deleted

List the organization's projects pending deletion, with the request date (`deleted_at`) and the permanent erasure date (`purge_after`). Admin role.

Request

curl -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/deleted

Response

[{"id":"abc123","name":"my-app",
  "deleted_at":"2026-10-14T09:12:00+00:00","purge_after":"2026-10-21T09:12:00+00:00"}]
POST /v1/projects/{project_id}/restore

Restore a project pending deletion (admin role). Returns the project, in the same shape as `GET /v1/projects/{project_id}`. Its computes stay suspended and wake on the next connection. 404 if the project is unknown, 409 if it is not pending deletion or if restoring it would exceed the plan's project or compute quota, 410 if the grace period is over. Audit log: `project.restored`.

Request

curl -X POST -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/restore

Response

{"id":"abc123","name":"my-app","region":"fr-par-1"}

Branches

Copy-on-write forks. Create in under a second for testing, staging, or CI. Seed SQL runs automatically on new branches. A branch keeps its id for life; the main branch's id is the project's id.

GET /v1/projects/{id}/branches

List all branches.

Request

curl -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/branches

Response

[{"id":"{id}","name":"main","is_primary":true},{"id":"feat","name":"staging"}]
POST /v1/projects/{id}/branches

Create a branch (fork). Provisions a new compute. Optional ttl_hours (1 to 720 h; 0 or omitted = no expiry, 400 out of bounds). The name must be unique within the project: 409 if it is already taken. A branch created from a masked branch inherits its anonymization (status and rules).

Request

curl -X POST -H "Authorization: Bearer $TOKEN"   -H "Content-Type: application/json" \
  -d '{"name":"staging","parent_id":"{id}","ttl_hours":24}' https://api.lampion.cloud/v1/projects/{id}/branches

Response

{"id":"feat","name":"staging","ttl_hours":24,"anon_enabled":false,"compute_id":"ep-new"}
PATCH /v1/projects/{id}/branches/{bid}

Update branch settings: auto-delete TTL (ttl_hours from 1 to 720 h, 0 or null clears it, 400 out of bounds) and protected status. When the TTL expires, the branch is deleted just like with DELETE: compute, data and metadata.

Request

curl -X PATCH -H "Authorization: Bearer $TOKEN"   -H "Content-Type: application/json" -d '{"ttl_hours":24,"protected":true}' https://api.lampion.cloud/v1/projects/{id}/branches/{bid}

Response

{"id":"feat","name":"staging","ttl_hours":24,"protected":true}
POST .../{bid}/reset

Reset a branch to its parent's current state (like git reset --hard). The branch gets fresh data and a new compute, and keeps its id and settings; nothing changes if the reset fails.

Request

curl -X POST -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/branches/{bid}/reset

Response

{"id":"feat","name":"staging","compute_id":"ep-new2"}
POST .../{bid}/merge

Merge schema changes (DDL only) from this branch to the parent. Use dry_run=true to preview SQL.

Request

curl -X POST -H "Authorization: Bearer $TOKEN"   -H "Content-Type: application/json" \
  -d '{"dry_run":true}' https://api.lampion.cloud/v1/projects/{id}/branches/{bid}/merge

Response

{"success":true,"dry_run":true,
 "migration_sql":"ALTER TABLE users ADD COLUMN avatar TEXT;",
 "changes":{"total_changes":1},"duration_ms":0}
DELETE /v1/projects/{id}/branches/{bid}

Delete a branch and its compute.

Request

curl -X DELETE -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/branches/{bid}

Response

204 No Content
POST .../{bid}/promote

Promote a branch to main: main takes the branch's current data and keeps its id. Destructive: main's previous data and compute are replaced. Requires the admin role.

Request

curl -X POST -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/branches/{bid}/promote

Response

{"success":true,"promoted_from":"staging",
 "new_main":{"id":"{id}","name":"main","is_primary":true}}
POST .../migration-preview

Preview the migration SQL between a branch and its parent, without applying anything.

Request

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"branch_id":"feat"}' https://api.lampion.cloud/v1/projects/{id}/migration-preview

Response

{"migration_sql":"ALTER TABLE users ADD COLUMN avatar TEXT;",
 "changes":{"total_changes":1}}

Endpoints (Computes)

PostgreSQL compute instances. Suspend/resume, resize live, configure auto-suspend, manage IP allowlists.

GET /v1/projects/{id}/endpoints/{eid}

Get a single endpoint by ID (status, connection string, settings).

Request

curl -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/endpoints/{eid}

Response

{"id":"ep-abc","status":"running","connection_string":"postgresql://...","auto_suspend_seconds":300,"compute_cu":0.25}
GET /v1/projects/{id}/endpoints

List endpoints with their connection strings. The cloud_admin password (pg_password, and the one embedded in connection_string) is only returned to developer roles and above; viewer and analyst receive null and the masked form ********.

Request

curl -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/endpoints

Response

[{"id":"ep-abc","status":"running",
  "connection_string":"postgresql://cloud_admin:********@db.lampion.cloud:5432/ep-abc.postgres?sslmode=require",
  "pg_password":null}]
// viewer / analyst : masque. developer et au-dessus : valeur en clair.
POST .../{eid}/suspend

Suspend (scale to zero).

Request

curl -X POST -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/endpoints/{eid}/suspend

Response

{"id":"ep-abc","status":"suspended"}
POST .../{eid}/resume

Resume a suspended compute.

Request

curl -X POST -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/endpoints/{eid}/resume

Response

{"id":"ep-abc","status":"running"}
PATCH .../{eid}

Update settings (auto_suspend_seconds). Duration in seconds; 0 = never suspend (paid plans only); negative values are rejected.

Request

curl -X PATCH -H "Authorization: Bearer $TOKEN"   -H "Content-Type: application/json" -d '{"auto_suspend_seconds":600}' https://api.lampion.cloud/v1/projects/{id}/endpoints/{eid}

Response

{"id":"ep-abc","auto_suspend_seconds":600}
GET .../{eid}/allowlist

Get IP allowlist.

Request

curl -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/endpoints/{eid}/allowlist

Response

{"cidrs":["10.0.0.0/8"],"allow_console_access":true}
PUT .../{eid}/allowlist

Replace IP allowlist.

Request

curl -X PUT -H "Authorization: Bearer $TOKEN"   -H "Content-Type: application/json" -d '{"allowlist":["10.0.0.0/8"]}' https://api.lampion.cloud/v1/projects/{id}/endpoints/{eid}/allowlist

Response

{"cidrs":["10.0.0.0/8"],"allow_console_access":true}
GET /v1/projects/{id}/endpoints/compute-sizes

List available compute sizes (CU tiers), with the max_connections actually applied (100 to 3357).

Request

curl -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/endpoints/compute-sizes

Response

[{"cu":0.25,"label":"0.25 CU","vcpu":0.25,"memory_gb":0.5,"shared_buffers_mb":64,"max_connections":100},{"cu":1,"label":"1 CU","vcpu":1,"memory_gb":4,"shared_buffers_mb":512,"max_connections":419},{"cu":4,"label":"4 CU","vcpu":4,"memory_gb":16,"shared_buffers_mb":2048,"max_connections":1678}]
PATCH .../{eid}

Change the compute size (compute_cu, one of the compute-sizes tiers; 1 CU = 1 vCPU + 4 GiB). The compute is resized right away, live and without dropping a connection whenever possible: any increase, and a moderate decrease. Otherwise it restarts briefly at the new size; a suspended compute picks it up on its next wake-up. The resize_method field of the response tells what happened: in_place (live), restart (short restart) or deferred (applied at the next start). 409 if capacity is short for now: the current size is kept, try again later. Autoscaling bounds min_cu/max_cu: compute-sizes tiers, min_cu ≤ max_cu and max_cu ≤ 8 × min_cu, 0 or below clears the bound — validated and stored now for automatic autoscaling, in preparation. 400 if a value is invalid, 403 if your plan is locked to 0.25 CU, 502 on an internal error. A rejected request changes nothing.

Request

curl -X PATCH -H "Authorization: Bearer $TOKEN"   -H "Content-Type: application/json" \
  -d '{"compute_cu":2,"min_cu":0.5,"max_cu":4}' https://api.lampion.cloud/v1/projects/{id}/endpoints/{eid}

Response

{"id":"ep-abc","compute_cu":2,"min_cu":0.5,"max_cu":4,"resize_method":"in_place"}

§ 02 — SQL & Schema

SQL Execution

Execute queries via the API. Supports multi-statement scripts and psql meta-commands.

POST .../{eid}/sql

Execute SQL. Returns columns, rows, duration.

Request

curl -X POST -H "Authorization: Bearer $TOKEN"   -H "Content-Type: application/json" \
  -d '{"query":"SELECT * FROM users LIMIT 5"}' https://api.lampion.cloud/v1/projects/{id}/endpoints/{eid}/sql

Response

{"columns":["id","name"],"rows":[{"id":1,"name":"Alice"}],"duration":12}

Schema Introspection

Browse databases, schemas, tables, and columns.

GET /v1/projects/{id}/schema

No params = databases. ?database=X = schemas. ?database=X&schema=Y = tables + columns.

Request

curl -H "Authorization: Bearer $TOKEN" "https://api.lampion.cloud/v1/projects/{id}/schema?database=postgres&schema=public"

Response

{"type":"tables","items":[{"name":"users","columns":[{"name":"id","type":"integer"},{"name":"email","type":"text"}]}]}

Databases

CRUD PostgreSQL databases within an endpoint.

GET .../{eid}/databases

List databases.

Request

curl -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/endpoints/{eid}/databases

Response

[{"name":"postgres","encoding":"UTF8","size_bytes":8945664}]
POST .../{eid}/databases

Create a database.

Request

curl -X POST -H "Authorization: Bearer $TOKEN"   -H "Content-Type: application/json" -d '{"name":"myapp"}' https://api.lampion.cloud/v1/projects/{id}/endpoints/{eid}/databases

Response

{"name":"myapp"}
DELETE .../{eid}/databases/{name}

Drop a database.

Request

curl -X DELETE -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/endpoints/{eid}/databases/myapp

Response

204 No Content

Roles

Manage PostgreSQL roles.

GET .../{eid}/roles

List roles.

Request

curl -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/endpoints/{eid}/roles

Response

[{"name":"cloud_admin","superuser":true,"can_login":true,
  "createdb":true,"connection_limit":-1,"password":null}]
// password : renseigne pour cloud_admin a partir du role developer.
POST .../{eid}/roles

Create a role. Optional password (16 to 128 characters, roles with can_login only, 422 out of bounds); without it, a password is generated and returned once. A provided password is never returned. On a branch with anonymization enabled, the role gets the MASKED label (masked: true) and only sees masked data; if the label cannot be set, the role is not created (502).

Request

curl -X POST -H "Authorization: Bearer $TOKEN"   -H "Content-Type: application/json" -d '{"name":"appuser","can_login":true}' https://api.lampion.cloud/v1/projects/{id}/endpoints/{eid}/roles

Response

{"name":"appuser","can_login":true,"superuser":false,
 "password":"genere-visible-une-seule-fois","masked":false}
DELETE .../{eid}/roles/{name}

Drop a role.

Request

curl -X DELETE -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/endpoints/{eid}/roles/appuser

Response

204 No Content
POST .../{eid}/roles/{name}/reset-password

Generate a new password for a role. Visible ONCE in the response.

Request

curl -X POST -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/endpoints/{eid}/roles/appuser/reset-password

Response

{"name":"appuser","password":"new-generated-password-xyz"}

Permissions

Manage table-level privileges (GRANT/REVOKE). Supported privileges: SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER, ALL.

GET .../{eid}/permissions

List table-level grants for the endpoint.

Request

curl -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/endpoints/{eid}/permissions

Response

[{"table":"public.users","role":"appuser","privileges":["SELECT","INSERT","UPDATE"]},{"table":"public.orders","role":"appuser","privileges":["SELECT"]}]
GET .../{eid}/permissions/tables

List available tables for granting permissions.

Request

curl -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/endpoints/{eid}/permissions/tables

Response

[{"table_schema":"public","table_name":"users"},
 {"table_schema":"public","table_name":"orders"}]
POST .../{eid}/permissions/grant

Grant privileges on a table to a role.

Request

curl -X POST -H "Authorization: Bearer $TOKEN"   -H "Content-Type: application/json" \
  -d '{"role":"appuser","table_schema":"public","table_name":"users","privileges":["SELECT","INSERT"]}' \
  https://api.lampion.cloud/v1/projects/{id}/endpoints/{eid}/permissions/grant

Response

{"status":"granted","privileges":["SELECT","INSERT"],"target":"users","role":"appuser"}
POST .../{eid}/permissions/revoke

Revoke privileges on a table from a role.

Request

curl -X POST -H "Authorization: Bearer $TOKEN"   -H "Content-Type: application/json" \
  -d '{"role":"appuser","table_schema":"public","table_name":"users","privileges":["INSERT"]}' \
  https://api.lampion.cloud/v1/projects/{id}/endpoints/{eid}/permissions/revoke

Response

{"status":"revoked","privileges":["INSERT"],"target":"users","role":"appuser"}

Tables (DDL)

Create, drop, and alter tables and columns via the API. All operations execute DDL statements on the target endpoint.

POST .../{eid}/tables

Create a table with columns (name, type, primary key, NOT NULL).

Request

curl -X POST -H "Authorization: Bearer $TOKEN"   -H "Content-Type: application/json" \
  -d '{"name":"orders","columns":[{"name":"id","type":"serial","primary_key":true},{"name":"total","type":"numeric","nullable":false}]}' \
  https://api.lampion.cloud/v1/projects/{id}/endpoints/{eid}/tables

Response

{"name":"orders","schema":"public","columns":2}
DELETE .../{eid}/tables/{table}

Drop a table. Irreversible.

Request

curl -X DELETE -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/endpoints/{eid}/tables/orders

Response

204 No Content
POST .../{eid}/tables/{table}/rename

Rename a table.

Request

curl -X POST -H "Authorization: Bearer $TOKEN"   -H "Content-Type: application/json" \
  -d '{"new_name":"customer_orders"}' https://api.lampion.cloud/v1/projects/{id}/endpoints/{eid}/tables/orders/rename

Response

{"old_name":"orders","new_name":"customer_orders"}
POST .../{eid}/tables/{table}/columns

Add a column to a table.

Request

curl -X POST -H "Authorization: Bearer $TOKEN"   -H "Content-Type: application/json" \
  -d '{"name":"status","type":"text","nullable":true,"default":"'pending'"}' \
  https://api.lampion.cloud/v1/projects/{id}/endpoints/{eid}/tables/orders/columns

Response

{"column":"status","type":"text"}
DELETE .../{eid}/tables/{table}/columns/{col}

Drop a column from a table.

Request

curl -X DELETE -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/endpoints/{eid}/tables/orders/columns/status

Response

204 No Content
POST .../{eid}/tables/{table}/columns/rename

Rename a column.

Request

curl -X POST -H "Authorization: Bearer $TOKEN"   -H "Content-Type: application/json" \
  -d '{"old_name":"total","new_name":"total_amount"}' \
  https://api.lampion.cloud/v1/projects/{id}/endpoints/{eid}/tables/orders/columns/rename

Response

{"old_name":"total","new_name":"total_amount"}
PATCH .../{eid}/tables/{table}/columns/{col}

Alter a column (type, nullable, default).

Request

curl -X PATCH -H "Authorization: Bearer $TOKEN"   -H "Content-Type: application/json" \
  -d '{"column":"total","new_type":"numeric(10,2)","set_nullable":false,"set_default":"0"}' \
  https://api.lampion.cloud/v1/projects/{id}/endpoints/{eid}/tables/orders/columns/total

Response

{"table":"orders","column":"total","changes":2}

Extensions

Install and manage PostgreSQL extensions.

GET .../{eid}/extensions

List extensions.

Request

curl -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/endpoints/{eid}/extensions

Response

[{"name":"plpgsql","default_version":"1.0","installed_version":"1.0","comment":"PL/pgSQL"},
 {"name":"pgvector","default_version":"0.7.0","installed_version":null,"comment":"vector types"}]
POST .../{eid}/extensions

Install an extension.

Request

curl -X POST -H "Authorization: Bearer $TOKEN"   -H "Content-Type: application/json" -d '{"name":"pgvector"}' https://api.lampion.cloud/v1/projects/{id}/endpoints/{eid}/extensions

Response

{"name":"pgvector","default_version":"0.7.0","installed_version":"0.7.0","comment":"vector types"}
DELETE .../{eid}/extensions/{name}

Uninstall an extension.

Request

curl -X DELETE -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/endpoints/{eid}/extensions/pgvector

Response

204 No Content

§ 03 — Data Management

Database Seeds

Attach up to 10 ordered SQL scripts per project. They run automatically on every new branch — test data, fixtures, extensions. Reorder, enable/disable individually.

GET /v1/projects/{id}/seeds

List all seed scripts for this project.

Request

curl -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/seeds

Response

[{"id":"seed-1","name":"fixtures","sql":"INSERT INTO ...","position":1,"enabled":true}]
POST /v1/projects/{id}/seeds

Create a new seed script.

Request

curl -X POST -H "Authorization: Bearer $TOKEN"   -H "Content-Type: application/json" \
  -d '{"name":"fixtures","sql":"INSERT INTO users (name) VALUES (\'Alice\');"}' \
  https://api.lampion.cloud/v1/projects/{id}/seeds

Response

{"id":"seed-1","name":"fixtures","position":1,"enabled":true}
PATCH /v1/projects/{id}/seeds/{seed_id}

Update a seed (name, sql, enabled).

Request

curl -X PATCH -H "Authorization: Bearer $TOKEN"   -H "Content-Type: application/json" \
  -d '{"enabled":false}' https://api.lampion.cloud/v1/projects/{id}/seeds/{seed_id}

Response

{"id":"seed-1","enabled":false}
DELETE /v1/projects/{id}/seeds/{seed_id}

Delete a seed script.

Request

curl -X DELETE -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/seeds/{seed_id}

Response

204 No Content
POST /v1/projects/{id}/seeds/reorder

Reorder seed scripts.

Request

curl -X POST -H "Authorization: Bearer $TOKEN"   -H "Content-Type: application/json" \
  -d '{"ids":["seed-2","seed-1","seed-3"]}' https://api.lampion.cloud/v1/projects/{id}/seeds/reorder

Response

{"ok":true}
GET /v1/projects/{id}/seed

Read the project legacy seed — a single script, predating the ordered seeds above. Returns an empty string when none is set.

Request

curl -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/seed

Response

{"seed_sql":"CREATE EXTENSION IF NOT EXISTS pgvector;"}
PUT /v1/projects/{id}/seed

Set or clear that legacy seed. Send `null` to clear it.

Request

curl -X PUT -H "Authorization: Bearer $TOKEN"   -H "Content-Type: application/json"   -d '{"seed_sql":"CREATE EXTENSION IF NOT EXISTS pgvector;"}'   https://api.lampion.cloud/v1/projects/{id}/seed

Response

{"seed_sql":"CREATE EXTENSION IF NOT EXISTS pgvector;"}

Query Replay

Capture top queries from one branch (via pg_stat_statements) and replay them on another to detect performance regressions after migrations.

POST /v1/projects/{id}/replay

Replay top N queries from source on target. Returns timing comparison with regression detection.

Request

curl -X POST -H "Authorization: Bearer $TOKEN"   -H "Content-Type: application/json" \
  -d '{"source_endpoint_id":"ep-main","target_endpoint_id":"ep-staging","limit":20}' \
  https://api.lampion.cloud/v1/projects/{id}/replay

Response

{"queries":[{"query":"SELECT...","source_mean_ms":1.2,"target_mean_ms":3.8,"ratio":3.17,"status":"regression"}],"summary":{"total":20,"regressions":2,"improvements":5,"stable":13}}

Backups & PITR

Snapshot your database at any point. Restore to a new branch without touching production.

GET /v1/projects/{id}/backups

List backup snapshots.

Request

curl -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/backups

Response

[{"id":"bk-42","name":"before-migration","branch_id":"main-tid","lsn":"0/15A2C08","created_at":"2026-04-01T10:00:00Z"}]
GET /v1/projects/{id}/backups/{bid}

Get a backup by ID.

Request

curl -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/backups/{bid}

Response

{"id":"bk-42","name":"before-migration","lsn":"0/15A2C08"}
POST /v1/projects/{id}/backups

Create a backup snapshot.

Request

curl -X POST -H "Authorization: Bearer $TOKEN"   -H "Content-Type: application/json" \
  -d '{"name":"before-migration","branch_id":"main-tid"}' https://api.lampion.cloud/v1/projects/{id}/backups

Response

{"id":"bk-42","name":"before-migration","lsn":"0/15A2C08"}
DELETE /v1/projects/{id}/backups/{bid}

Delete a backup.

Request

curl -X DELETE -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/backups/{bid}

Response

204 No Content
POST /v1/projects/{id}/backups/{bid}/restore

Restore to a new branch at this LSN.

Request

curl -X POST -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/backups/{bid}/restore

Response

{"id":"tl-restored","project_id":"abc123","name":"restored-bk-42",
 "restored_from_backup":"bk-42","lsn":"0/15A2C08","compute_id":"ep-new"}

Database Export

Export your database in multiple formats via pg_dump. Filterable by database or table. Three formats: plain SQL (.sql), custom compressed (.dump for pg_restore), and CSV (single table export).

GET .../{eid}/dump

Download database export. ?format=plain|custom|csv (default: plain). ?database=X&table=Y for single table. CSV format requires table param.

Request

curl -H "Authorization: Bearer $TOKEN" "https://api.lampion.cloud/v1/projects/{id}/endpoints/{eid}/dump?format=plain" -o dump.sql

Response

-- SQL dump saved to dump.sql
GET .../{eid}/dump

Export as custom format (compressed, for pg_restore).

Request

curl -H "Authorization: Bearer $TOKEN" "https://api.lampion.cloud/v1/projects/{id}/endpoints/{eid}/dump?format=custom" -o dump.dump

Response

-- Binary dump saved to dump.dump (restore with pg_restore)
GET .../{eid}/dump

Export a single table as CSV (COPY TO STDOUT).

Request

curl -H "Authorization: Bearer $TOKEN" "https://api.lampion.cloud/v1/projects/{id}/endpoints/{eid}/dump?format=csv&database=postgres&table=users" -o users.csv

Response

-- CSV saved to users.csv
GET .../{eid}/export

Full export of the endpoint as a `.tar.gz` archive: a manifest carrying the SHA-256 fingerprint of each file, the roles (without passwords) and one custom-format pg_dump file per database. Minimum role `developer`. CLI equivalent: `lampion export`.

Request

curl -H "Authorization: Bearer $TOKEN" -o export.tar.gz "https://api.lampion.cloud/v1/projects/{id}/endpoints/{eid}/export"
# CLI
lampion export <pid> <eid>

Response

HTTP/1.1 200 OK
Content-Type: application/gzip
-- export.tar.gz: manifest (SHA-256 per file) + roles (no passwords)
-- + one pg_dump custom-format file per database (restore with pg_restore)

Read Replicas

Add read-only replicas to any branch. Each replica has its own connection string and can be suspended independently.

GET /v1/projects/{id}/branches/{bid}/replicas

List replicas for a branch.

Request

curl -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/branches/{bid}/replicas

Response

[{"id":"rep-1","status":"running","connection_string":"postgresql://...","type":"read_only"}]
POST /v1/projects/{id}/branches/{bid}/replicas

Create a read replica.

Request

curl -X POST -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/branches/{bid}/replicas

Response

{"id":"rep-1","status":"running","connection_string":"postgresql://...","type":"read_only"}
DELETE .../{rid}

Delete a replica.

Request

curl -X DELETE -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/branches/{bid}/replicas/{rid}

Response

204 No Content
POST .../{rid}/suspend

Suspend a replica.

Request

curl -X POST -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/branches/{bid}/replicas/{rid}/suspend

Response

{"id":"rep-1","status":"suspended"}
POST .../{rid}/resume

Resume a suspended replica.

Request

curl -X POST -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/branches/{bid}/replicas/{rid}/resume

Response

{"id":"rep-1","status":"running"}

Database Import

Import an external PostgreSQL database into a new branch via pg_dump | psql. Validates the source, checks extensions compatibility, and creates the branch automatically.

POST /v1/projects/{id}/import/validate

Validate source DSN: test connection, check PG version, size, extensions compatibility.

Request

curl -X POST -H "Authorization: Bearer $TOKEN"   -H "Content-Type: application/json" \
  -d '{"source_dsn":"postgresql://user:pass@host:5432/mydb"}' \
  https://api.lampion.cloud/v1/projects/{id}/import/validate

Response

{"ok":true,"errors":[],"source":{"pg_version":"17.5","size_mb":142,"table_count":12,"extensions":[{"name":"pgvector","version":"0.8.0","available_on_target":true}]}}
POST /v1/projects/{id}/import/start

Start the import. Creates a new branch and pipes pg_dump | psql from the source DSN.

Request

curl -X POST -H "Authorization: Bearer $TOKEN"   -H "Content-Type: application/json" \
  -d '{"source_dsn":"postgresql://user:pass@host:5432/mydb","branch_name":"imported"}' \
  https://api.lampion.cloud/v1/projects/{id}/import/start

Response

{"branch_id":"imp-tid","branch_name":"imported","compute_id":"ep-imp",
 "restore_stats":{"tables":12},"extensions_installed":["pgvector"],"extensions_skipped":[]}
// Appel synchrone : la reponse arrive une fois l'import termine.

§ 04 — Security & Privacy

PII Masking (Anonymization)

Dynamically mask sensitive columns on a branch using postgresql_anonymizer. Enable per branch (never on production: refused with a 400 on the primary branch), define rules per column, choose from a strict allowlist of masking functions. When enabled, a PostgreSQL role lampion_analyst with MASKED label is auto-created. Users with the analyst RBAC role get a dedicated analyst_connection_string that connects as lampion_analyst and sees only anonymized data. That field is exposed by GET /v1/projects/{id}/endpoints, not by the anonymization routes. Roles created after enabling are masked too, and a branch created from a masked branch inherits the masking.

GET .../branches/{bid}/anonymization

Get anonymization status and active rules.

Request

curl -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/branches/{bid}/anonymization

Response

{"enabled":true,"rules":[{"id":"r-1","schema_name":"public","table_name":"users","column_name":"email","masking_function":"anon.fake_email()"}]}
POST .../anonymization/enable

Enable dynamic masking on this branch. Installs the anon extension, applies all rules, and creates a lampion_analyst PostgreSQL role with MASKED label. The matching analyst_connection_string then becomes available on GET /v1/projects/{id}/endpoints. 400 on the primary branch.

Request

curl -X POST -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/branches/{bid}/anonymization/enable

Response

{"enabled":true}
POST .../anonymization/disable

Disable masking and remove all security labels.

Request

curl -X POST -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/branches/{bid}/anonymization/disable

Response

{"enabled":false}
GET .../anonymization/functions

List allowed masking functions (allowlist anti-injection).

Request

curl -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/branches/{bid}/anonymization/functions

Response

[{"function":"anon.fake_email()","description":"Fake email address"},{"function":"anon.fake_iban()","description":"Fake IBAN"},{"function":"anon.hash({COL})","description":"SHA256 hash"}]
GET .../anonymization/rules

List masking rules for this branch.

Request

curl -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/branches/{bid}/anonymization/rules

Response

[{"id":"r-1","schema_name":"public","table_name":"users","column_name":"email","masking_function":"anon.fake_email()"}]
POST .../anonymization/rules

Add a masking rule. If anonymization is enabled, the rule is applied immediately; if it cannot be (missing column, unreachable compute), it is not saved and the API returns 502. 400 on the primary branch.

Request

curl -X POST -H "Authorization: Bearer $TOKEN"   -H "Content-Type: application/json" \
  -d '{"table_name":"users","column_name":"email","masking_function":"anon.fake_email()"}' \
  https://api.lampion.cloud/v1/projects/{id}/branches/{bid}/anonymization/rules

Response

{"id":"r-1","schema_name":"public","table_name":"users","column_name":"email","masking_function":"anon.fake_email()"}
DELETE .../anonymization/rules/{rule_id}

Delete a masking rule. Removes the security label live if enabled.

Request

curl -X DELETE -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/branches/{bid}/anonymization/rules/{rule_id}

Response

204 No Content

§ 05 — Observability

Metrics & Usage

Real-time metrics and monthly usage for billing.

GET /v1/projects/{id}/metrics

Live: connections, cache ratio, storage, CPU, memory.

Request

curl -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/metrics

Response

{"connections_total":5,"cache_hit_ratio":98.5,"storage_logical_mb":42.3,"compute_cpu_seconds":123.4}
GET /v1/projects/{id}/metrics/history

Historical metrics (24h max, every 30s).

Request

curl -H "Authorization: Bearer $TOKEN" "https://api.lampion.cloud/v1/projects/{id}/metrics/history?hours=6"

Response

[{"snapshot_at":"...","connections_total":3,"storage_logical_mb":42.1}]
GET /v1/projects/{id}/usage

Monthly: compute hours, storage GB, transfer GB.

Request

curl -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/usage

Response

{"compute_hours":12.5,"storage_gb":0.042,"transfer_total_gb":0.001,"period":"2026-03"}
GET /v1/usage

Org-wide usage with plan info and cost estimation.

Request

curl -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/usage

Response

{"plan":{"name":"startup"},"total":{"compute_hours":25},"estimated_cost":{"total_eur":2.50}}
GET /v1/projects/{id}/metrics/compute-history

Compute usage history (suspend/resume events).

Request

curl -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/metrics/compute-history

Response

[{"id":"csl-1","project_id":"abc123","endpoint_id":"ep-abc",
  "state":"running","trigger":"resume","created_at":"2026-09-20T10:00:00Z"}]
GET /v1/projects/{id}/metrics/vacuum

Vacuum and autovacuum statistics per table.

Request

curl -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/metrics/vacuum

Response

{"tables":[{"schema":"public","table":"users","live_tuples":1200,"dead_tuples":42,
   "dead_pct":3.4,"last_autovacuum":"2026-09-19T22:00:00Z","autovacuum_count":3}],
 "transaction_id":{"oldest_xid_age":120,"wraparound_pct":0.01,"warning":false}}

Query Analysis

Slow query dashboard via pg_stat_statements. Top queries by total time, mean time, or call count.

GET .../{eid}/analyse/slow-queries

Top slow queries. ?order_by=total_time|mean_time|calls&limit=30

Request

curl -H "Authorization: Bearer $TOKEN" "https://api.lampion.cloud/v1/projects/{id}/endpoints/{eid}/analyse/slow-queries?order_by=mean_time"

Response

[{"query":"SELECT...","calls":150,"mean_time_ms":12.3,"total_time_ms":1845,"cache_hit_pct":98.5}]
POST .../{eid}/analyse/reset-stats

Reset all pg_stat_statements counters.

Request

curl -X POST -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/endpoints/{eid}/analyse/reset-stats

Response

{"ok":true}

Logs

PostgreSQL server logs.

GET .../{eid}/logs

Tail PG logs. ?lines=N (default 200, max 5000).

Request

curl -H "Authorization: Bearer $TOKEN" "https://api.lampion.cloud/v1/projects/{id}/endpoints/{eid}/logs?lines=50"

Response

{"lines":["2026-03-30 LOG: connection authorized"],"count":50}

Project Events

Activity feed for a project: project, endpoint and branch creation. Derived from the current state of branches rather than from an audit log — the 20 most recent events, no pagination, and a deletion leaves no trace. For a complete, timestamped record, see the organisation audit log.

GET /v1/projects/{id}/events

List the 20 most recent project events, newest first.

Request

curl -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/projects/{id}/events

Response

[{"id":"ev-a1b2c3d4","project_id":"abc123","type":"branch.created",
   "message":"Branch staging created","created_at":"2026-09-20T14:02:11+00:00"},
 {"id":"ev-e5f6a7b8-ep","project_id":"abc123","type":"endpoint.created",
   "message":"Endpoint created on branch main","created_at":"2026-09-18T09:41:02+00:00"}]

§ 06 — Organization

Webhooks

HTTP notifications on events. Payloads signed HMAC-SHA256.

GET /v1/orgs/webhooks

List webhooks.

Request

curl -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/orgs/webhooks

Response

[{"id":"wh-abc","url":"https://...","events":["*"],"enabled":true}]
POST /v1/orgs/webhooks

Create webhook. Returns signing secret.

Request

curl -X POST -H "Authorization: Bearer $TOKEN"   -H "Content-Type: application/json" \
  -d '{"url":"https://hook.example.com","events":["project.created"]}' https://api.lampion.cloud/v1/orgs/webhooks

Response

{"id":"wh-abc","secret":"a1b2c3...","events":["project.created"]}
PATCH /v1/orgs/webhooks/{id}

Update webhook.

Request

curl -X PATCH -H "Authorization: Bearer $TOKEN"   -H "Content-Type: application/json" -d '{"enabled":false}' https://api.lampion.cloud/v1/orgs/webhooks/{id}

Response

{"id":"wh-abc","enabled":false}
DELETE /v1/orgs/webhooks/{id}

Delete webhook.

Request

curl -X DELETE -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/orgs/webhooks/{id}

Response

204 No Content

Members & Invitations

Manage organization members, invite collaborators, transfer ownership, delete the organization (restorable for 7 days). Roles: owner, admin, developer, viewer, analyst. The analyst role restricts access to branches with anonymization enabled — analysts see only masked data via a dedicated connection string.

GET /v1/orgs/members

List organization members.

Request

curl -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/orgs/members

Response

[{"id":"u-1","email":"[email protected]","role":"owner"},{"id":"u-2","email":"[email protected]","role":"developer"},{"id":"u-3","email":"[email protected]","role":"analyst"}]
PATCH /v1/orgs/members/{uid}/role

Change a member's role. Valid roles: owner, admin, developer, viewer, analyst.

Request

curl -X PATCH -H "Authorization: Bearer $TOKEN"   -H "Content-Type: application/json" -d '{"role":"analyst"}' https://api.lampion.cloud/v1/orgs/members/{uid}/role

Response

{"id":"u-3","email":"[email protected]","name":"Carol","org_id":"org-1","role":"analyst"}
DELETE /v1/orgs/members/{uid}

Remove a member from the organization.

Request

curl -X DELETE -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/orgs/members/{uid}

Response

204 No Content
POST /v1/orgs/transfer-ownership

Transfer ownership to another member.

Request

curl -X POST -H "Authorization: Bearer $TOKEN"   -H "Content-Type: application/json" -d '{"new_owner_id":"u-2"}' https://api.lampion.cloud/v1/orgs/transfer-ownership

Response

{"ok":true}
GET /v1/orgs/invitations

List pending invitations.

Request

curl -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/orgs/invitations

Response

[{"id":"inv-1","email":"[email protected]","role":"developer","status":"pending"}]
POST /v1/orgs/invitations

Invite a user by email.

Request

curl -X POST -H "Authorization: Bearer $TOKEN"   -H "Content-Type: application/json" \
  -d '{"email":"[email protected]","role":"developer"}' https://api.lampion.cloud/v1/orgs/invitations

Response

{"id":"inv-1","email":"[email protected]","role":"developer","status":"pending"}
DELETE /v1/orgs/invitations/{inv_id}

Cancel a pending invitation.

Request

curl -X DELETE -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/orgs/invitations/{inv_id}

Response

204 No Content
DELETE /v1/orgs

Delete the organization and all its data (GDPR): the target is the token's organization (for an API key, the key's). No body. Deletion is not immediate: the organization and all its projects move to `pending_deletion` for a 7-day grace period. During that period computes are stopped, connections are refused, and every other API call for this organization returns 403 `"Organization is pending deletion"`, except restore and status. Once `purge_after` is reached, an hourly job permanently erases every project (branches, computes, storage, data), then the webhooks, API keys, invitations, audit log and memberships. Returns 202 Accepted. Reserved to the `owner` (403 for any other role, `admin` included). Audit log: `org.deletion_requested`, then `org.deleted` on permanent erasure.

Request

curl -X DELETE -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/orgs

Response

202 Accepted
{"id":"org-1","status":"pending_deletion",
 "deleted_at":"2026-10-14T09:12:00+00:00","purge_after":"2026-10-21T09:12:00+00:00"}
POST /v1/orgs/restore

Restore the organization during the grace period. The projects deleted along with it are restored too (`restored_projects`); projects deleted individually before it stay pending deletion. Reserved to the `owner`. 409 if the organization is not pending deletion, 410 if the grace period is over. Audit log: `org.restored`.

Request

curl -X POST -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/orgs/restore

Response

{"id":"org-1","name":"Acme","status":"active","restored_projects":["abc123","def456"]}
GET /v1/orgs/status

Organization status: `active` or `pending_deletion`, with the deletion request date (`deleted_at`) and the permanent erasure date (`purge_after`). Open to any role, including during the grace period.

Request

curl -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/orgs/status

Response

{"id":"org-1","name":"Acme","status":"pending_deletion",
 "deleted_at":"2026-10-14T09:12:00+00:00","purge_after":"2026-10-21T09:12:00+00:00"}

API Keys

Manage API keys for your organization. Keys use the lmp_live_ prefix and have developer-level permissions.

GET /v1/api-keys

List API keys (truncated values).

Request

curl -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/api-keys

Response

[{"id":"key-1","name":"CI/CD","key_prefix":"lmp_live_abc...","created_at":"2026-04-01T10:00:00Z"}]
POST /v1/api-keys

Create a new API key. The full key is returned only once.

Request

curl -X POST -H "Authorization: Bearer $TOKEN"   -H "Content-Type: application/json" -d '{"name":"CI/CD"}' https://api.lampion.cloud/v1/api-keys

Response

{"id":"key-1","name":"CI/CD","key_value":"lmp_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}
// key_value : visible une seule fois, a la creation.
DELETE /v1/api-keys/{key_id}

Revoke an API key.

Request

curl -X DELETE -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/api-keys/{key_id}

Response

204 No Content

Audit Log

Each organization has a timestamped audit log, kept for 12 months: console actions on projects, branches, API keys, members, roles and anonymization, plus full endpoint exports. Available to admin and owner roles.

GET /v1/orgs/audit-log

List audit events. ?limit=N&offset=N for pagination.

Request

curl -H "Authorization: Bearer $TOKEN" "https://api.lampion.cloud/v1/orgs/audit-log?limit=10"

Response

[{"id":"al-1","action":"project.created","user_email":"[email protected]",
  "resource":"project","resource_id":"my-app","ip_address":"203.0.113.4",
  "created_at":"2026-04-01T10:00:00Z"}]

Account

Preferences and lifecycle of the authenticated account: language, "What's new" emails, address confirmation, deletion. These routes act on the account behind the token — for an API key, the account of its creator.

PATCH /v1/auth/me/locale

Change the account language — `fr` or `en`. Any other value is rejected.

Request

curl -X PATCH -H "Authorization: Bearer $TOKEN"   -H "Content-Type: application/json"   -d '{"locale":"en"}' https://api.lampion.cloud/v1/auth/me/locale

Response

{"id":"usr_a1b2c3","locale":"en"}
GET /v1/auth/me/email-preferences

Read the "What's new" email subscription (`marketing_emails`). Service emails (maintenance, changes to the terms) do not depend on this preference. 404 if the account cannot be found.

Request

curl -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/auth/me/email-preferences

Response

{"marketing_emails":true}
PATCH /v1/auth/me/email-preferences

Subscribe to or unsubscribe from "What's new" emails. Body: `marketing_emails` (boolean, required, otherwise 422). Every change is recorded, to keep proof of your choice. The unsubscribe link at the bottom of those emails has the same effect, without signing in. 404 if the account cannot be found.

Request

curl -X PATCH -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"marketing_emails":false}' https://api.lampion.cloud/v1/auth/me/email-preferences

Response

{"marketing_emails":false}
POST /v1/auth/me/resend-verification

Resend the confirmation link for the account email address. Stays reachable while the address is unconfirmed: it is the way out of the block. `alreadyVerified: true` if the address is already confirmed (nothing is sent). At most 3 requests per hour (429 beyond, with a `Retry-After` header), 502 if the email could not be sent: the failure is reported, never hidden.

Request

curl -X POST -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/auth/me/resend-verification

Response

{"ok":true,"alreadyVerified":false}
DELETE /v1/auth/me

Permanently delete your account (GDPR article 17, right to erasure). Your API keys, organization memberships, received invitations and beta access requests are deleted; your identity is removed from the audit log and from the invitations you sent, which remain in anonymized form. `purged` counts the affected rows per table. Your organizations are not deleted (see `DELETE /v1/orgs`). 400 if you are the sole `owner` of an organization that still has projects: delete them or transfer ownership first. Irreversible.

Request

curl -X DELETE -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/auth/me

Response

{"ok":true,"purged":{"api_keys":1,"org_memberships":1,
 "audit_log_anonymized":12,"console_users":1}}

§ 07 — Infrastructure

Data Residency

Proof of where your data physically resides. Region, datacenter, provider, host certifications (distinct from those held by Lampion), encryption per layer as it is actually configured. Exportable as a timestamped PDF carrying a SHA-256 fingerprint of its content (versioned format) and an Ed25519 signature of that fingerprint, so anyone can check the document has not been altered and was issued by Lampion (public keys: `GET /v1/compliance/signing-keys`).

GET /v1/projects/{id}/residency

Get full data residency report for a project. Each entry of `data_layers` carries a `label` field (human-readable name). Parameter locale (`fr` or `en`, default `en`): localizes the layers' `label`, `description` and encryption values.

Request

curl -H "Authorization: Bearer $TOKEN" "https://api.lampion.cloud/v1/projects/{id}/residency?locale=fr"

Response

{"region_id":"fr-par-1","region":{"city":"Paris","provider":"Scaleway","datacenter":"DC2","certifications":["ISO 27001","HDS"]},"data_layers":[...],"compliance":{"data_in_country":"France"}}
GET /v1/projects/{id}/residency.pdf

Project residency report as a timestamped PDF. The SHA-256 fingerprint printed in the footer is also returned in the `X-Lampion-Report-Digest` header, and its Ed25519 signature in the `X-Lampion-Report-Signature` header. Parameter locale (`fr` or `en`). 404 if the project does not belong to your organisation, 503 if PDF export is unavailable on the server.

Request

curl -H "Authorization: Bearer $TOKEN" -o residency.pdf "https://api.lampion.cloud/v1/projects/{id}/residency.pdf?locale=fr"

Response

HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Disposition: attachment; filename="lampion-residency-{id}-2026-10-14.pdf"
X-Lampion-Report-Digest: sha256:3f9a…
X-Lampion-Report-Signature: alg=Ed25519;key_id=9b1c4e0a7d2f6835;value=…

Compliance

What you need to answer a security questionnaire or your DPO without asking us. Readable by any organisation member: nothing in it is secret. The sub-processor list shows which ones actually see your data (`in_use`, based on your projects' regions). The questionnaire is a knowledge base: the `md` output is a single document meant to be given to your AI assistant, and it carries its own instructions — the assistant must respect each answer's status (`yes`, `no`, `partial`, `planned`) and never present a `planned` item as available. The DPA (data processing agreement, GDPR article 28) is accepted online on behalf of the company: any member can read its status and download the certificate, but accepting it is reserved to the organisation `owner` (an `admin` gets 403), since it legally binds the company. It is deliberately not exposed to the MCP (Model Context Protocol) server: an AI assistant must not be able to sign a contract on your behalf.

GET /v1/orgs/compliance/subprocessors

List sub-processors (GDPR article 28(2)): registry version, change notice period (30 days), regions used by the organisation, and for each one purpose, location, data processed, transfer outside the EU. Parameter locale (`fr` or `en`).

Request

curl -H "Authorization: Bearer $TOKEN" "https://api.lampion.cloud/v1/orgs/compliance/subprocessors?locale=en"

Response

{"version":"2026-10-14","notice_period_days":30,"regions_in_use":["fr-par-1"],
 "subprocessors":[{"id":"scaleway","name":"Scaleway","entity":"Scaleway SAS","country_code":"FR",
   "scope":"global","outside_eu":false,"transfer_mechanism":null,"purpose":"Cloud hosting: ...",
   "location":"France (Paris region)","data":"Account data; ...","in_use":true},
  {"id":"resend","name":"Resend","entity":"Plus Five Five, Inc.","country_code":"US","outside_eu":true,
   "transfer_mechanism":"EU-U.S. Data Privacy Framework (self-certification) + Standard Contractual Clauses (...)",
   "source":"https://resend.com/legal/dpa","location":"USA","in_use":true, ...},
  {"id":"ovhcloud","name":"OVH Cloud","scope":"fr-gra-1","in_use":false, ...}, ...]}
GET /v1/orgs/compliance/questionnaire

Security questionnaire for the organisation, each answer with its status and sources. Parameters locale (`fr` or `en`) and format: `json` (default), `md` (single document with instructions for an AI) or `csv` (columns id, category, status, question, answer, evidence).

Request

curl -H "Authorization: Bearer $TOKEN" \
  "https://api.lampion.cloud/v1/orgs/compliance/questionnaire?locale=en&format=md" -o lampion-security.md

Response

{"version":"...","locale":"en","org_id":"org_a1b2c3","usage":"...",
 "entries":[{"id":"dpa","category":"gdpr","category_label":"GDPR and subprocessing","status":"yes",
   "question":"...","answer":"...","evidence":["https://lampion.cloud/dpa"]}, ...]}
GET /v1/orgs/compliance/residency

Residency report for the whole organisation: countries, regions, hosting provider, datacenter and provider certifications, data layers, projects and branches per region, sub-processors actually in use, `digest` (SHA-256 fingerprint of the canonical content, identical to the PDF's) and `signature` (`alg`: `Ed25519`, `key_id`: key identifier, `value`: base64-encoded Ed25519 signature of the `digest` string). Parameter locale (`fr` or `en`).

Request

curl -H "Authorization: Bearer $TOKEN" "https://api.lampion.cloud/v1/orgs/compliance/residency?locale=en"

Response

{"format_version":"3","scope":"org","locale":"en","generated_at":"2026-10-14T10:00:00+00:00",
 "org":{"id":"org_a1b2c3","name":"Acme"},"countries":["France"],"cross_region_replication":false,
 "lampion_certifications":[],"lampion_certifications_planned":"2027-Q1",
 "regions":[{"id":"fr-par-1","provider":"Scaleway","datacenter":"DC2",
   "provider_certifications":["ISO 27001","HDS"],
   "data_layers":[{"name":"compute","location":"DC2, Paris",
     "encryption_transit":"TLS 1.2 minimum enforced through the proxy",
     "encryption_rest":"Encryption at rest planned for Q1 2027"},
    {"name":"pageserver","location":"DC2, Paris",
     "encryption_transit":"Cluster-internal network (TLS not claimed)",
     "encryption_rest":"Encryption at rest planned for Q1 2027"}, ...],
   "projects":[{"id":"proj_x1","name":"shop","branches":["main","dev"]}]}],
 "subprocessors":[{"id":"scaleway","name":"Scaleway", ...}, ...],
 "digest":"sha256:3f9a…",
 "signature":{"alg":"Ed25519","key_id":"…","value":"…"}}
GET /v1/orgs/compliance/residency.pdf

The same report as a timestamped PDF, ready to hand to your DPO or a buyer as is. The fingerprint printed in the footer is also returned in the `X-Lampion-Report-Digest` header, and its Ed25519 signature in the `X-Lampion-Report-Signature` header. Parameter locale (`fr` or `en`). 503 if PDF export is unavailable on the server.

Request

curl -H "Authorization: Bearer $TOKEN" -o residency.pdf "https://api.lampion.cloud/v1/orgs/compliance/residency.pdf?locale=fr"

Response

HTTP/1.1 200 OK
Content-Type: application/pdf
X-Lampion-Report-Digest: sha256:3f9a…
X-Lampion-Report-Signature: alg=Ed25519;key_id=9b1c4e0a7d2f6835;value=…
GET /v1/orgs/compliance/dpa

DPA status for the organisation: current version (`current_version`), links to the text (`url.fr`, `url.en`), `accepted` and details of the acceptance of the current version (`acceptance`, otherwise `null`), `needs_reacceptance` (an earlier version was accepted but not the current one), sub-processor registry version and `subprocessors_changed_since_acceptance`, and the full acceptance history (`history`). Open to any member.

Request

curl -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/orgs/compliance/dpa

Response

{"current_version":"2026-10-18",
 "url":{"fr":"https://lampion.cloud/dpa","en":"https://lampion.cloud/en/dpa"},
 "accepted":true,
 "acceptance":{"id":"dpa-4f2a9c1e7b30","dpa_version":"2026-10-18","company_name":"Acme SAS",
   "company_registration":"RCS Paris 123 456 789","signer_name":"Jane Doe","signer_title":"CEO",
   "accepted_by_email":"[email protected]","accepted_at":"2026-10-18T10:00:00+00:00"},
 "needs_reacceptance":false,"subprocessors_version":"2026-10-14",
 "subprocessors_changed_since_acceptance":false,
 "history":[{"id":"dpa-4f2a9c1e7b30","dpa_version":"2026-10-18", ...}]}
POST /v1/orgs/compliance/dpa/accept

Accept the current DPA version on behalf of the company — reserved to the organisation `owner` (403 for any other role, `admin` included). Body: `dpa_version` (the version you read, which must be the current one, otherwise 409), `company_name`, `company_registration` (optional: company registration number), `signer_name`, `signer_title`. 201 on first acceptance, 200 if this version was already accepted (idempotent: the existing acceptance is returned as is), 422 if a required field is blank. Recorded in the audit log (action `dpa.accepted`).

Request

curl -X POST https://api.lampion.cloud/v1/orgs/compliance/dpa/accept \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"dpa_version":"2026-10-18","company_name":"Acme SAS",
       "company_registration":"RCS Paris 123 456 789",
       "signer_name":"Jane Doe","signer_title":"CEO"}'

Response

HTTP/1.1 201 Created
{"id":"dpa-4f2a9c1e7b30","dpa_version":"2026-10-18","company_name":"Acme SAS",
 "company_registration":"RCS Paris 123 456 789","signer_name":"Jane Doe","signer_title":"CEO",
 "accepted_by_email":"[email protected]","accepted_at":"2026-10-18T10:00:00+00:00"}
GET /v1/orgs/compliance/dpa/certificate.pdf

DPA acceptance certificate as a PDF: company, signer, version, date. Carries a SHA-256 fingerprint of its content, also returned in the `X-Lampion-Report-Digest` header. Parameters locale (`fr` or `en`) and version (default: the current version). 404 if this version has not been accepted by the organisation, 503 if PDF export is unavailable on the server. Open to any member.

Request

curl -H "Authorization: Bearer $TOKEN" -o dpa-certificate.pdf \
  "https://api.lampion.cloud/v1/orgs/compliance/dpa/certificate.pdf?locale=fr&version=2026-10-18"

Response

HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Disposition: attachment; filename="lampion-dpa-org_a1b2c3-v2026-10-18.pdf"
X-Lampion-Report-Digest: sha256:8c41…
X-Lampion-Report-Signature: alg=Ed25519;key_id=9b1c4e0a7d2f6835;value=…
GET /v1/compliance/signing-keys

Ed25519 public keys that sign residency reports, identified by `key_id`. Public endpoint, no authentication: a third party (your DPO, a buyer) can verify a report without a Lampion account. Verification: `signature.value`, base64-decoded, is the Ed25519 signature of the `digest` string by the key named in `signature.key_id`.

Request

# Public endpoint: no token
curl https://api.lampion.cloud/v1/compliance/signing-keys

Response

{"keys":[{"key_id":"9b1c4e0a7d2f6835","alg":"Ed25519",
  "public_key":"<base64, 32 raw bytes>",
  "pem":"-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----\n"}]}
// signature.value (base64) = Ed25519 signature of the UTF-8 "digest" string,
// made with the key whose id is signature.key_id.

Plans

Pricing plans.

GET /v1/plans

List plans with limits and pricing.

Request

curl -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/plans

Response

[{"name":"free","max_projects":3,"pricing":{"cu_hour_eur":0,"storage_gb_month_eur":0}},
 {"name":"startup","max_projects":1000,"pricing":{"cu_hour_eur":0.10,"storage_gb_month_eur":0.40}},
 {"name":"souverain","pricing":{"cu_hour_eur":0.176,"storage_gb_month_eur":0.40}}]

Billing

What your organisation consumes, and what has been billed. Every closed statement carries quantities as well as amounts, so you can answer "why this amount" without asking us. Admin role required — what a company spends is not operational data.

GET /v1/billing

Current period summary: subscription, credits (granted, consumed, balance, overage) and invoices.

Request

curl -H "Authorization: Bearer $TOKEN" https://api.lampion.cloud/v1/billing

Response

{"period":"2026-09","subscription":{"plan":"startup","status":"active"},
 "credits":{"granted_eur":0,"consumed_eur":19.0,"balance_eur":-19.0,"overage_eur":19.0,"pct_used":null},
 "invoices":[],"stripe_mode":"live"}
GET /v1/billing/periods

History of closed statements, newest first. Parameters limit (default 24, max 120) and offset.

Request

curl -H "Authorization: Bearer $TOKEN" "https://api.lampion.cloud/v1/billing/periods?limit=2"

Response

[{"period":"2026-08","status":"closed","plan_name":"startup",
   "compute_cu_hours":190.0,"storage_gb_month":12.4,"transfer_gb":3.1,
   "floor_eur":29.0,"usage_eur":23.96,"overage_eur":23.96,"total_eur":52.96,
   "closed_at":"2026-09-01T03:17:04+00:00","reported_at":"2026-09-01T03:17:05+00:00"}]