Français
Tables
Les routes sont relatives à <PUBLIC_BASE_URL> ; les corps de requête et de réponse sont en JSON sauf mention contraire. L’authentification, les portées, la pagination et le format des erreurs sont décrits dans les guides de l’API REST.
GET /api/v1/tables
Lister les tables
Toutes les tables de l’instance avec leurs colonnes et leur nombre de lignes. Les tables sont partagées par toute l’équipe.
Accès — Session de membre ou clé d’API portant tables:read.
Réponses
200 — Les tables.
| Champ | Type | Requis |
|---|---|---|
tables | object[] | oui |
Schéma JSON
json
{
"type": "object",
"properties": {
"tables": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": { "type": "string" },
"slug": {
"type": "string",
"minLength": 1,
"maxLength": 60,
"pattern": "^[a-z][a-z0-9_-]*$"
},
"name": { "type": "string", "minLength": 1, "maxLength": 120 },
"description": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"columns": {
"type": "array",
"items": {
"type": "object",
"properties": {
"key": {
"type": "string",
"minLength": 1,
"maxLength": 60,
"pattern": "^[a-z][a-z0-9_]*$"
},
"label": { "type": "string", "minLength": 1, "maxLength": 120 },
"type": {
"type": "string",
"enum": [
"text",
"number",
"boolean",
"date",
"datetime",
"select",
"email"
]
},
"isKey": { "type": "boolean" },
"required": { "type": "boolean" },
"options": {
"maxItems": 100,
"type": "array",
"items": { "type": "string", "minLength": 1, "maxLength": 200 }
},
"width": {
"anyOf": [
{ "type": "integer", "minimum": 80, "maximum": 800 },
{ "type": "null" }
]
},
"description": {
"anyOf": [ { "type": "string", "maxLength": 400 }, { "type": "null" } ]
}
},
"required": [
"key",
"label",
"type",
"isKey",
"required",
"options",
"width",
"description"
],
"additionalProperties": false
}
},
"keyUnique": { "type": "boolean" },
"rowCount": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 },
"createdAt": { "type": "string" },
"updatedAt": { "type": "string" }
},
"required": [
"id",
"slug",
"name",
"description",
"columns",
"keyUnique",
"rowCount",
"createdAt",
"updatedAt"
],
"additionalProperties": false
}
}
},
"required": [ "tables" ],
"additionalProperties": false
}401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
POST /api/v1/tables
Créer une table
Administrateurs seulement. Le slug est déduit du nom quand il est absent, et rendu unique. Les colonnes peuvent être déclarées d’emblée ; keyUnique (vrai par défaut) fait refuser les lignes dont la clé existe déjà.
Accès — Session de membre ou clé d’API portant tables:write.
Corps de la requête (application/json)
| Champ | Type | Requis |
|---|---|---|
name | string | oui |
slug | string | non |
description | string | null | non |
columns | object[] | non |
keyUnique | boolean | non |
Schéma JSON
json
{
"type": "object",
"properties": {
"name": { "type": "string", "minLength": 1, "maxLength": 120 },
"slug": {
"type": "string",
"minLength": 1,
"maxLength": 60,
"pattern": "^[a-z][a-z0-9_-]*$"
},
"description": { "anyOf": [ { "type": "string", "maxLength": 1000 }, { "type": "null" } ] },
"columns": {
"type": "array",
"items": {
"type": "object",
"properties": {
"key": {
"type": "string",
"minLength": 1,
"maxLength": 60,
"pattern": "^[a-z][a-z0-9_]*$"
},
"label": { "type": "string", "minLength": 1, "maxLength": 120 },
"type": {
"default": "text",
"type": "string",
"enum": [
"text",
"number",
"boolean",
"date",
"datetime",
"select",
"email"
]
},
"isKey": { "default": false, "type": "boolean" },
"required": { "default": false, "type": "boolean" },
"options": {
"default": [],
"maxItems": 100,
"type": "array",
"items": { "type": "string", "minLength": 1, "maxLength": 200 }
},
"description": {
"anyOf": [ { "type": "string", "maxLength": 400 }, { "type": "null" } ]
}
},
"required": [ "label" ]
}
},
"keyUnique": { "default": true, "type": "boolean" }
},
"required": [ "name" ]
}Réponses
201 — La table.
| Champ | Type | Requis |
|---|---|---|
table | object | oui |
Schéma JSON
json
{
"type": "object",
"properties": {
"table": {
"type": "object",
"properties": {
"id": { "type": "string" },
"slug": {
"type": "string",
"minLength": 1,
"maxLength": 60,
"pattern": "^[a-z][a-z0-9_-]*$"
},
"name": { "type": "string", "minLength": 1, "maxLength": 120 },
"description": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"columns": {
"type": "array",
"items": {
"type": "object",
"properties": {
"key": {
"type": "string",
"minLength": 1,
"maxLength": 60,
"pattern": "^[a-z][a-z0-9_]*$"
},
"label": { "type": "string", "minLength": 1, "maxLength": 120 },
"type": {
"type": "string",
"enum": [
"text",
"number",
"boolean",
"date",
"datetime",
"select",
"email"
]
},
"isKey": { "type": "boolean" },
"required": { "type": "boolean" },
"options": {
"maxItems": 100,
"type": "array",
"items": { "type": "string", "minLength": 1, "maxLength": 200 }
},
"width": {
"anyOf": [
{ "type": "integer", "minimum": 80, "maximum": 800 },
{ "type": "null" }
]
},
"description": {
"anyOf": [ { "type": "string", "maxLength": 400 }, { "type": "null" } ]
}
},
"required": [
"key",
"label",
"type",
"isKey",
"required",
"options",
"width",
"description"
],
"additionalProperties": false
}
},
"keyUnique": { "type": "boolean" },
"rowCount": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 },
"createdAt": { "type": "string" },
"updatedAt": { "type": "string" }
},
"required": [
"id",
"slug",
"name",
"description",
"columns",
"keyUnique",
"rowCount",
"createdAt",
"updatedAt"
],
"additionalProperties": false
}
},
"required": [ "table" ],
"additionalProperties": false
}400 — La requête ne respecte pas son schéma.
401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
Cette opération accepte un en-tête Idempotency-Key : rejouer la même requête avec la même clé rend la réponse d’origine au lieu d’agir deux fois. Voir Idempotence.
Codes d’erreur — request.bad_request, auth.forbidden, tables.limit_reached, tables.duplicate_slug, tables.duplicate_column. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.
Exemple de requête
json
{
"name": "Départements → consultants",
"columns": [
{ "label": "Département", "type": "text", "isKey": true, "required": true },
{ "label": "Consultant", "type": "email", "required": true }
]
}GET /api/v1/tables/limits
Lire les plafonds des tables
Les plafonds de l’instance : tables, colonnes par table, lignes par table, caractères par cellule. En atteindre un rend 409 tables.limit_reached.
Accès — Session de membre ou clé d’API portant tables:read.
Réponses
200 — Les plafonds.
| Champ | Type | Requis |
|---|---|---|
limits | object | oui |
Schéma JSON
json
{
"type": "object",
"properties": {
"limits": {
"type": "object",
"properties": {
"maxTables": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
},
"maxColumns": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
},
"maxRows": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
},
"maxCellChars": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
}
},
"required": [ "maxTables", "maxColumns", "maxRows", "maxCellChars" ],
"additionalProperties": false
}
},
"required": [ "limits" ],
"additionalProperties": false
}401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
GET /api/v1/tables/{id}
Lire une table
Par identifiant ou par slug. La structure seulement ; les lignes se lisent à part.
Accès — Session de membre ou clé d’API portant tables:read.
Paramètres
| Nom | Où | Type | Requis |
|---|---|---|---|
id | chemin | string | oui |
Réponses
200 — La table.
| Champ | Type | Requis |
|---|---|---|
table | object | oui |
Même schéma que POST /api/v1/tables.
401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
Codes d’erreur — tables.not_found. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.
PATCH /api/v1/tables/{id}
Modifier une table
Nom, slug, description, unicité de la clé. Administrateurs seulement. Partiel : seuls les champs présents changent.
Accès — Session de membre ou clé d’API portant tables:write.
Paramètres
| Nom | Où | Type | Requis |
|---|---|---|---|
id | chemin | string | oui |
Corps de la requête (application/json)
| Champ | Type | Requis |
|---|---|---|
name | string | non |
slug | string | non |
description | string | null | non |
keyUnique | boolean | non |
Schéma JSON
json
{
"type": "object",
"properties": {
"name": { "type": "string", "minLength": 1, "maxLength": 120 },
"slug": {
"type": "string",
"minLength": 1,
"maxLength": 60,
"pattern": "^[a-z][a-z0-9_-]*$"
},
"description": { "anyOf": [ { "type": "string", "maxLength": 1000 }, { "type": "null" } ] },
"keyUnique": { "type": "boolean" }
}
}Réponses
200 — La table.
| Champ | Type | Requis |
|---|---|---|
table | object | oui |
Même schéma que POST /api/v1/tables.
400 — La requête ne respecte pas son schéma.
401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
Codes d’erreur — request.bad_request, tables.not_found, auth.forbidden, tables.duplicate_slug. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.
DELETE /api/v1/tables/{id}
Supprimer une table
Administrateurs seulement. Les lignes partent avec elle. Lire usage d’abord : les workflows qui s’en servent ne sont pas arrêtés.
Accès — Session de membre ou clé d’API portant tables:write.
Paramètres
| Nom | Où | Type | Requis |
|---|---|---|---|
id | chemin | string | oui |
Réponses
204 — Supprimée.
401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
Codes d’erreur — tables.not_found, auth.forbidden. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.
POST /api/v1/tables/{id}/columns
Ajouter une colonne
Administrateurs seulement. La clé est déduite du libellé quand elle est absente. position l’insère à un rang donné ; ajoutée à la fin sinon. Les lignes existantes reçoivent une cellule vide.
Accès — Session de membre ou clé d’API portant tables:write.
Paramètres
| Nom | Où | Type | Requis |
|---|---|---|---|
id | chemin | string | oui |
Corps de la requête (application/json)
| Champ | Type | Requis |
|---|---|---|
key | string | non |
label | string | oui |
type | "text" | "number" | "boolean" | "date" | "datetime" | "select" | "email" | non |
isKey | boolean | non |
required | boolean | non |
options | string[] | non |
description | string | null | non |
position | integer | non |
Schéma JSON
json
{
"type": "object",
"properties": {
"key": {
"type": "string",
"minLength": 1,
"maxLength": 60,
"pattern": "^[a-z][a-z0-9_]*$"
},
"label": { "type": "string", "minLength": 1, "maxLength": 120 },
"type": {
"default": "text",
"type": "string",
"enum": [ "text", "number", "boolean", "date", "datetime", "select", "email" ]
},
"isKey": { "default": false, "type": "boolean" },
"required": { "default": false, "type": "boolean" },
"options": {
"default": [],
"maxItems": 100,
"type": "array",
"items": { "type": "string", "minLength": 1, "maxLength": 200 }
},
"description": { "anyOf": [ { "type": "string", "maxLength": 400 }, { "type": "null" } ] },
"position": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }
},
"required": [ "label" ]
}Réponses
200 — La table, avec la colonne.
| Champ | Type | Requis |
|---|---|---|
table | object | oui |
Même schéma que POST /api/v1/tables.
400 — La requête ne respecte pas son schéma.
401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
Cette opération accepte un en-tête Idempotency-Key : rejouer la même requête avec la même clé rend la réponse d’origine au lieu d’agir deux fois. Voir Idempotence.
Codes d’erreur — request.bad_request, tables.not_found, auth.forbidden, tables.limit_reached, tables.duplicate_column. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.
PATCH /api/v1/tables/{id}/columns/{key}
Modifier une colonne
Renommer, retyper, déplacer, changer les options ou les drapeaux. Administrateurs seulement. Un changement de type convertit d’abord toutes les cellules et est refusé en bloc (tables.conversion_failed, avec les cellules fautives) si l’une ne passe pas.
Accès — Session de membre ou clé d’API portant tables:write.
Paramètres
| Nom | Où | Type | Requis |
|---|---|---|---|
id | chemin | string | oui |
key | chemin | string | oui |
Corps de la requête (application/json)
| Champ | Type | Requis |
|---|---|---|
key | string | non |
label | string | non |
type | "text" | "number" | "boolean" | "date" | "datetime" | "select" | "email" | non |
isKey | boolean | non |
required | boolean | non |
options | string[] | non |
width | integer | null | non |
description | string | null | non |
position | integer | non |
force | boolean | non |
Schéma JSON
json
{
"type": "object",
"properties": {
"key": {
"type": "string",
"minLength": 1,
"maxLength": 60,
"pattern": "^[a-z][a-z0-9_]*$"
},
"label": { "type": "string", "minLength": 1, "maxLength": 120 },
"type": {
"type": "string",
"enum": [ "text", "number", "boolean", "date", "datetime", "select", "email" ]
},
"isKey": { "type": "boolean" },
"required": { "type": "boolean" },
"options": {
"maxItems": 100,
"type": "array",
"items": { "type": "string", "minLength": 1, "maxLength": 200 }
},
"width": {
"anyOf": [
{ "type": "integer", "minimum": 80, "maximum": 800 },
{ "type": "null" }
]
},
"description": { "anyOf": [ { "type": "string", "maxLength": 400 }, { "type": "null" } ] },
"position": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 },
"force": { "default": false, "type": "boolean" }
}
}Réponses
200 — La table, mise à jour.
| Champ | Type | Requis |
|---|---|---|
table | object | oui |
Même schéma que POST /api/v1/tables.
400 — La requête ne respecte pas son schéma.
401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
Codes d’erreur — request.bad_request, tables.not_found, auth.forbidden, tables.unknown_column, tables.duplicate_column, tables.conversion_failed. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.
DELETE /api/v1/tables/{id}/columns/{key}
Retirer une colonne
Administrateurs seulement. Ses cellules disparaissent de toutes les lignes. La dernière colonne d’une table ne se retire pas.
Accès — Session de membre ou clé d’API portant tables:write.
Paramètres
| Nom | Où | Type | Requis |
|---|---|---|---|
id | chemin | string | oui |
key | chemin | string | oui |
Réponses
200 — La table, sans la colonne.
| Champ | Type | Requis |
|---|---|---|
table | object | oui |
Même schéma que POST /api/v1/tables.
401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
Codes d’erreur — tables.not_found, auth.forbidden, tables.unknown_column, tables.last_column. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.
GET /api/v1/tables/{id}/rows
Lister les lignes
Filtrées (q sur les cellules, conditions filter combinées par match), triées par une colonne, paginées par offset et limit (500 au plus, offset plafonné). total compte les lignes filtrées, totalUnfiltered la table. Les auteurs sont résolus en noms.
Accès — Session de membre ou clé d’API portant tables:read.
Paramètres
| Nom | Où | Type | Requis |
|---|---|---|---|
id | chemin | string | oui |
q | requête | string | non |
filter | requête | string | non |
match | requête | "all" | "any" | non |
sort | requête | string | non |
dir | requête | "asc" | "desc" | non |
offset | requête | integer | non |
limit | requête | integer | non |
Réponses
200 — Une page de lignes.
| Champ | Type | Requis |
|---|---|---|
rows | object[] | oui |
total | integer | oui |
totalUnfiltered | integer | oui |
Schéma JSON
json
{
"type": "object",
"properties": {
"rows": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": { "type": "string" },
"data": {
"type": "object",
"propertyNames": { "type": "string" },
"additionalProperties": {
"anyOf": [
{ "type": "string" },
{ "type": "number" },
{ "type": "boolean" },
{ "type": "null" }
]
}
},
"createdAt": { "type": "string" },
"updatedAt": { "type": "string" },
"createdBy": {
"type": "object",
"properties": {
"kind": {
"type": "string",
"enum": [ "member", "workflow", "import", "unknown" ]
},
"id": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"label": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }
},
"required": [ "kind", "id", "label" ],
"additionalProperties": false
},
"updatedBy": {
"type": "object",
"properties": {
"kind": {
"type": "string",
"enum": [ "member", "workflow", "import", "unknown" ]
},
"id": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"label": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }
},
"required": [ "kind", "id", "label" ],
"additionalProperties": false
}
},
"required": [ "id", "data", "createdAt", "updatedAt", "createdBy", "updatedBy" ],
"additionalProperties": false
}
},
"total": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 },
"totalUnfiltered": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }
},
"required": [ "rows", "total", "totalUnfiltered" ],
"additionalProperties": false
}400 — La requête ne respecte pas son schéma.
401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
Codes d’erreur — request.bad_request, tables.not_found. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.
POST /api/v1/tables/{id}/rows
Ajouter une ligne
Tout membre. values est indexé par clé de colonne ; chaque valeur est convertie dans le type de sa colonne, et tous les refus sont rendus ensemble dans details.rejections. Une clé en double sur une table keyUnique rend 409.
Accès — Session de membre ou clé d’API portant tables:write.
Paramètres
| Nom | Où | Type | Requis |
|---|---|---|---|
id | chemin | string | oui |
Corps de la requête (application/json)
| Champ | Type | Requis |
|---|---|---|
values | object | oui |
Schéma JSON
json
{
"type": "object",
"properties": {
"values": {
"type": "object",
"propertyNames": { "type": "string" },
"additionalProperties": {
"anyOf": [
{ "type": "string" },
{ "type": "number" },
{ "type": "boolean" },
{ "type": "null" }
]
}
}
},
"required": [ "values" ]
}Réponses
201 — La ligne.
| Champ | Type | Requis |
|---|---|---|
row | object | oui |
Schéma JSON
json
{
"type": "object",
"properties": {
"row": {
"type": "object",
"properties": {
"id": { "type": "string" },
"data": {
"type": "object",
"propertyNames": { "type": "string" },
"additionalProperties": {
"anyOf": [
{ "type": "string" },
{ "type": "number" },
{ "type": "boolean" },
{ "type": "null" }
]
}
},
"createdAt": { "type": "string" },
"updatedAt": { "type": "string" },
"createdBy": {
"type": "object",
"properties": {
"kind": {
"type": "string",
"enum": [ "member", "workflow", "import", "unknown" ]
},
"id": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"label": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }
},
"required": [ "kind", "id", "label" ],
"additionalProperties": false
},
"updatedBy": {
"type": "object",
"properties": {
"kind": {
"type": "string",
"enum": [ "member", "workflow", "import", "unknown" ]
},
"id": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"label": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }
},
"required": [ "kind", "id", "label" ],
"additionalProperties": false
}
},
"required": [ "id", "data", "createdAt", "updatedAt", "createdBy", "updatedBy" ],
"additionalProperties": false
}
},
"required": [ "row" ],
"additionalProperties": false
}400 — La requête ne respecte pas son schéma.
401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
Cette opération accepte un en-tête Idempotency-Key : rejouer la même requête avec la même clé rend la réponse d’origine au lieu d’agir deux fois. Voir Idempotence.
Codes d’erreur — request.bad_request, tables.not_found, tables.limit_reached, tables.duplicate_key, tables.invalid_value, tables.required_value, tables.unknown_column. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.
Exemple de requête
json
{ "values": { "departement": "Nord", "consultant": "alice@example.test" } }PATCH /api/v1/tables/{id}/rows/{rowId}
Modifier les cellules d’une ligne
Partiel : seules les cellules présentes changent. expectedUpdatedAt protège d’une modification concurrente : si la ligne a changé depuis cette date, 409 tables.row_conflict et rien n’est écrit.
Accès — Session de membre ou clé d’API portant tables:write.
Paramètres
| Nom | Où | Type | Requis |
|---|---|---|---|
id | chemin | string | oui |
rowId | chemin | string | oui |
Corps de la requête (application/json)
| Champ | Type | Requis |
|---|---|---|
values | object | oui |
expectedUpdatedAt | string | non |
Schéma JSON
json
{
"type": "object",
"properties": {
"values": {
"type": "object",
"propertyNames": { "type": "string" },
"additionalProperties": {
"anyOf": [
{ "type": "string" },
{ "type": "number" },
{ "type": "boolean" },
{ "type": "null" }
]
}
},
"expectedUpdatedAt": { "type": "string" }
},
"required": [ "values" ]
}Réponses
200 — La ligne.
| Champ | Type | Requis |
|---|---|---|
row | object | oui |
Même schéma que POST /api/v1/tables/{id}/rows.
400 — La requête ne respecte pas son schéma.
401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
Codes d’erreur — request.bad_request, tables.not_found, tables.duplicate_key, tables.row_conflict, tables.invalid_value, tables.required_value, tables.unknown_column. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.
POST /api/v1/tables/{id}/rows/delete
Supprimer des lignes
Jusqu’à 500 lignes par identifiant, dans un corps. La réponse rend les lignes supprimées telles qu’elles étaient, pour que restore puisse annuler le geste sans corbeille côté serveur. Les identifiants inconnus sont ignorés.
Accès — Session de membre ou clé d’API portant tables:write.
Paramètres
| Nom | Où | Type | Requis |
|---|---|---|---|
id | chemin | string | oui |
Corps de la requête (application/json)
| Champ | Type | Requis |
|---|---|---|
rowIds | string[] | oui |
Schéma JSON
json
{
"type": "object",
"properties": {
"rowIds": {
"minItems": 1,
"maxItems": 500,
"type": "array",
"items": { "type": "string", "minLength": 1 }
}
},
"required": [ "rowIds" ]
}Réponses
200 — Le compte et les lignes restaurables.
| Champ | Type | Requis |
|---|---|---|
deleted | integer | oui |
restorable | object[] | oui |
Schéma JSON
json
{
"type": "object",
"properties": {
"deleted": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 },
"restorable": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": { "type": "string" },
"data": {
"type": "object",
"propertyNames": { "type": "string" },
"additionalProperties": {
"anyOf": [
{ "type": "string" },
{ "type": "number" },
{ "type": "boolean" },
{ "type": "null" }
]
}
},
"createdAt": { "type": "string" },
"updatedAt": { "type": "string" },
"createdBy": {
"type": "object",
"properties": {
"kind": {
"type": "string",
"enum": [ "member", "workflow", "import", "unknown" ]
},
"id": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"label": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }
},
"required": [ "kind", "id", "label" ],
"additionalProperties": false
},
"updatedBy": {
"type": "object",
"properties": {
"kind": {
"type": "string",
"enum": [ "member", "workflow", "import", "unknown" ]
},
"id": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"label": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }
},
"required": [ "kind", "id", "label" ],
"additionalProperties": false
}
},
"required": [ "id", "data", "createdAt", "updatedAt", "createdBy", "updatedBy" ],
"additionalProperties": false
}
}
},
"required": [ "deleted", "restorable" ],
"additionalProperties": false
}400 — La requête ne respecte pas son schéma.
401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
Cette opération accepte un en-tête Idempotency-Key : rejouer la même requête avec la même clé rend la réponse d’origine au lieu d’agir deux fois. Voir Idempotence.
Codes d’erreur — request.bad_request, tables.not_found. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.
POST /api/v1/tables/{id}/rows/restore
Restaurer des lignes supprimées
Réinsère des lignes rendues par rows/delete, avec leurs identifiants d’origine. Une ligne qui existe de nouveau, ou dont la clé est maintenant prise, est sautée ; le plafond de lignes arrête la restauration. restored compte ce qui est revenu.
Accès — Session de membre ou clé d’API portant tables:write.
Paramètres
| Nom | Où | Type | Requis |
|---|---|---|---|
id | chemin | string | oui |
Corps de la requête (application/json)
| Champ | Type | Requis |
|---|---|---|
rows | object[] | oui |
Schéma JSON
json
{
"type": "object",
"properties": {
"rows": {
"minItems": 1,
"maxItems": 500,
"type": "array",
"items": {
"type": "object",
"properties": {
"id": { "type": "string", "minLength": 1 },
"values": {
"type": "object",
"propertyNames": { "type": "string" },
"additionalProperties": {
"anyOf": [
{ "type": "string" },
{ "type": "number" },
{ "type": "boolean" },
{ "type": "null" }
]
}
}
},
"required": [ "id", "values" ]
}
}
},
"required": [ "rows" ]
}Réponses
200 — Combien de lignes sont revenues.
| Champ | Type | Requis |
|---|---|---|
restored | integer | oui |
Schéma JSON
json
{
"type": "object",
"properties": {
"restored": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }
},
"required": [ "restored" ],
"additionalProperties": false
}400 — La requête ne respecte pas son schéma.
401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
Cette opération accepte un en-tête Idempotency-Key : rejouer la même requête avec la même clé rend la réponse d’origine au lieu d’agir deux fois. Voir Idempotence.
Codes d’erreur — request.bad_request, tables.not_found, tables.invalid_value, tables.required_value, tables.unknown_column. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.
POST /api/v1/tables/{id}/import/preview
Prévisualiser un import CSV
Lit un CSV ou un collage, détecte le séparateur, propose une correspondance entre colonnes du fichier et colonnes de la table et rend des lignes d’exemple. Ne change rien.
Accès — Session de membre ou clé d’API portant tables:read.
Paramètres
| Nom | Où | Type | Requis |
|---|---|---|---|
id | chemin | string | oui |
Corps de la requête (application/json)
| Champ | Type | Requis |
|---|---|---|
csv | string | oui |
delimiter | "," | ";" | "\t" | "auto" | non |
hasHeader | boolean | non |
Schéma JSON
json
{
"type": "object",
"properties": {
"csv": { "type": "string", "minLength": 1, "maxLength": 4194304 },
"delimiter": { "default": "auto", "type": "string", "enum": [ ",", ";", "\t", "auto" ] },
"hasHeader": { "default": true, "type": "boolean" }
},
"required": [ "csv" ]
}Réponses
200 — La correspondance proposée et les exemples.
| Champ | Type | Requis |
|---|---|---|
columns | string[] | oui |
sample | string[][] | oui |
suggestedMapping | object | oui |
rowCount | integer | oui |
delimiter | "," | ";" | "\t" | oui |
Schéma JSON
json
{
"type": "object",
"properties": {
"columns": { "type": "array", "items": { "type": "string" } },
"sample": {
"type": "array",
"items": { "type": "array", "items": { "type": "string" } }
},
"suggestedMapping": {
"type": "object",
"propertyNames": { "type": "string" },
"additionalProperties": {
"type": "string",
"minLength": 1,
"maxLength": 60,
"pattern": "^[a-z][a-z0-9_]*$"
}
},
"rowCount": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 },
"delimiter": { "type": "string", "enum": [ ",", ";", "\t" ] }
},
"required": [ "columns", "sample", "suggestedMapping", "rowCount", "delimiter" ],
"additionalProperties": false
}400 — La requête ne respecte pas son schéma.
401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
Codes d’erreur — request.bad_request, tables.not_found, tables.invalid_csv. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.
POST /api/v1/tables/{id}/import
Importer des lignes depuis un CSV
Écrit les lignes mappées ; les conflits de clé suivent onConflict, et la réponse compte lignes créées, mises à jour et sautées avec la raison de chaque saut. truncate vide d’abord la table et exige le rôle administrateur. Les colonnes du fichier mappées vers des colonnes inconnues sont ignorées ; s’il n’en reste aucune, 400.
Accès — Session de membre ou clé d’API portant tables:write.
Paramètres
| Nom | Où | Type | Requis |
|---|---|---|---|
id | chemin | string | oui |
Corps de la requête (application/json)
| Champ | Type | Requis |
|---|---|---|
csv | string | oui |
delimiter | "," | ";" | "\t" | "auto" | non |
hasHeader | boolean | non |
mapping | object | oui |
onConflict | "skip" | "update" | "replace" | "append" | oui |
truncate | boolean | non |
Schéma JSON
json
{
"type": "object",
"properties": {
"csv": { "type": "string", "minLength": 1, "maxLength": 4194304 },
"delimiter": { "default": "auto", "type": "string", "enum": [ ",", ";", "\t", "auto" ] },
"hasHeader": { "default": true, "type": "boolean" },
"mapping": {
"type": "object",
"propertyNames": { "type": "string" },
"additionalProperties": {
"type": "string",
"minLength": 1,
"maxLength": 60,
"pattern": "^[a-z][a-z0-9_]*$"
}
},
"onConflict": { "type": "string", "enum": [ "skip", "update", "replace", "append" ] },
"truncate": { "default": false, "type": "boolean" }
},
"required": [ "csv", "mapping", "onConflict" ]
}Réponses
200 — Le bilan de l’import.
| Champ | Type | Requis |
|---|---|---|
created | integer | oui |
updated | integer | oui |
deleted | integer | oui |
skipped | object[] | oui |
Schéma JSON
json
{
"type": "object",
"properties": {
"created": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 },
"updated": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 },
"deleted": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 },
"skipped": {
"type": "array",
"items": {
"type": "object",
"properties": {
"row": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
},
"reason": {
"type": "string",
"enum": [
"missing_required",
"invalid_value",
"missing_key",
"duplicate",
"row_limit"
]
},
"column": {
"anyOf": [
{
"type": "string",
"minLength": 1,
"maxLength": 60,
"pattern": "^[a-z][a-z0-9_]*$"
},
{ "type": "null" }
]
}
},
"required": [ "row", "reason", "column" ],
"additionalProperties": false
}
}
},
"required": [ "created", "updated", "deleted", "skipped" ],
"additionalProperties": false
}400 — La requête ne respecte pas son schéma.
401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
Cette opération accepte un en-tête Idempotency-Key : rejouer la même requête avec la même clé rend la réponse d’origine au lieu d’agir deux fois. Voir Idempotence.
Codes d’erreur — request.bad_request, tables.not_found, auth.forbidden, tables.invalid_csv, tables.unknown_column. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.
GET /api/v1/tables/{id}/export.csv
Exporter une table en CSV
La table entière, RFC 4180, séparateur point-virgule et BOM UTF-8 pour qu’un tableur français l’ouvre correctement. Servie en téléchargement, nommée d’après le slug.
Accès — Session de membre ou clé d’API portant tables:read.
Paramètres
| Nom | Où | Type | Requis |
|---|---|---|---|
id | chemin | string | oui |
Réponses
200 — Le fichier CSV.
Type de contenu : text/csv
401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
Codes d’erreur — tables.not_found. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.
GET /api/v1/tables/{id}/usage
Quels workflows utilisent une table
Les workflows dont des nœuds lisent ou écrivent cette table, avec, pour chacun, s’il est publié et s’il écrit — renommer une colonne sous un nœud qui écrit perd des données.
Accès — Session de membre ou clé d’API portant tables:read.
Paramètres
| Nom | Où | Type | Requis |
|---|---|---|---|
id | chemin | string | oui |
Réponses
200 — Les usages.
| Champ | Type | Requis |
|---|---|---|
usages | object[] | oui |
Schéma JSON
json
{
"type": "object",
"properties": {
"usages": {
"type": "array",
"items": {
"type": "object",
"properties": {
"workflowId": { "type": "string" },
"workflowName": { "type": "string" },
"published": { "type": "boolean" },
"nodeTypes": { "type": "array", "items": { "type": "string" } },
"writes": { "type": "boolean" }
},
"required": [ "workflowId", "workflowName", "published", "nodeTypes", "writes" ],
"additionalProperties": false
}
}
},
"required": [ "usages" ],
"additionalProperties": false
}401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
Codes d’erreur — tables.not_found. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.