Core Concept

API Contract & Integration Design

How to shape the surface between services and clients — structured errors, idempotent mutations, pagination contracts, webhooks, long-running job APIs, auth scopes, and versioning policy — independent of whether you choose REST, GraphQL, or gRPC on the wire.


1. What It Is

Beyond picking HTTP vs gRPC, we define the contract: error shapes, pagination, idempotency, versioning, and webhook semantics. Integrators judge your API by predictability, not throughput alone.

What:

The set of conventions that define how callers interact with your system beyond transport choice — request/response shapes, failure semantics, auth boundaries, and evolution rules.

Primary purpose:

Make integrations predictable for humans and machines: clients know how to retry, paginate, authenticate, and handle partial failures without tribal knowledge.

Usually used for:

Public REST/GraphQL products, B2B partner APIs, payment and booking flows, async job platforms, and webhook-driven event notifications.

2. Core Mental Model

We separate three layers in every API discussion:

📡 Transport

HTTP/2, gRPC, WebSocket — how bytes move. Covered in Network Protocols.

📜 Contract

Resources, fields, error codes, pagination tokens, idempotency rules — what callers may depend on.

🔌 Integration

Webhooks, batch imports, OAuth scopes, SLA headers — how external systems stay in sync over time.

In the room

Name idempotency keys for POST retries, cursor-based pagination for large lists, and structured error codes (not just 500). Versioning strategy (URL vs header) comes up — pick one and explain migration.

3. Why It Matters in HLD

API contracts define how services integrate — versioning, errors, idempotency, and pagination shape reliability. Three lenses:

Needed When:

Multiple clients (web, mobile, partners) consume the same backend, or money-moving operations require exactly-once business semantics.

Avoids:

Ambiguous 500 errors, duplicate charges on retry, and breaking mobile apps silently when response fields disappear.

Optimizes For:

Operability — on-call engineers and partner developers can debug from logs and documented error codes alone.

4. Architecture & Data Flow

Walk API design as interview steps. Step 1 — Resource model: nouns, IDs, and ownership boundaries. Step 2 — Endpoints: key CRUD + action routes with HTTP verbs. Step 3 — Errors: structured envelope with code, message, retryable flag. Step 4 — Idempotency: Idempotency-Key header on POST/payment. Step 5 — Pagination: cursor-based for deep lists; state why not offset.

Loading...

In the room

Propose cursor pagination for infinite feeds — offset pagination at page 10,000 is a classic senior signal. Mention idempotency keys on any money-moving POST.

5. Key Characteristics

REST vs GraphQL vs RPC, sync vs webhook, version strategy — we compare contract choices:

Contract TraitWhat to Specify
Structured errors
  • Machine-readable codes plus human messages
  • never expose stack traces publicly.
Safe retries
  • Idempotency keys on POST
  • GET/PUT/DELETE documented as naturally idempotent where applicable.
Stable pagination
  • Cursor tokens over deep offset scans
  • document sort order guarantees.
Explicit auth scopes
  • Least-privilege tokens
  • separate read vs write vs admin capabilities.
Versioned evolutionDeprecation headers, sunset dates, parallel /v1 and /v2 routes during migration.
GraphQL contracts
  • Schema-first SDL with nullable vs non-null fields explicit
  • deprecate fields via @deprecated directive
  • cap query depth and complexity to prevent N+1 resolver storms.

6. Strategic Tradeoffs

Strict contracts improve integration but slow iteration — we state both:

BenefitCost
Explicit contracts — clients and services agree on error shapes, pagination tokens, and webhook signatures before code shipsDocumentation debt — contracts drift unless OpenAPI/schema checks run in CI
Integration resilience — idempotency keys and signed webhooks survive network retries without duplicate side effectsStorage overhead — idempotency records and webhook delivery logs consume Redis/DB capacity

7. Failure / Bottleneck Awareness

Breaking changes, N+1 GraphQL, missing idempotency on payments — we name pitfalls:

🔁 Retry Storms Without Idempotency

Problem: A mobile client retries a failed payment POST three times. Without an idempotency key, the gateway creates three charges.

Mitigation: Require Idempotency-Key on mutating endpoints; store key → response mapping in Redis with 24-hour TTL; return cached response on duplicate key.

📬 Webhook Delivery Gaps

Problem: Partner endpoint is down for 10 minutes; order-shipped events are lost with fire-and-forget POST.

Mitigation: Persist outbound events in a queue; exponential backoff retries; expose GET /events for manual replay; sign payloads with HMAC so partners verify authenticity.

📄 Offset Pagination Cliff

Problem: Admin dashboard requests page 5000 with offset=100000; database scans and discards 100k rows per request.

Mitigation: Cursor pagination keyed on indexed columns; document that arbitrary page jumps are unsupported for large datasets.

8. Common HLD Usage

Public developer platforms, webhook integrations, and mobile clients drive API design depth:

ProblemUsage
Payment checkout APIIdempotency-Key header, structured 402/409 errors, webhook on settlement
Partner B2B integrationOAuth2 client-credentials scopes, rate-limit response headers, versioned base path
Video transcoding job202 Accepted + job_id, GET /jobs/{id} polling or callback URL on completion
Bulk user import
  • Batch POST with per-row error array
  • partial success without failing entire upload

9. Decision Signals

Deep-dive API contracts when the interviewer focuses on integration, not just storage:

🎯 Design contract details when:
  • Money or inventory moves — idempotency and conflict codes are non-negotiable.
  • Third parties integrate — publish OpenAPI, webhook schemas, and sandbox environments.
  • Jobs exceed 2 seconds — return 202 + job resource instead of blocking HTTP connection.
  • Lists exceed 10k rows — cursor pagination and optional export-to-file async endpoints.
  • Breaking changes ship — version bump, deprecation header, minimum 90-day sunset for public APIs.

11. Deep Dive (Optional)

Structured Error Envelopes

Avoid returning plain text or generic {"error": "something went wrong"}. Production APIs expose a stable machine code, a safe human message, optional field-level validation details, and a correlation ID for support:

JSON
{
  "error": {
    "code": "INSUFFICIENT_FUNDS",
    "message": "Account balance too low for this transfer.",
    "request_id": "req_8f3a2b",
    "details": [{ "field": "amount", "issue": "exceeds_available_balance" }]
  }
}

Map HTTP status to retry semantics explicitly in docs — 4xx generally non-retryable except 429; 5xx and 503 retryable with backoff. Interviewers notice when you distinguish 401 (who are you?) from 403 (I know you, but you cannot do this).

Long-Running Operations: 202 Accepted Pattern

When work exceeds HTTP timeout budgets (video transcode, report generation), accept the request synchronously and process asynchronously:

  1. POST /exports → 202 Accepted with Location: /jobs/abc123 and body {"status":"queued"}.
  2. Client polls GET /jobs/abc123 until status is completed or failed.
  3. Alternatively, client supplies callback_url; server POSTs signed webhook on terminal state.

Never hold a TCP connection open for minutes — load balancers and mobile networks will kill it.

Batch APIs with Partial Success

Importing 500 users in one request should not fail entirely because row 237 has an invalid email. Return 207 Multi-Status or 200 with a per-item result array:

JSON
{
  "succeeded": 498,
  "failed": 2,
  "results": [
    { "index": 236, "status": "ok", "id": "usr_991" },
    { "index": 237, "status": "error", "code": "INVALID_EMAIL" }
  ]
}

Cap batch size server-side (e.g., max 100 items) and document throughput limits so clients chunk large imports themselves.

Webhook Security & Delivery Guarantees

  • HMAC signature: Include X-Signature: sha256=... over raw body; partners verify with shared secret.
  • Idempotent delivery: Each event carries unique event_id; receivers dedupe in a 72-hour window.
  • At-least-once delivery: Retry with backoff; document that partners must handle duplicates.
  • Replay endpoint: GET /webhooks/events?since=timestamp for partners to backfill after outage.

Rate Limit Transparency

When returning 429, include headers so clients self-throttle without guessing:

X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1717084800
Retry-After: 42

Differentiate per-API-key quotas from per-IP throttling — B2B partners expect contractual limits, not surprise blocks.

HTTP Status Quick Reference

StatusWhenClient Action
400 Bad RequestClient sent malformed JSON or violated field constraints
  • Fix payload
  • do not retry blindly
401 / 403Missing token vs authenticated but forbiddenRefresh credentials or request elevated scope
409 ConflictOptimistic lock version mismatch or duplicate resourceFetch latest state and merge or surface to user
429 Too Many RequestsRate or quota limit exceeded
  • Honor Retry-After header
  • exponential backoff
503 Service Unavailable
  • Overload or dependency outage
  • may be transient
  • Retry with jitter
  • circuit-break after N failures

💬Review

Help Us Improve

How helpful was this walkthrough?

Click a star to rate. We actively use this feedback to refine and update our system design content.

Placeholder
Optional but highly appreciated!

Discussion

Share your thoughts, ask questions, or help others.

Loading comments...