Enterprise API Guidelines
Enterprise API Guidelines
Inspired by Zalando’s API Guidelines. Keywords “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” are interpreted as described in RFC 2119.
API Specification and Documentation
MUST provide and publish API specifications using OpenAPI.
MUST create or update API documentation in the developer portal.
SHOULD provide comprehensive documentation, from getting started examples to in-depth details on all request and response parameters.
REST Design
MUST use REST maturity level 2 (Richardson Maturity Model).
HTTP Request Standards
MUST use HTTP methods correctly per RFC-9110 Methods.
MUST fulfill common method properties (safety, idempotency, cacheability).
MUST use official HTTP status codes per RFC-9110 Status Codes.
SHOULD only use most common HTTP status codes.
MUST use most specific HTTP status codes.
MUST use EV- prefix for custom headers.
EV-Quota-Limit: 1000
MAY consider supporting Idempotency-Key header for POST requests.
HTTP Response Standards
MUST return HTTP 201 Created for successful resource creation with Location header:
HTTP 201 Created
Location: /v3/resources/1234567890abcdef
Content-Type: application/json
{
"id": "1234567890abcdef"
}
MUST return HTTP 204 No Content for successful deletions:
HTTP 204 No Content
MUST return HTTP 400 Bad Request for invalid client data:
HTTP 400 Bad Request
Content-Type: application/json
{
"type": "https://datatracker.ietf.org/doc/html/rfc7231#section-6.5.1",
"title": "Bad Request",
"status": 400,
"detail": "Invalid request payload.",
"traceId": "",
"errors": [
{
"path": "field.name",
"messages": ["Must not be empty"]
}
]
}
MUST return HTTP 401 Unauthorized for missing or invalid authentication:
HTTP 401 Unauthorized
Content-Type: application/json
{
"type": "https://datatracker.ietf.org/doc/html/rfc7235#section-3.1",
"title": "Unauthorized",
"status": 401,
"detail": "Authentication required to access this resource."
}
MUST return HTTP 403 Forbidden when access is denied despite authentication:
HTTP 403 Forbidden
Content-Type: application/json
{
"type": "https://datatracker.ietf.org/doc/html/rfc7231#section-6.5.3",
"title": "Forbidden",
"status": 403,
"detail": "User does not have access to this resource."
}
MUST return HTTP 404 Not Found when resource does not exist:
HTTP 404 Not Found
Content-Type: application/json
{
"type": "https://datatracker.ietf.org/doc/html/rfc7231#section-6.5.4",
"title": "Not Found",
"status": 404,
"detail": "Requested resource does not exist."
}
MUST return HTTP 429 Too Many Requests when rate limits are exceeded:
HTTP 429 Too Many Requests
Retry-After: 60
Content-Type: application/json
{
"type": "https://datatracker.ietf.org/doc/html/rfc6585#section-4",
"title": "Too Many Requests",
"status": 429,
"detail": "Rate limit exceeded. Please retry later.",
"traceId": ""
}
MUST return HTTP 500 Internal Server Error for unexpected server errors:
HTTP 500 Internal Server Error
Content-Type: application/json
{
"type": "https://datatracker.ietf.org/doc/html/rfc7231#section-6.6.1",
"title": "Internal Server Error",
"status": 500,
"detail": "An unexpected error occurred on our side. Please try again later."
}
Resource Naming and URL Structure
MUST NOT use /api as base path.
MUST keep URLs verb-free.
MUST avoid actions — think about resources.
MUST use domain-specific resource names.
MUST pluralize resource names.
MUST use URL-friendly resource identifiers.
MUST use kebab-case for path segments.
MUST identify resources and sub-resources via path segments:
GET /resources/{resource-id}/sub-resources/{sub-resource-id}
MAY consider using non-nested URLs for sub-resources.
SHOULD limit number of sub-resource levels (≤ 3).
MUST use snake_case for query parameters:
GET /resources?filter_field_value=value
SHOULD pass lists in query parameters using comma-separated values:
GET /scorecards?siren_numbers=1,2,3,4,5
Data and Format Standards
MUST use JSON as the payload data format.
SHOULD define and observe a general response format for all outcomes (success, error, batch).
MUST use standard media types (IANA).
MUST use OpenAPI-defined standard data formats.
MUST use standard date/time formats (RFC 3339):
{
"createdAt": "2025-03-21T14:23:45Z"
}
SHOULD use UTC for time representation.
SHOULD use Accept-Language header for localization.
MUST use standard formats for country, language, and currency codes:
- Country: ISO 3166-1-alpha-2
- Language: ISO 639-1
- Currency: ISO 4217
MUST use camelCase for property names.
SHOULD declare enum values using UPPER_SNAKE_CASE (except case-sensitive external standards like ISO 639-1).
MUST follow a common sorting behavior using sort_field and sort_type:
GET /resources?sort_field=name&sort_type=asc
MUST support pagination:
GET /resources?page_size=100&page_number=1
{
"pagination": {
"currentPage": 1,
"pageSize": 100,
"totalItems": 1000,
"hasNextPage": true
},
"data": [
{...},
{...}
]
}
Errors
MUST specify success and error responses with actionable messages (see HTTP Response Standards section).
Security
MUST secure all endpoints.
MUST NOT expose stack traces in production.
Versioning and Compatibility
MUST not break backward compatibility.
SHOULD prefer backward-compatible extensions: add only optional fields, avoid changing semantics, keep validation consistent.
SHOULD avoid versioning — prefer resource variants over breaking changes.
MUST use semantic versioning (SemVer 2.0.0).
MUST use URL versioning.
MUST reflect deprecation in OpenAPI specs.
SHOULD add Deprecation and Sunset headers to responses.