Methodology
API methodology
Public, CORS-enabled, no API key. The deliberate design choices behind /api/v1/.
By Buğra SözeriPublished Updated
Every conversion Convertitive ships is also a JSON endpoint under /api/v1/. The API has been live since FAZ 4 and serves the same factors and formulas as the UI — if a result is correct on the page, it’s correct from the API.
Endpoint design
REST-style. Path describes the resource, query string carries the parameters. Examples:
GET /api/v1/convert/unit?category=length&from=cm&to=inches&value=5GET /api/v1/convert/currency?from=USD&to=EUR&value=100GET /api/v1/convert/color?from=hex&to=rgb&value=%23FF6B35GET /api/v1/categories— list every unit categoryGET /api/v1/health/— service health (uptime + version)
No POST bodies. All inputs are query parameters. Idempotent, cacheable, browser-friendly.
Response envelope
Every successful response uses the same shape:
{
"ok": true,
"data": { /* endpoint-specific */ },
"meta": { /* optional metadata: rateDate, factor, etc. */ }
}Every error response:
{
"ok": false,
"error": {
"code": "INVALID_PARAM",
"message": "Human-readable explanation",
"param": "from"
}
}Standard HTTP status codes: 200 for success, 400 for input errors, 404 for unknown categories/units, 500 only when something genuinely broke. Don’t treat 4xx as retryable.
CORS policy
Access-Control-Allow-Origin: * on every API endpoint. Use it from any origin, including localhost development. No preflight needed because every request is GET with no custom headers — simple-request rules apply.
No authentication
No API key, no OAuth, no signed requests. Every endpoint is anonymous. Three reasons:
- The data isn’t valuable enough to gate. Unit conversion factors are public-domain. ECB rates are publicly republished by ~20 services. Charging for them would be charging for someone else’s data.
- Auth adds friction for the dominant use case. A developer testing a feature, a student scripting a homework comparison, a hobbyist building a tracker — none of them want to register first.
- Rate limits handle abuse.Cloudflare’s defaults plus the trivial computational cost of each conversion mean someone trying to scrape Convertitive can get the data faster by mirroring the public ECB feed directly.
Versioning
The /api/v1/ prefix is intentional. When the response envelope or error shape changes meaningfully, a/api/v2/ships alongside; v1 is supported for at least 12 months past v2’s launch.
Bug-fix and additive changes (new endpoints, new optional fields in responses) ship continuously without a version bump.
The API itself is locale-agnostic — numbers, unit symbols and ISO codes don’t translate — but the editorial pages that document it do. We publish localized variants under per-locale path prefixes and signal them to search engines with hreflang annotations generated from a central translation registry, so a Spanish reader of /es/methodology/api/ gets the same JSON contract described in their language.
Currency rate freshness
Currency endpoints return the ECB mid-market rate cached for one hour via ISR. The meta.rateDate field in every currency response tells you when the rate was published (always a recent ECB business day). For high- precision real-time work, get rates from your broker; for anything else, our cache is fine.
What we won’t add to the API
- POST endpoints for stateful operations (we have no state).
- Bulk endpoints (loop over the singletons; it’s fast enough).
- WebSocket / streaming (the data doesn’t change frequently enough to justify the protocol).
- API keys / paid tiers (see “no authentication” above).
Algorithm details: request lifecycle, end to end
Each API request runs the same six-stage pipeline so the observable behaviour is uniform across endpoints. The stages, in order:
- Edge routing. Cloudflare matches the request against the cached route map and either serves the cached response (currency, popular unit pairs) or forwards the miss to the Next.js function. p50 cache-hit latency: ~25 ms; cache-miss p50: ~70 ms.
- Method & CORS preflight. Reject non-GET methods with 405. Apply the
Access-Control-Allow-Origin: *header on every response per the WHATWG Fetch spec. - Schema validation. Parse query parameters with a Zod-style schema. Missing or ill-formed params return 400 with
{ ok: false, error: { code: "INVALID_PARAM", param } }. - Resolve the conversion. Look up the target conversion in the same registry the UI uses (units, currency, colour, image …). For currency, read the ISR cache; for unit/colour, the function is a deterministic pure computation.
- Format the envelope. Always
{ ok: true, data, meta }. Numbers are serialised as JSON numbers (not strings) per RFC 8259 for native consumer parsing. - Cache headers. Currency responses get
Cache-Control: public, max-age=3600, stale-while-revalidate=86400; unit/colour responses getmax-age=31536000, immutablebecause the math never changes.
Sources & references
The API design follows HTTP semantics from RFC 9110 and HTTP caching rules from RFC 9111. CORS behaviour follows the WHATWG Fetch spec. Response bodies use UTF-8 JSON per RFC 8259. Error-envelope rationale traces back to RFC 7807 (Problem Details). See the Sources block at the foot of the page for the canonical specifications.
Assumptions & limitations
- GET-only. No POST/PUT/DELETE. Anything requiring a body would need a different design and most likely auth.
- No request-body parsing. All inputs are query parameters with URL encoding. Inputs larger than ~2 KB risk hitting URL-length limits on intermediaries.
- Rate limits are network-edge, not per-API-key. High-volume clients sharing a NAT may share the same quota; mirror the relevant data locally for production loads.
- No SLA. The API is best-effort. Cache aggressively and treat 5xx as transient.
- No structured WebSocket / SSE. Polling is fine because the underlying data updates at most hourly.
- JSON only, no XML / msgpack.
Acceptnegotiation is not implemented. - Time-zone-naive timestamps in some legacy responses. All new endpoints emit ISO 8601 with explicit offset; pre-v1.4 fields are UTC by convention but lack a Z suffix.
Live docs at /api/.
Frequently asked questions
- Why no API key?
- Because we don't have a paid tier and don't want one. The API is a SEO weapon (every endpoint links back to a tool page) and a developer-onboarding ramp, not a product. Capping it behind auth would cap our reach.
- What's the rate limit?
- Cloudflare's default DDoS protection (~120 req/min/IP, soft). Beyond that, scrape-rate behaviour gets challenged. For high-volume use, please be polite — cache locally and consider hosting your own copy of the conversion factors (most are public-domain).
Sources & references
Authoritative references cited by this piece. Verified by Buğra Sözeri on the dates shown and re-checked at every deploy.
- RFC 9110 — HTTP Semantics — Defines the HTTP method semantics (GET as safe and idempotent), status code meanings, and caching considerations our API follows.(as of )
- RFC 9111 — HTTP Caching — Underpins our Cache-Control and stale-while-revalidate header strategy for currency endpoints.(as of )
- Fetch Living Standard — CORS protocol — WHATWG specification for the Access-Control-Allow-Origin behaviour our endpoints expose unconditionally.(as of )
- RFC 8259 — JSON — Defines the JSON serialisation our response envelope uses; UTF-8 by default, no comments, strict number formatting.(as of )
- RFC 7807 — Problem Details for HTTP APIs — Reference for the structured-error pattern that informed our { ok: false, error } envelope (we use a flatter shape but the design rationale derives from RFC 7807).(as of )
Related
Published May 15, 2026 · Last reviewed May 31, 2026