The Stripe API: A Masterclass in Schema Design
Stripe processes billions of dollars in payments, and thousands of companies integrate with their API. A single breaking schema change could cascade into production failures for all of them. So Stripe treats their API schema like a legal contract: every field has a type, a description, and a guarantee of how it will behave. Their response format has not changed in over a decade. This discipline is what separates APIs that developers love from APIs that developers dread.
Why does schema design matter so much? Consider the alternative: a payment API that sometimes returns amounts as strings and sometimes as integers, or that wraps errors in a different structure depending on the error type. Every client integration becomes a spaghetti of special cases. Schema design is not about aesthetics - it is about making the right thing easy and the wrong thing impossible.
The Schema Contract
API Schema Design Patterns:
Request Schema (strict):
POST /api/users
{
"name": string, // required, 1-100 chars
"email": string, // required, valid email format
"role": enum, // optional, ["admin","user","viewer"]
// default: "user"
"metadata": object // optional, max 50 keys
}
Response Schema (consistent envelope):
{
"data": {
"id": "usr_abc123", // always return resource ID
"name": "Alice",
"email": "alice@co.com",
"role": "user",
"created_at": "2024-01-15T10:30:00Z" // ISO 8601 always
},
"meta": {
"request_id": "req_xyz789" // for debugging/support
}
}
Error Schema (predictable):
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Email format is invalid",
"field": "email" // which field failed
}
}
Client parsing rule: check for 'error' key first, then read 'data'
Naming Conventions and Field Types
Consistency in naming eliminates an entire class of bugs. Use snake_case everywhere (created_at, not createdAt) or camelCase everywhere - never mix. Timestamps should always be ISO 8601 strings with timezone (2024-01-15T10:30:00Z), not Unix epoch integers that clients have to guess about. Money should use the smallest currency unit as integers (amount: 1499 means $14.99) to avoid floating-point rounding. IDs should be prefixed strings (usr_abc123, pay_xyz789) so engineers can tell the resource type from the ID alone.
Input Validation Layers
Good schemas validate at three layers. First, structural validation: is the JSON well-formed and does it contain the required fields? Second, type validation: is the email field actually a valid email, is the role one of the allowed enum values? Third, business validation: does this user already exist, does the referenced organization ID point to a real organization? Reject bad data as early as possible with clear error messages. Stripe returns the exact field that failed, the validation rule that was violated, and a human-readable message - all in a predictable error structure.
Schema Evolution Rules
Safe vs Breaking Schema Changes:
Change Type Safe? Why
--------------------------- ----- ----------------------------
Add field to response YES Clients ignore unknown fields
Add optional request field YES Old clients don't send it
Remove response field NO Clients relying on it break
Change field type NO string->int breaks parsing
Make optional field required NO Old clients don't send it
Rename a field NO Same as remove + add
Safe evolution strategy:
1. Add new field alongside old field
2. Deprecate old field (document, log warnings)
3. Wait 6-12 months (or 2 API versions)
4. Remove old field in new version
OpenAPI and Schema Documentation
Machine-readable schemas (OpenAPI/Swagger) are not optional for production APIs - they are essential. An OpenAPI spec lets you auto-generate client SDKs in any language, validate requests against the schema in middleware, auto-generate API documentation, and run contract tests that catch breaking changes in CI before they ship. Tools like Stoplight, Redocly, and SwaggerHub make this easy. The investment in writing a proper spec pays for itself in fewer integration bugs, faster onboarding for new developers, and confidence that schema changes will not break existing clients.
Interview Tip
API schemas are contracts: strict input validation (reject bad data early), consistent response envelopes (always wrap in {data, meta, error}), and additive-only evolution (never remove or rename fields without versioning). Mention OpenAPI/Swagger for machine-readable schema documentation. The key principle: make your API predictable so clients can parse responses without reading documentation for every endpoint.
Key Takeaway
Treat your API schema like a published contract. Validate inputs at three layers (structural, type, business), use consistent naming and types, wrap every response in a standard envelope, and evolve schemas additively. Breaking changes require versioning - never remove or rename fields in place.