
# Vue d'ensemble des enregistrements

Chaque table que vous déclarez expose automatiquement une API REST complète pour ses enregistrements. Il n'y a aucun résolveur à écrire ni aucun point de terminaison à enregistrer — dès qu'une table existe dans votre configuration, sa collection `records` est accessible sous `/api/tables/:tableId/records`. Cette page documente la surface d'API partagée : la structure des URL, l'enveloppe de réponse, les métadonnées d'auteur et les règles transversales (authentification, permissions, mise en forme) que tout point de terminaison d'enregistrements respecte.

Les enregistrements sont les lignes d'une [table](tables-overview). Les tables définissent les colonnes (champs) ; les enregistrements contiennent les valeurs. L'API des enregistrements est le chemin canonique de lecture/écriture de ces données — les pages l'affichent, les formulaires y écrivent, les automatisations y réagissent et les intégrations externes la consomment.

## Surface des points de terminaison

`:tableId` accepte soit l'`id` numérique de la table, soit son `name`/slug. Tous les points de terminaison acceptent et renvoient du JSON.

| Méthode et chemin                                                          | Description                                                                                         |
| -------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| `POST /api/tables/:tableId/records`                                        | Créer un enregistrement unique                                                                      |
| `GET /api/tables/:tableId/records`                                         | Lister les enregistrements (pagination, tri, filtre, sélection de champs, regroupement, agrégation) |
| `GET /api/tables/:tableId/records/:recordId`                               | Lire un enregistrement unique par ID                                                                |
| `PATCH /api/tables/:tableId/records/:recordId`                             | Mettre à jour un enregistrement unique (partiel)                                                    |
| `DELETE /api/tables/:tableId/records/:recordId`                            | Supprimer (réversible) un enregistrement (`?permanent=true` pour suppression définitive)            |
| `POST /api/tables/:tableId/records/upsert`                                 | Créer ou mettre à jour selon des champs de correspondance                                           |
| `POST /api/tables/:tableId/records/batch`                                  | Création en lot                                                                                     |
| `PATCH /api/tables/:tableId/records/batch`                                 | Mise à jour en lot                                                                                  |
| `DELETE /api/tables/:tableId/records/batch`                                | Suppression (réversible) en lot                                                                     |
| `POST /api/tables/:tableId/records/:recordId/restore`                      | Restaurer un enregistrement supprimé de façon réversible                                            |
| `POST /api/tables/:tableId/records/batch/restore`                          | Restauration en lot                                                                                 |
| `GET /api/tables/:tableId/records/:recordId/history`                       | Historique des modifications d'un enregistrement                                                    |
| `GET\|POST\|PATCH\|DELETE /api/tables/:tableId/records/:recordId/comments` | Commentaires d'un enregistrement                                                                    |
| `GET /api/tables/:tableId/trash`                                           | Parcourir les enregistrements supprimés de façon réversible (vue corbeille)                         |
| `GET /api/tables/:tableSlug/subscribe`                                     | Abonnement WebSocket en temps réel                                                                  |

Le comportement détaillé est réparti sur des pages dédiées : [CRUD et upsert](records-crud), [filtrage, tri et pagination](records-filtering-sorting), [opérations en lot](records-batch), [historique et commentaires](record-history), [suppression réversible et corbeille](records-soft-delete), [abonnements en temps réel](records-realtime) et [import/export](records-import-export).

## L'enveloppe `fields`

Les corps d'écriture d'enregistrements utilisent l'enveloppe canonique de style Airtable : un objet `fields` associant les noms de champs à leurs valeurs.

```json
POST /api/tables/contacts/records
{
  "fields": {
    "email": "john@example.com",
    "first_name": "John",
    "last_name": "Doe"
  }
}
```

Une création réussie renvoie `201 Created` avec l'enregistrement stocké, y compris son `id` généré et ses métadonnées d'auteur :

```json
{
  "id": "42",
  "fields": {
    "email": "john@example.com",
    "first_name": "John",
    "last_name": "Doe"
  },
  "createdBy": "user-uuid-123",
  "createdAt": "2025-01-15T10:30:00Z",
  "updatedAt": "2025-01-15T10:30:00Z"
}
```

:::callout
**Les corps plats sont également acceptés.** Un corps sans clé `fields` (par ex. `{ "email": "john@example.com" }`) est automatiquement enveloppé dans la forme canonique `{ "fields": { ... } }`. La forme enveloppée est préférée et constitue la seule forme acceptée par les points de terminaison en lot et upsert.
:::

## Enveloppe de réponse de liste

`GET .../records` renvoie une enveloppe paginée, jamais un simple tableau :

```json
{
  "records": [{ "id": "1", "fields": {} }],
  "pagination": { "total": 128, "limit": 20, "offset": 0 }
}
```

`records` est la page de résultats ; `pagination` porte le nombre total `total` de lignes correspondantes ainsi que les valeurs `limit`/`offset` ayant produit cette page. Voir [Filtrage, tri et pagination](records-filtering-sorting) pour la grammaire complète des paramètres de requête.

## Métadonnées d'auteur

L'API estampille et expose automatiquement l'auteur de chaque écriture. Ces champs sont contrôlés par le serveur et **en lecture seule** — les valeurs fournies dans le corps d'une requête sont ignorées, de sorte que la piste d'audit ne peut pas être falsifiée.

| Champ                     | Renseigné quand                            | Effacé/mis à jour              |
| ------------------------- | ------------------------------------------ | ------------------------------ |
| `createdBy` / `createdAt` | L'enregistrement est créé                  | Ne change jamais               |
| `updatedBy` / `updatedAt` | L'enregistrement est créé ou mis à jour    | Réestampillé à chaque écriture |
| `deletedBy` / `deletedAt` | L'enregistrement est supprimé (réversible) | Effacé lors de la restauration |

`createdBy`, `updatedBy` et `deletedBy` se résolvent en l'ID de l'utilisateur authentifié. Ils sont exposés via des [types de champs d'audit utilisateur](user-audit-fields) dédiés (`created-by`, `updated-by`, `deleted-by`) et le champ système `updated-at` incrémente automatiquement l'horodatage à chaque écriture — ce qui permet le contrat de [verrouillage optimiste](records-crud).

## Règles transversales

Chaque point de terminaison d'enregistrements applique les mêmes garanties :

| Préoccupation                        | Comportement                                                                                                                                                |
| ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Authentification**                 | Les points de terminaison nécessitent une session. Les requêtes non authentifiées renvoient `401`.                                                          |
| **Existence de la table**            | Un `:tableId` inconnu renvoie `404` — jamais un 403, pour éviter l'énumération.                                                                             |
| **RBAC**                             | La création/lecture/mise à jour/suppression est régulée par [permission de table](table-permissions) et les attributions [RBAC](auth-roles-rbac) du rôle.   |
| **Permissions au niveau des champs** | Les réponses omettent les champs que l'appelant ne peut pas lire ; les écritures vers des champs que l'appelant ne peut pas modifier sont rejetées.         |
| **Validation**                       | Les valeurs des champs sont validées par rapport au type de champ ; les champs requis manquants et les violations de contraintes renvoient `400`.           |
| **Anti-énumération**                 | Un accès non autorisé à un enregistrement existant renvoie `404`, et non `403`, de sorte qu'un attaquant ne peut pas distinguer « interdit » de « absent ». |

:::callout
**404 plutôt que 403 est intentionnel.** Pour empêcher l'énumération des enregistrements, l'API renvoie `404 Not Found` pour les enregistrements auxquels l'appelant n'a pas accès — identique à la réponse pour les enregistrements qui n'existent pas. Voir la [vue d'ensemble de l'authentification](auth-overview).
:::

## Mise en forme d'affichage vs brute

Par défaut, les valeurs des champs sont renvoyées brutes (la valeur stockée). Passez `?format=display` pour recevoir des valeurs lisibles par un humain, sensibles à la locale et au fuseau horaire (devises, dates, durées et noms d'affichage des pièces jointes mis en forme). La forme brute est préférée pour les clients programmatiques ; la forme d'affichage est préférée pour le rendu direct. Voir [Mise en forme des enregistrements](records-crud) pour les contrôles.

## Pages associées

- [CRUD et upsert](records-crud) — créer, lire, mettre à jour, supprimer, upsert, mise en forme
- [Filtrage, tri et pagination](records-filtering-sorting) — paramètres de requête
- [Opérations en lot](records-batch) — création/mise à jour/suppression en masse
- [Historique et commentaires des enregistrements](record-history) — journal des modifications et collaboration
- [Suppression réversible et restauration](records-soft-delete) — corbeille et récupération
- [Abonnements en temps réel](records-realtime) — WebSocket/SSE/sondage
- [Import et export](records-import-export) — CSV/JSON et presse-papiers
- [Référence de l'API](api-reference) — le catalogue de points de terminaison généré
