Most API responses are judged in microseconds and bytes. Ours is judged in picas. The Risume API takes structured resume data and returns a typeset PDF, and that one design decision — the response is a page, not a payload — quietly inverted half of what we knew about building services. These are the notes we wish we'd had.
Determinism is the contract
If you POST the same resume twice, you must get byte-identical PDFs back. That sounds obvious and is quietly hard: font rasterization, hyphenation dictionaries, even floating-point line-break math all have to be pinned. We version the entire rendering pipeline — fonts, dictionaries, algorithm — as a single artifact, and the API lets you pin to it. A resume rendered in January must not reflow in March because a hyphenation dictionary got an update. Nobody's work history should be at the mercy of a minor version bump.
What's an error, when the response is paper?
A JSON API fails loudly: 422, message, done. A rendering API can fail silently and beautifully — the PDF generates, and the third job is half a line past the page boundary. So we made overflow a first-class, structured error: the API tells you the content doesn't fit, by how much, and which sections could absorb the cut. What it will never do is silently shrink the font. Every layout decision is either specified by the template or reported to the caller. There is no "the renderer decided."
A rendering API can fail silently and beautifully. Overflow had to become a loud, structured error.
The shape that fell out
- Content and presentation never mix. The request body is pure data — roles, dates, bullets. Templates are referenced by ID and versioned like the renderer.
- Dry-run layout. A /layout endpoint returns page-fit metrics without rendering, so integrators can validate before generating.
- Idempotent by construction. Same input, same pipeline version, same bytes — which makes caching trivial and audit trails honest.
The through-line: when your response is a document someone will print and hand to a stranger, correctness stops being an availability number. It's whether the page can be wrong. The API's whole job is to make that impossible by construction.