Saltar a contenido

API Endpoint Conventions (Contract‑First, REST, Versioning)

Note: Repository content must be in English. This guide follows that rule and provides conventions and examples for HTTP APIs.

1) Principles

  • Contract‑first: Define the API contract (OpenAPI/Swagger) before implementation. Treat the contract as source of truth and version‑control it.
  • Resource‑oriented: Model endpoints around nouns (resources), not verbs.
  • Consistency: Consistent naming, casing, pagination, filtering, and errors across all services.
  • Backward compatibility: New versions must not break existing clients without a deprecation path.
  • Security by default: AuthN, AuthZ, and secure defaults (TLS, scopes, least privilege).
  • Observability: Correlation IDs, structured logging, metrics, and tracing for every request.

2) Versioning

  • Base path versioning: Use a major version in the URL: /api/v1. Avoid embedding minor/patch versions in URLs.
  • Breaking changes → increment major (/api/v2). Non‑breaking changes (adding fields, new optional params) stay in the same major.
  • Sunset headers: For deprecated versions, return:
  • Deprecation: true
  • Sunset: <RFC3339 date>
  • Optionally Link: <URL>; rel="deprecation"

Examples

/api/v1/users
/api/v1/orders/{orderId}
/api/v2/users   # after breaking change

3) Naming & URL Design

  • Plural resource names: /users, /orders, /products.
  • Lowercase, kebab-case for path segments when needed: /payment-methods.
  • Stable IDs: Use opaque IDs (UUIDs) where possible.
  • Relationships:
  • Sub‑resources: /users/{userId}/orders
  • Linking via IDs for many‑to‑many; avoid deep nesting (>2 levels). Prefer filters instead.
  • No verbs in paths. Use HTTP methods to express actions.

Good

GET  /api/v1/users/{id}
POST /api/v1/users
Avoid
POST /api/v1/createUser

4) HTTP Methods & Semantics

Method Safe Idempotent Typical Use
GET Retrieve resources
POST Create resource / non‑idempotent operations
PUT Replace entire resource
PATCH ✗* Partial update (use JSON Patch/Merge Patch)
DELETE Delete resource

*PATCH may be made idempotent by design of patch document.

5) Status Codes

  • 200 OK (GET), 201 Created (POST with Location header), 202 Accepted (async), 204 No Content (DELETE/PUT with no body)
  • Client errors: 400 (validation), 401 (unauthenticated), 403 (forbidden), 404 (not found), 409 (conflict), 422 (semantic errors)
  • Server errors: 500, 502, 503, 504 — never expose internals.

6) Error Model (Problem Details)

Use RFC 9457 – Problem Details for HTTP APIs style:

{
  "type": "https://api.example.com/errors/validation-failed",
  "title": "Validation failed",
  "status": 422,
  "detail": "email must be a valid address",
  "instance": "urn:trace:44f5a8...",
  "errors": [
    { "field": "email", "message": "invalid format" },
    { "field": "password", "message": "min length is 12" }
  ]
}

Always include a correlation/trace ID (e.g., in instance) and return it also as a header, e.g. X-Request-Id.

7) Filtering, Sorting, Pagination, Fields

  • Pagination: cursor‑based recommended (page[size], page[cursor]). Offset allowed for small datasets (page, page_size).
  • Sorting: sort=created_at or sort=-created_at (descending).
  • Filtering: ?status=active&created_from=2025-01-01&created_to=2025-01-31.
  • Sparse fieldsets: fields= id,name,email to limit payloads.
  • Expansions (optional): expand=owner,items to embed related resources.

Example

GET /api/v1/orders?status=shipped&sort=-created_at&page[size]=50&page[cursor]=eyJvcmRlcmlkIjoiLi4uIn0=

8) Request/Response Bodies

  • JSON only by default (application/json; charset=utf-8).
  • Use snake_case or camelCase consistently (choose once for all services; camelCase is common in JSON).
  • Include createdAt, updatedAt timestamps where useful (ISO‑8601/RFC3339 in UTC).
  • For collections, wrap in an object with data and meta:
    {
      "data": [{ "id": "...", "name": "..." }],
      "meta": { "total": 123, "nextCursor": "..." }
    }
    

9) Idempotency

  • For non‑idempotent POSTs (e.g., payments), support Idempotency‑Key header. Store key + request hash + result for a TTL.

10) Caching

  • ETags and If-None-Match on GET for conditional responses (304).
  • Cache-Control with appropriate max‑age or no-store for sensitive data.

11) Security

  • TLS everywhere.
  • Auth: OAuth2/OIDC (Bearer tokens), or mTLS where appropriate.
  • Scopes/claims → fine‑grained Authorization.
  • Input validation & output encoding. Reject unknown fields if strictness is required.
  • Rate limiting (429), API keys for server‑to‑server if needed.
  • Never leak stack traces or internal messages in responses.

12) Async Operations & Webhooks

  • Long‑running tasks return 202 Accepted with a status resource:
    POST /api/v1/exports → 202
    Location: /api/v1/exports/6f…/status
    
  • Provide webhooks for completion events; sign webhook requests and retry on 5xx/timeout.

13) OpenAPI (Contract‑First Workflow)

  1. Design the OpenAPI spec (YAML/JSON).
  2. Review: API review checklist (naming, pagination, errors, security).
  3. Generate server stubs & SDKs (if applicable).
  4. Mock server to unblock consumers.
  5. Implement handlers behind the contract.
  6. Test conformance (contract tests).
  7. Publish documentation & changelog.

Minimal OpenAPI skeleton

openapi: 3.0.3
info:
  title: Example API
  version: 1.0.0
servers:
  - url: https://api.example.com/api/v1
paths:
  /users:
    get:
      summary: List users
      parameters:
        - in: query
          name: page[size]
          schema: { type: integer, minimum: 1, maximum: 100 }
      responses:
        '200':
          description: OK

14) Deprecation Policy

  • Announce in changelog & docs.
  • Mark endpoints as deprecated (deprecated: true in OpenAPI; Deprecation header).
  • Provide migration guidance and a minimum 90‑day window before removal (adjust to your domain).

15) Observability & Reliability

  • Structured logs (JSON): include service, env, version, traceId, spanId.
  • Metrics: request count, latencies, error rates, saturation, dependency health.
  • Tracing: propagate traceparent/baggage (W3C), instrument outbound calls.
  • SLOs/SLIs: define target latency and uptime; alert on breach.

16) Examples

Create user

POST /api/v1/users
Content-Type: application/json
Idempotency-Key: 4b1f…

{ "email": "j.smith@example.com", "name": "John Smith" }
Response
201 Created
Location: /api/v1/users/3f25…

{ "id": "3f25…", "email": "j.smith@example.com", "name": "John Smith", "createdAt": "2025-08-17T12:34:56Z" }