API conventions
Formats, status codes, errors, validation, and streaming — the rules every endpoint follows.
A handful of conventions hold across the entire web app API. Learn them once and every endpoint becomes predictable.
Requests and responses
- JSON in, JSON out. Send
Content-Type: application/json; responses are JSON unless they're a stream or a binary download. - Resource-shaped URLs. Collections and items follow REST-ish paths, e.g.
/api/calendarand/api/calendar/[id]. - Standard verbs.
GETto read,POSTto create,PATCHto update,DELETEto remove.
Status codes
| Code | Meaning |
|---|---|
200 | Success, body included |
201 | Created |
400 | Bad request — your input failed validation |
401 | Not authenticated |
403 | Authenticated, but not allowed |
404 | Not found (or not yours to see) |
429 | Rate-limited — slow down |
503 | A dependent service is unavailable (e.g. an unconfigured integration) |
Error shape
Errors return a consistent JSON body so clients can handle them uniformly:
{
"error": {
"message": "Invalid request body",
"status": 400
}
}Treat message as human-readable, not machine-parseable. Branch on the HTTP
status code, not on the text of the message.
Validation
Request bodies are checked against strict schemas before any work happens.
Unexpected or malformed fields are rejected with a 400 rather than being
silently dropped or stored — so a request either fully matches the contract or
fails fast.
Streaming responses
AI endpoints stream. Instead of waiting for the full answer, the server sends tokens as they're generated, so chat and generation feel immediate.
Open the request
Call the endpoint as usual; the response is a readable stream rather than a single JSON blob.
Consume chunks
Read the stream as it arrives and render progressively.
Handle completion
The stream closes when the response is done (or aborts if the user interrupts).
Graceful degradation
Optional integrations (telemedicine, calendar sync, certain scan modes) are
configuration-gated. When a dependency isn't set up or is unreachable, the
endpoint returns a clear, handled state — typically a 503 or a "coming soon"
payload — instead of crashing. Build clients that treat these as expected.
Good to know
This is why a missing third-party key never takes the whole app down: each integration probes its own availability and the UI gates on the real answer, not on "is a key present."