API guidelines
Enterprise API Guidelines
API Style Guideline
Inspired by Zalando’s API Guidelines.
The requirement level keywords “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” used in this document (case insensitive) are to be interpreted as described in RFC 2119.
A. 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 straight-forward getting started examples to in-depth details on all request and response parameters.
B. REST Design
MUST use REST maturity level 2 (as per the Richardson Maturity Model).
C. HTTP Request Standards
MUST use HTTP methods correctly — comply with standardized HTTP semantics (see RFC-9110 Methods).
MUST fulfill common method properties (safety, idempotency, and cacheability).
MUST use official HTTP status codes correctly — follow 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.
Example: EV-Quota-Limit
MAY consider supporting Idempotency-Key
header for POST requests.
D. HTTP Response Standards
MUST return HTTP 201 Created for successful resource creation.
Include a Location
header with the URI of the newly created resource.
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 when the client sends invalid 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 when authentication is missing or invalid.
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 the requested 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.
MAY include the Retry-After
header.
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."
}
E. 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.
Example: /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.
Example: /resources?filter_field_value=value
SHOULD pass lists in query parameters using comma-separated values.
Example: /scorecards?siren_numbers=1,2,3,4,5
F. 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).
Example: "2025-03-21T14:23:45Z"
SHOULD use UTC for time representation.
SHOULD use Accept-Language
header for localization (when supported).
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.
Exception: case-sensitive external standards like ISO 639-1.
MUST follow a common sorting behavior.
Use sort_field
and sort_type
(values: asc
, desc
)
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": [
{...},
{...}
]
}
G. Errors
MUST specify success and error responses.
Include actionable messages. Refer to section D for standard error formats and examples.
H. Security
MUST secure all endpoints.
MUST NOT expose stack traces in production.
I. 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.