BuildCalc API

Errors & retries

RFC 7807 problem+json responses + idempotency safety

Error format (RFC 7807)

All non-2xx responses follow application/problem+json:

{
  "type": "https://docs.buildcalcapi.dev/errors/422",
  "title": "Validation Error",
  "status": 422,
  "detail": "One or more request parameters failed validation.",
  "errors": [
    {"type": "missing", "loc": ["body", "length_ft"], "msg": "Field required"}
  ],
  "instance": "/v1/calc/concrete/yards",
  "request_id": "req_..."
}
StatusMeaningWhen to retry
400Bad request (malformed JSON, mutually-exclusive fields)No
401Missing / invalid / revoked API keyNo — rotate key
403Insufficient tier (e.g., calling admin from free tier)No — upgrade
404Unknown calc kind or resourceNo
409Conflict (duplicate signup, idempotency-key collision)No
422Validation error (Pydantic)No — fix payload
429Rate limit exceeded — check Retry-After headerYes, after delay
500Server errorYes, with backoff
502/503/504Upstream / dependency errorYes, with backoff

Idempotency

Mutating endpoints (signup, key rotation, billing actions) accept Idempotency-Key: <uuid-or-random-string> per the IETF Idempotency-Key HTTP header draft.

  • First request with a fresh key executes normally and the response is cached
  • Subsequent retries with the same key return the cached response (same status, same body) for 24 hours
  • Different request body with same key returns 409 Conflict (catch bugs)

Safe to retry on network drop, 5xx, or client crash without double-charging or double-creating.

Rate limiting

Every response (success and error) includes forward-looking rate limit headers per the IETF draft-ietf-httpapi-ratelimit-headers:

RateLimit-Limit: 60
RateLimit-Remaining: 47
RateLimit-Reset: 60
RateLimit-Policy: 60;w=60
  • RateLimit-Limit — current window limit (per-minute, matches your tier)
  • RateLimit-Remaining — calls remaining in current window
  • RateLimit-Reset — seconds until the window resets (token-bucket is continuous refill; this reports the full window duration)
  • RateLimit-Policy — full policy descriptor (<limit>;w=<seconds>)

429 Too Many Requests adds the standard backoff hint:

Retry-After: 60

Token-bucket algorithm — burst capacity = 2× the RPM limit. Refill is continuous (not on minute boundaries). Cleanest retry strategy: trust RateLimit-Remaining to self-throttle BEFORE hitting 429; on 429, use exponential backoff respecting Retry-After.

request_id

Every response (including errors) returns a request_id field in the RFC 7807 body. Include it in any support ticket / GitHub issue for fast diagnosis. Logs are queryable by request_id for 90 days.

On this page