Enterprise API Design: 8 Principles That Scale
Eight battle-tested API design principles for enterprise systems — REST vs gRPC, versioning, pagination, error handling, and more.
APIs are the contracts that hold enterprise systems together. A poorly designed API creates years of tech debt; a well-designed one becomes a competitive advantage. After building and reviewing hundreds of enterprise APIs, we have distilled the principles that separate APIs that scale from those that become liabilities.
These eight principles are framework-agnostic, though we will reference .NET, Azure API Management, and OpenAPI where relevant.
Principle 1: Choose Your Protocol With Intent
REST and gRPC solve different problems. Choosing the wrong one for the context is a costly mistake.
Use REST (HTTP/JSON) when:
- Your consumers are external or browser-based
- You need broad tooling ecosystem support
- Human readability of payloads matters for debugging
- You are building a public API or partner integration
Use gRPC (HTTP/2 + Protobuf) when:
- Both producer and consumer are services you control
- Low latency and high throughput are critical (gRPC is 5-10x faster for serialization)
- You need bidirectional streaming
- Strong typing across polyglot services is valuable
Our default: REST for north-south traffic (client-to-service), gRPC for east-west traffic (service-to-service). This combination gives you the best of both worlds.
Principle 2: Version From Day One
Do not ship an API without a versioning strategy. Changing this later is orders of magnitude harder.
Recommended approach — URL path versioning:
GET /api/v1/orders/{id}
GET /api/v2/orders/{id}We prefer URL path versioning over header-based versioning for one reason: visibility. Operations teams, load balancers, and logging pipelines can route and filter by version without inspecting headers.
Version lifecycle rules:
- Support N and N-1 simultaneously. Deprecate N-2 with a 6-month sunset notice.
- Never break a published version. Additive changes (new fields, new endpoints) are fine. Removing or renaming fields requires a new version.
- Document the migration path between versions explicitly. A changelog is not enough — provide a migration guide.
Principle 3: Design Pagination for Large Datasets
Enterprise APIs deal with datasets that cannot fit in a single response. Pagination is not optional.
Cursor-based pagination (recommended for most cases):
{
"data": [...],
"pagination": {
"next_cursor": "eyJpZCI6MTAwfQ==",
"has_more": true
}
}Why cursor over offset?
- Offset pagination breaks when data is inserted or deleted between requests
- Cursor pagination maintains consistency and performs better on large tables (no
OFFSETscan) - Cursors are opaque — you can change the underlying implementation without breaking clients
Rules:
- Default page size: 25 items. Maximum: 100. Let clients specify within this range.
- Always include total count as a separate, optional field (it requires an extra query, so let clients opt in via
?include=total_count). - Sort order must be deterministic. If sorting by
created_at, add a tiebreaker (e.g.,id) to avoid ambiguous ordering.
Principle 4: Standardize Error Responses
Nothing frustrates API consumers more than inconsistent error formats. Adopt RFC 9457 (Problem Details) as your standard:
{
"type": "https://api.example.com/errors/insufficient-funds",
"title": "Insufficient Funds",
"status": 422,
"detail": "Account balance of 30.00 EUR is less than the requested transfer of 50.00 EUR.",
"instance": "/transfers/abc123",
"traceId": "00-4bf92f3577b34da6-00f067aa0ba902b7-01"
}Non-negotiable rules:
- Every error response follows the same schema. No exceptions.
- Include a
traceIdso support teams can correlate errors with distributed traces. - Use appropriate HTTP status codes. 400 for validation errors, 401 for authentication, 403 for authorization, 404 for not found, 409 for conflicts, 422 for business rule violations, 429 for rate limiting.
- Never expose stack traces or internal implementation details in production error responses.
Principle 5: Implement Rate Limiting Transparently
Every enterprise API needs rate limiting. Without it, a single misbehaving client can bring down your entire platform.
Implementation approach:
- Use the token bucket algorithm for flexible burst handling.
- Return rate limit headers on every response, not just 429 responses:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 742
X-RateLimit-Reset: 1709913600
Retry-After: 30- Differentiate limits by tier: internal services get higher limits than external consumers.
- Apply limits at multiple levels: per-client, per-endpoint, and global. A client should not be able to monopolize a single expensive endpoint.
Practical note: Azure API Management handles this natively with its
rate-limit-by-keypolicy. Do not re-implement what your gateway already provides.
Principle 6: Invest in OpenAPI as the Source of Truth
An OpenAPI specification is not documentation — it is a contract. Treat it as a first-class artifact.
Best practices:
- Design-first, not code-first. Write the OpenAPI spec before implementing the endpoint. This forces you to think about the consumer experience.
- Generate client SDKs from the spec using tools like NSwag, Kiota, or openapi-generator. Handwritten clients drift.
- Validate requests and responses against the spec in your CI pipeline. If the implementation does not match the spec, the build fails.
- Include examples for every endpoint. Real examples with realistic data, not
"string"placeholders.
Tooling we recommend:
- Spectral for linting OpenAPI specs against your organization's API standards
- Kiota (Microsoft) for generating type-safe API clients
- Stoplight Studio for visual API design
Principle 7: Design for Backward Compatibility
Backward compatibility is not a nice-to-have — it is a requirement for any API with more than one consumer.
Safe changes (non-breaking):
- Adding new optional fields to response bodies
- Adding new endpoints
- Adding new optional query parameters
- Adding new enum values (if consumers ignore unknown values)
Breaking changes (require a new version):
- Removing or renaming fields
- Changing field types
- Making optional fields required
- Changing the meaning of existing fields
- Removing endpoints
Defensive patterns:
- Use
additionalProperties: truein JSON Schema to allow unknown fields. Clients should ignore fields they do not recognize. - Test backward compatibility in CI. Record API snapshots and diff against them on every pull request. Tools like Optic automate this.
- Communicate deprecation via response headers:
Deprecation: trueandSunset: Sat, 01 Nov 2026 00:00:00 GMT.
Principle 8: Secure by Default, Not by Afterthought
API security is not a feature — it is a baseline.
Minimum security requirements:
- OAuth 2.0 + OpenID Connect for authentication. No API keys as the sole authentication mechanism for production APIs.
- Scope-based authorization: define granular scopes (e.g.,
orders:read,orders:write) and enforce them at every endpoint. - TLS 1.3 everywhere. No exceptions. No fallback to 1.2 unless absolutely required.
- Input validation on every field. Validate types, ranges, lengths, and patterns. Reject early.
- CORS with explicit origins. Never use
*in production.
Often overlooked:
- Request size limits: set a maximum payload size (e.g., 1 MB) to prevent abuse.
- Field-level encryption for PII in transit — especially relevant under GDPR.
- Audit logging: log every write operation with the authenticated identity, timestamp, and before/after state.
Putting It All Together
These eight principles form a coherent API strategy:
| Principle | Key Decision |
|---|---|
| Protocol | REST externally, gRPC internally |
| Versioning | URL path, support N and N-1 |
| Pagination | Cursor-based, max 100 items |
| Errors | RFC 9457 Problem Details |
| Rate Limiting | Token bucket, transparent headers |
| OpenAPI | Design-first, CI-validated |
| Compatibility | Snapshot testing in CI |
| Security | OAuth 2.0, scoped, TLS 1.3 |
At CC Conceptualise, we help enterprise teams define and implement API standards that hold up at scale. If your API landscape needs structure, let us know.