EN

Conventions

Conventions communes à tous les endpoints de l'API v1 — request IDs, idempotency, pagination cursor, versioning, et règles de transport.

Request IDs

Chaque requête reçoit un ID au format ULID préfixé req_. Cet ID est retourné dans 2 headers (alias) :

  • X-Request-ID: req_01J9X8Z3F4K2M5N7P9Q1R3S5T7
  • Capturia-Request-ID: req_01J9X8Z3F4K2M5N7P9Q1R3S5T7

Fournis cet ID au support pour qu'on retrouve l'incident dans Sentry/logs.

Idempotency

Les routes mutantes (POST / PUT / DELETE) acceptent un header optionnel Idempotency-Key pour garantir qu'un retry n'exécute pas l'opération deux fois.

Idempotency-Key: a1b2c3d4-1234-4567-89ab-cdef01234567
  • Format accepté : [a-zA-Z0-9_-]{1,64} (généralement un UUID v4)

  • TTL stockage : 24h dans Vercel KV

  • Scope : par clé API (deux clés différentes peuvent réutiliser la même Idempotency-Key sans conflit)

Comportements

ScénarioRésultat
1ʳᵉ exécution

Endpoint exécuté normalement, response cachée 24h

Replay (même payload)

Response originale rejouée verbatim, même status, header Idempotent-Replayed: true

Conflit (payload différent)

409 idempotency_conflict avec details.original_request_id

Requête concurrent (lock actif)

409 idempotency_conflict avec details.in_progress: true

Pagination

Tous les endpoints GET collection utilisent une pagination cursor-based opaque :

ParamètreTypeDéfautMaxDescription
limitint20100

Taille de la page (max 100, > 100 → 400 invalid_request)

cursorstring

Cursor opaque base64url retourné dans pagination.next_cursor de la response précédente

{
  "data": [...],
  "pagination": {
    "next_cursor": "eyJ2IjoxLCJmIjoiY3JlYXRlZF9hdCIsInMiOiJkZXNjIiwidmFsIjoiMjAyNi0wNS0wNFQxMDowMDowMFoiLCJpZCI6ImN0X2FiYyJ9",
    "has_more": true,
    "limit": 20
  }
}

Format d'erreur

Toutes les erreurs respectent une enveloppe unifiée. Voir Catalog d'erreurs pour la liste exhaustive des codes.

Versioning et dépréciation

Versioning dans l'URL (/v1/, futur /v2/). Une version majeure n'arrive que pour des breaking changes — les ajouts backwards-compatible restent dans la version courante.

  • Délai minimum 12 mois entre annonce de dépréciation et retrait

  • Headers émis sur endpoints dépréciés : Deprecation (RFC 9745) + Sunset (RFC 8594) + Link: <url>; rel="deprecation"

  • Page changelog publique : /developers/api/v1/changelog

Mode dry-run

Le query param ?dry_run=true est parsé par le wrapper de routes mais le support varie par endpoint. Vérifie la référence de chaque endpoint pour savoir si le dry-run est implémenté.

Content-Type

Strict application/json (avec ou sans charset=utf-8). Refusés : multipart/form-data, application/x-www-form-urlencoded, etc → 415 invalid_content_type.

Taille du body

Limite : 1 MB par requête. Au-delà → 413 payload_too_large. Pour pousser des batches volumineux (>100 contacts), utilise plusieurs requêtes plus petites avec Idempotency-Key distincts.

Encoding

UTF-8 strict. Toute autre charset rejetée → 400 invalid_encoding.

Compression

Géré automatiquement par Vercel : Accept-Encoding: gzip, br supporté. Le header Vary: Accept-Encoding est émis pour les caches intermédiaires.