Designing a public API: the decisions behind our launch

— Field Operations Editor

Published: 5/2/2026 • Last reviewed: 5/2/2026 • 8 min read

Why we chose REST over GraphQL, headers over query strings, and rolling quotas over calendar months.

Designing a public API: the decisions behind our launch

The audience drives the style

Our API is consumed by HR and fintech developers who typically integrate five or six APIs per project.[^irs-2025] They don't want to learn a new query language or wire up resolvers — they want cURL, fetch, and requests. So we went with classic REST: five endpoints, plain JSON, OpenAPI 3.1. For our use case (calculate distance and reimbursement), GraphQL would add nothing. It would only introduce another client and a learning curve.

Auth in the header, not in the URL

API keys passed in query strings end up in server logs, browser referers, and screenshots. Moving them to `X-API-Key` (with `Authorization: Bearer …` as a fallback) removes most of that leakage without complicating the developer's life — every HTTP client supports first-class headers.

Rolling 30-day quotas, not calendar months

We chose rolling 30 days over calendar months because the calendar creates artificial spikes at the start of each month. With a rolling window, the limit distributes naturally. The window resets when the oldest request falls outside the last 30 days — a simple implementation in the database with a `usage_window_start` plus counter.

A free tier large enough to prove value

1,000 requests per window comfortably covers a prototype, a hackathon, or a 10-person team testing an integration. Beyond that we expect a human conversation — anyone consuming 5,000+ req/month usually already has SLA, IP-allowlist, or key-rotation requirements that deserve a tailored partner plan.

An integrity hash on every receipt

The `POST /receipt` endpoint returns a SHA-256 of the input fields. Auditors can recompute the hash locally and compare — any alteration to the PDF is instantly detectable. It's the same technique banks use for immutable statements.

OpenAPI before code

We designed the OpenAPI spec first, generated TypeScript types from it, and only then wrote the handlers. That guarantees the documentation never drifts — it's the contract.

What we left out (for now)

Webhooks, batch endpoints, and multi-stop route optimization. Each has real demand but adds complexity. We'll ship them as partners request — and every release will land in the [public changelog](/api/changelog) with an RSS feed so nobody has to ask us.

Quilometragem
Loading Quilometragem…