
# Opérations en lot

Les points de terminaison en lot écrivent de nombreux enregistrements en une seule requête, afin que vous puissiez importer, synchroniser ou modifier des données en masse efficacement — et de façon atomique. Chaque lot s'exécute dans une seule transaction : si un enregistrement échoue à la validation, l'ensemble du lot est annulé et aucune ligne n'est écrite. Passez `returnRecords: true` pour recevoir les enregistrements affectés dans la réponse (sinon, seul un résumé est renvoyé).

| Méthode et chemin                                 | Opération              | Max par lot |
| ------------------------------------------------- | ---------------------- | ----------- |
| `POST /api/tables/:tableId/records/batch`         | Créer                  | 1000        |
| `PATCH /api/tables/:tableId/records/batch`        | Mettre à jour          | 100         |
| `DELETE /api/tables/:tableId/records/batch`       | Suppression réversible | 100         |
| `POST /api/tables/:tableId/records/batch/restore` | Restaurer              | 100         |
| `POST /api/tables/:tableId/records/upsert`        | Upsert                 | 100         |

Tous les corps en lot requièrent la forme enveloppée canonique (`{ "fields": { ... } }`) — le raccourci de corps plat accepté par la création d'un enregistrement unique n'est **pas** disponible dans les requêtes en lot. Chaque lot doit contenir au moins un enregistrement.

## Création en lot

Envoyez un tableau `records`, chaque élément étant une enveloppe. Jusqu'à 1000 enregistrements par appel.

```json
POST /api/tables/contacts/records/batch
{
  "records": [
    { "fields": { "email": "alice@example.com", "name": "Alice" } },
    { "fields": { "email": "bob@example.com", "name": "Bob" } }
  ],
  "returnRecords": true
}
```

| Statut             | Signification                                                                                                    |
| ------------------ | ---------------------------------------------------------------------------------------------------------------- |
| `201 Created`      | Tous les enregistrements créés                                                                                   |
| `400 Bad Request`  | Tableau vide, au-delà de la limite de 1000, ou un enregistrement échoue à la validation (tout le lot est annulé) |
| `401 Unauthorized` | Aucune session active                                                                                            |
| `404 Not Found`    | Table introuvable ou non visible                                                                                 |

## Mise à jour en lot

Chaque élément nomme l'`id` de l'enregistrement (chaîne ou nombre) plus les `fields` à mettre à jour. Jusqu'à 100 enregistrements par appel.

```json
PATCH /api/tables/contacts/records/batch
{
  "records": [
    { "id": "1", "fields": { "status": "active" } },
    { "id": 2, "fields": { "status": "archived" } }
  ],
  "returnRecords": true
}
```

Les mises à jour sont partielles par enregistrement — seuls les champs nommés sont écrits. Si un `id` est manquant ou une valeur invalide, la transaction est annulée.

## Suppression en lot

Envoyez un tableau `ids`. Suppression réversible par défaut ; définissez `permanent: true` pour supprimer définitivement des enregistrements déjà supprimés de façon réversible (réservé aux administrateurs, appliqué dans la couche applicative). Jusqu'à 100 ID par appel.

```json
DELETE /api/tables/contacts/records/batch
{
  "ids": ["1", "2", 3],
  "permanent": false
}
```

:::callout
**`permanent` peut aussi être une chaîne de requête.** Les variantes de route qui conservent le contrat hérité acceptent `?permanent=true`. La forme par corps JSON est préférée. La suppression définitive en lot est irréversible et requiert la permission `permanentDelete` — voir [Suppression réversible et restauration](records-soft-delete).
:::

## Restauration en lot

Récupérez plusieurs enregistrements supprimés de façon réversible en une seule fois. Les enregistrements qui ne sont pas actuellement supprimés sont ignorés ; un `id` manquant annule l'ensemble du lot.

```json
POST /api/tables/contacts/records/batch/restore
{
  "ids": ["1", "2", "3"]
}
```

La restauration efface les champs `deletedAt`/`deletedBy` de chaque enregistrement et est consignée dans l'[historique des modifications](record-history) de l'enregistrement.

## Upsert en lot

Créez ou mettez à jour de nombreux enregistrements correspondant à un ou plusieurs champs uniques, en une seule transaction. Nommez la ou les clés de fusion avec `fieldsToMergeOn` (alias : `matchFields`). Jusqu'à 100 enregistrements par appel.

```json
POST /api/tables/contacts/records/upsert
{
  "records": [
    { "fields": { "email": "alice@example.com", "name": "Alice" } },
    { "fields": { "email": "carol@example.com", "name": "Carol" } }
  ],
  "fieldsToMergeOn": ["email"],
  "returnRecords": true
}
```

Chaque enregistrement est mis en correspondance sur les champs de fusion : une correspondance existante est mise à jour, sinon une nouvelle ligne est créée. L'upsert en lot est le chemin canonique pour la synchronisation idempotente depuis une source de vérité externe.

## Résumé des limites et de la sémantique

| Propriété       | Comportement                                                                                         |
| --------------- | ---------------------------------------------------------------------------------------------------- |
| Atomicité       | Chaque lot est une seule transaction — tout ou rien                                                  |
| `returnRecords` | `false` par défaut ; `true` renvoie les enregistrements affectés                                     |
| Taille minimale | Au moins un enregistrement/ID requis (`400` sinon)                                                   |
| Auteur          | `createdBy`/`updatedBy`/`deletedBy` estampillés par enregistrement, comme pour les écritures uniques |
| Permissions     | RBAC et permissions au niveau des champs appliqués par enregistrement                                |

## Pages associées

- [CRUD et upsert](records-crud) — opérations sur un enregistrement unique et contrat d'upsert
- [Suppression réversible et restauration](records-soft-delete) — suppression définitive et restauration
- [Historique et commentaires des enregistrements](record-history) — les opérations en lot sont consignées
- [Vue d'ensemble des enregistrements](records-overview) — règles d'enveloppe et d'auteur
