Tapemetric

HTTP API

Error codes

Every HTTP status Tapemetric returns, what triggered it, and how to handle it.

Error response shape

json
{
  "detail": "invalid api key",
  "code": "AUTH_INVALID_KEY",
  "request_id": "req_a1b2c3d4e5f6"
}

Include the request_id when you contact support — it lets us pull your exact request from our logs.

HTTP status codes

StatuscodeAction
400VALIDATION_ERRORFix payload; don’t retry as-is
401AUTH_MISSINGAdd auth header
401AUTH_INVALID_KEYCheck key not revoked; recreate if needed
401AUTH_TOKEN_EXPIREDRefresh JWT via /v1/auth/login
403TENANT_INACTIVEContact billing
403QUOTA_EXCEEDEDUpgrade plan or wait for reset
403SCOPE_DENIEDKey lacks required scope
404NOT_FOUNDResource doesn’t exist for this tenant
409CONFLICTe.g. slug already taken
413BATCH_TOO_LARGESplit into ≤500 event batches
422EVENT_SCHEMA_ERRORA field failed validation — see errors array
429RATE_LIMITExponential backoff starting at 1s
500SERVER_ERRORRetry with backoff; open a ticket if it persists
503DEGRADEDIngest briefly down; SDK queues automatically

Validation errors

json
{
  "detail": "validation error",
  "code": "VALIDATION_ERROR",
  "errors": [
    { "loc": ["events", 0, "event_type"], "msg": "field required" },
    { "loc": ["events", 2, "ts"], "msg": "invalid iso8601 timestamp" }
  ]
}

Retry strategy

For retriable codes (429, 500, 502, 503, 504), the SDK uses exponential backoff starting at 1s, doubling up to 60s, with jitter. Custom HTTP clients should do the same.

typescript
async function retryable<T>(fn: () => Promise<Response>, max = 6): Promise<Response> {
  let delay = 1000;
  for (let i = 0; i < max; i++) {
    const res = await fn();
    if (res.ok) return res;
    if (![429, 500, 502, 503, 504].includes(res.status)) return res;
    await new Promise((r) => setTimeout(r, delay + Math.random() * 500));
    delay = Math.min(delay * 2, 60_000);
  }
  throw new Error('retry budget exhausted');
}

Rate limit headers

Every response includes:

  • X-RateLimit-Limit — requests allowed per minute
  • X-RateLimit-Remaining — requests left in current window
  • X-RateLimit-Reset — UTC epoch when the window resets