4.6 KiB
Executable File
4.6 KiB
Executable File
API Design Patterns — Guide Expert
REST API Best Practices
Nommage des URLs
# BON — Resource-oriented, pluriel, hiérarchique
GET /api/v1/users # Liste
GET /api/v1/users/123 # Détail
POST /api/v1/users # Créer
PUT /api/v1/users/123 # Remplacer
PATCH /api/v1/users/123 # Modifier partiellement
DELETE /api/v1/users/123 # Supprimer
GET /api/v1/users/123/orders # Sous-resource
GET /api/v1/users/123/orders/456 # Détail sous-resource
# MAUVAIS
GET /api/getUser/123 # Verbe dans l'URL
POST /api/user/create # Redondant avec POST
GET /api/v1/User # Singulier, majuscule
Status Codes
| Code | Usage |
|---|---|
| 200 | OK — GET/PUT/PATCH réussi |
| 201 | Created — POST réussi |
| 204 | No Content — DELETE réussi |
| 400 | Bad Request — Input invalide |
| 401 | Unauthorized — Pas d'auth |
| 403 | Forbidden — Auth OK mais pas les permissions |
| 404 | Not Found |
| 409 | Conflict — Doublon, état incohérent |
| 422 | Unprocessable Entity — Validation échouée |
| 429 | Too Many Requests — Rate limit |
| 500 | Internal Server Error |
| 503 | Service Unavailable — Maintenance |
Pagination
// Cursor-based (recommandé pour les grands datasets)
GET /api/v1/contacts?limit=50&cursor=eyJpZCI6MTIzNH0=
Response:
{
"data": [...],
"meta": {
"total": 6650000,
"limit": 50,
"next_cursor": "eyJpZCI6MTI4NH0=",
"has_more": true
}
}
// Offset-based (simple mais lent sur gros volumes)
GET /api/v1/contacts?page=5&per_page=50
Error Format Standard
{
"error": {
"code": "VALIDATION_ERROR",
"message": "La validation a échoué",
"details": [
{
"field": "email",
"message": "Format email invalide",
"code": "INVALID_FORMAT"
},
{
"field": "name",
"message": "Le nom est requis",
"code": "REQUIRED"
}
],
"request_id": "req_abc123",
"timestamp": "2026-02-17T10:30:00Z"
}
}
Rate Limiting Headers
X-RateLimit-Limit: 1000 # Max requêtes par fenêtre
X-RateLimit-Remaining: 742 # Requêtes restantes
X-RateLimit-Reset: 1708171200 # Timestamp de reset
Retry-After: 60 # Secondes à attendre (si 429)
Authentication Patterns
# Bearer Token (recommandé)
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
# API Key (simple, pour server-to-server)
X-API-Key: wevads_live_abc123def456
# Basic Auth (legacy, HTTPS obligatoire)
Authorization: Basic base64(username:password)
Versioning Strategies
| Strategy | Exemple | Avantages | Inconvénients |
|---|---|---|---|
| URL path | /api/v1/users | Clair, simple | URL change |
| Header | Accept: application/vnd.api.v2+json | URL stable | Moins visible |
| Query param | /api/users?version=2 | Simple | Pollue les params |
Webhook Design
// Webhook payload standard WEVADS
{
"event": "conversion.created",
"timestamp": "2026-02-17T10:30:00Z",
"data": {
"conversion_id": "conv_abc123",
"offer_id": 42,
"payout": 27.50,
"currency": "USD",
"sub1": "camp_123",
"sub2": "creative_456",
"sub3": "user_789"
},
"signature": "sha256=abc123..."
}
// Signature verification (HMAC)
$expectedSig = 'sha256=' . hash_hmac('sha256', $rawBody, $webhookSecret);
if (!hash_equals($expectedSig, $receivedSig)) {
http_response_code(401);
die('Invalid signature');
}
Patterns d'intégration WEVADS
CX3 Ads (CAKE) API
# Pull conversions
GET https://api.cx3ads.com/conversions?start_date=2026-02-17&end_date=2026-02-17&affiliate_id=10805
Headers: Authorization: Bearer {api_key}
# Response
{
"conversions": [
{
"conversion_id": "...",
"offer_id": 42,
"payout": 27.50,
"sub1": "wevads_camp_123",
"sub2": "creative_456",
"sub3": "contact_789",
"datetime": "2026-02-17T14:30:00Z"
}
]
}
Ollama API (local LLM)
# Chat completion
POST http://88.198.4.195:11434/api/chat
{
"model": "deepseek-r1:32b",
"messages": [
{"role": "system", "content": "Tu es WEVIA..."},
{"role": "user", "content": "Question..."}
],
"stream": false,
"options": {"temperature": 0.7}
}
# Generate embedding
POST http://88.198.4.195:11434/api/embeddings
{
"model": "nomic-embed-text",
"prompt": "Texte à embedder"
}
// Response: {"embedding": [0.123, -0.456, ...]} // 768 dimensions
# List models
GET http://88.198.4.195:11434/api/tags