Une API de données n’est pas un entrepôt à ciel ouvert. Elle doit exposer des contrats lisibles, des formats stables et des garanties simples: comment filtrer, paginer, trier, comprendre les erreurs et se mettre à jour sans casser les clients. Le but est de réduire le temps entre la question et la réponse fiable.
prerequis
- Un entrepôt ou un lac avec des vues stables et documentées.
- Des schémas décrits (types, unités, périmètre, fraîcheur).
- Une stratégie d’identité et d’autorisations simple (tokens, scopes).
idees clefs
- Un contrat de schéma visible et versionné.
- Pagination, tri et filtres cohérents sur tous les endpoints.
- Formats simples: JSON pour navigation, CSV/NDJSON/Parquet pour volumes.
- Horodatage et fuseau explicites, pas d’ambiguite sur les dates.
- Erreurs claires et idempotence des créations/modifications.
- Dépréciation annoncée et migration assistée.
pas a pas
etape 1: écrire le contrat
Définir pour chaque endpoint les champs, types, unités, ordre, filtres et limites.
endpoint: GET /api/sales/orders
contract:
params:
- name: start_date # YYYY-MM-DD
- name: end_date # YYYY-MM-DD, exclusif
- name: country # ex: FR, DE
- name: limit # pagination: 1..1000
- name: cursor # token opaque
response:
- order_id: string
- order_date: datetime (UTC)
- amount_eur: number
- country: string
sort: order_date asc
freshness_slo_min: 180
etape 2: normaliser pagination et filtres
Même mécanique partout: limit + cursor, pas d’off-by-one ni de pages aléatoires.
# 1ere page
curl -H "Authorization: Bearer $TOKEN" \
"https://api.data.pm/api/sales/orders?start_date=2020-01-01&end_date=2020-01-31&limit=500"
# reponse (extrait)
# {
# "data": [...],
# "next_cursor": "eyJvcmRlcl9kYXRlIjoiMjAyMC0wMS0xNVQxMjozMDo1MFoiLCJvcmRlcl9pZCI6IjEyMzQifQ=="
# }
# page suivante
curl -H "Authorization: Bearer $TOKEN" \
"https://api.data.pm/api/sales/orders?cursor=eyJvcm...==&limit=500"
etape 3: soigner les dates et les unités
Toujours préciser timezone, format, unité; fournir un exemple.
{
"order_date": "2020-01-15T12:30:50Z",
"amount_eur": 129.90,
"country": "FR"
}
etape 4: proposer des exports pour le volume
Même endpoint logique, suffixes clairs pour formats bruts.
# CSV
curl -L -H "Authorization: Bearer $TOKEN" \
"https://api.data.pm/api/sales/orders.csv?start_date=2020-01-01&end_date=2020-01-31" -o orders_2020_01.csv
# NDJSON (une ligne JSON par enregistrement)
curl -L -H "Authorization: Bearer $TOKEN" \
"https://api.data.pm/api/sales/orders.ndjson?start_date=2020-01-01&end_date=2020-01-31" -o orders_2020_01.ndjson
etape 5: documenter les erreurs et l’idempotence
Des codes HTTP honnêtes et des messages utiles; fournir une cle idempotency.
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": "invalid_parameter",
"message": "start_date must be before end_date",
"param": "start_date",
"docs": "https://api.data.pm/docs#errors"
}
# creation idempotente
curl -X POST -H "Authorization: Bearer $TOKEN" \
-H "Idempotency-Key: 3d7f3e8a-8de0-4a2a-b1a1-dc2b18" \
-H "Content-Type: application/json" \
-d '{"name":"orders_daily_v1","schedule":"0 5 * * *"}' \
https://api.data.pm/api/exports
etape 6: versionner sans casser
Garder v1 stable; introduire v2 en parallele et annoncer la depreciation.
deprecation:
- v1 retiree le 2020-06-30
- v2 expose "tax_eur" et "amount_eur" se limite au HT
- guide: https://api.data.pm/migrate-orders-v2
exemples
cas: endpoint de series temporelles simple et robuste
GET /api/metrics/daily?metric=cpa_eur&start=2020-01-01&end=2020-03-01&group_by=country&limit=1000
Authorization: Bearer <token>
{
"metric": "cpa_eur",
"granularity": "day",
"unit": "EUR",
"data": [
{"date":"2020-01-01","country":"FR","value":48.3},
{"date":"2020-01-01","country":"DE","value":46.9}
],
"next_cursor": null
}
-- cote entrepot: vue stable alimentee par ETL
CREATE OR REPLACE VIEW metrics.cpa_daily_v AS
SELECT
DATE_TRUNC('day', ts)::date AS d,
country,
ROUND(SUM(spend_eur)/NULLIF(SUM(conversions),0),2) AS cpa_eur
FROM marketing.daily_stats
GROUP BY 1,2;
pieges frequents
- filtres differents par endpoint -> confusion -> meme grammaire de filtres partout
- pages numerotees -> trous/doublons -> utiliser cursor base sur tri deterministe
- champs caches/renommes -> casse -> contrat de schema et changelog publics
- fuseaux implicites -> erreurs -> toujours UTC en stockage, TZ explicite si affichage local
- overfetch JSON -> lenteur -> proposer CSV/NDJSON/Parquet pour gros volumes
- auth ad hoc -> failles -> tokens scopes, RLS cote entrepot
faq
- comment limiter la casse lors des changements ? Garder v1 intacte, publier v2 en parallele, fournir un guide de migration et une periode de double publication.
- faut il tout mettre en temps reel ? Non. Fixez des SLO de fraicheur credibles et annoncez les delais de disponibilite.
- quels formats recommander ? JSON pour navigation et APIs metier; CSV/NDJSON pour export rapide; Parquet quand il faut compresser et typer.