API Contracts
This guide covers API design patterns, request/response formats, and best practices. For complete endpoint reference, see .context/api/endpoints.md.API Format
The CMS API uses REST + JSON-LD/Hydra format powered by API Platform.JSON-LD Structure
All responses include JSON-LD context and type information:@context: Schema definition URL@id: Unique identifier (IRI)@type: Resource type
Hydra Collections
Collection endpoints return Hydra format:Request Patterns
Headers
Required for all authenticated requests:Create Resource (POST)
Update Resource (PUT)
Full Replacement:Partial Update (PATCH)
Update Specific Fields:Delete Resource (DELETE)
Pagination
Query Parameters
page: Page number (default: 1)per_page: Items per page (default: 30, max: 100)
Response Structure
Filtering
Exact Match
Multiple Filters
Full-Text Search
Relationships
Embedded Resources (IRIs)
Request with Relationships:- Format:
/admin/{resource}/{uuid} - API Platform resolves IRIs to actual entities
Response with Embedded Data
Admin Endpoint (includes related data):Multi-Language Content
Request Format
All multi-language fields use JSON objects with locale keys:Supported Locales
fr(French)en(English)
config/services.yaml:
Fallback Strategy
Frontend should implement fallback:Error Responses
RFC7807 Problem Details
All errors follow RFC7807 format:Common Status Codes
| Code | Meaning | Example |
|---|---|---|
| 200 | OK | Successful GET, PUT, PATCH |
| 201 | Created | Successful POST |
| 204 | No Content | Successful DELETE |
| 400 | Bad Request | Invalid JSON, missing required header |
| 401 | Unauthorized | Missing/invalid JWT token |
| 403 | Forbidden | Insufficient permissions |
| 404 | Not Found | Resource doesn’t exist |
| 409 | Conflict | Unique constraint violation |
| 412 | Precondition Failed | ETag mismatch (optimistic locking) |
| 422 | Unprocessable Entity | Validation errors |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Server Error | Server error |
Error Examples
Validation Error (422):Rate Limiting
Limits
Anonymous Users:- 100 requests / 15 minutes per IP
- 1000 requests / 15 minutes per user
Headers
Response Headers:Handling Rate Limits
Optimistic Locking
Using ETags
1. Get Resource with ETag:Conflict (412 Precondition Failed): Resource modified by another user
Conflict Resolution
Best Practices
For API Consumers
-
Always include required headers
Authorizationfor authenticated requestsX-Tenant-Idfor all requests
-
Handle pagination
- Use
hydra:nextfor navigation - Don’t construct page URLs manually
- Use
-
Use IRIs for relationships
- Send
/admin/tags/{uuid}not{"id": 1}
- Send
-
Implement error handling
- Check
statuscode - Parse
violationsfor validation errors
- Check
-
Respect rate limits
- Check
X-RateLimit-*headers - Implement exponential backoff
- Check
-
Cache appropriately
- Public content: 1 hour
- Admin data: 5 minutes
- Invalidate on updates
For API Developers
-
Use serialization groups
- Control exposed fields
- Separate public/admin/write contexts
-
Validate input
- Use Symfony Validator
- Return meaningful error messages
-
Document endpoints
- Add OpenAPI descriptions
- Provide examples
-
Test thoroughly
- Unit tests for logic
- Functional tests for endpoints
- Integration tests for workflows
-
Monitor performance
- Track slow queries
- Monitor cache hit rates
- Alert on high error rates