Browse all docs
API Reference

Error Codes and Handling

6 min read

Error Codes and Handling

Every non-2xx response from the Loomstack API uses the same envelope, so one error handler covers the whole API. This reference lists each error code, its cause and fix, and — critically — which errors are retryable and which mean your request will never succeed as written.

The Error Envelope

{
  "success": false,
  "error": {
    "code": "VALIDATION_FAILED",
    "message": "title must be between 1 and 300 characters",
    "field": "title",
    "request_id": "req_a81f42"
  }
}
  • code — stable, machine-readable string; branch your logic on this, never on message
  • field — present on validation errors, naming the offending field
  • request_id — include this when contacting support; it lets the team find your exact request in server logs

4xx Errors: Fix the Request

These indicate a problem with your request. Do not retry unchanged — the result will be identical.

StatusCodeCause and fix
400VALIDATION_FAILEDA field failed validation; see field and message
400MALFORMED_JSONBody isn’t valid JSON — check quoting and trailing commas
401INVALID_API_KEYKey is wrong, revoked, or missing the Bearer prefix
401KEY_EXPIREDKey passed its expiry date; generate a new one
403INSUFFICIENT_SCOPEKey lacks the required scope (e.g., calling POST /v1/projects without write:projects) — check with GET /v1/me
403PLAN_LIMITFeature not on your plan (e.g., SSO endpoints on Pro)
404PROJECT_NOT_FOUND, TASK_NOT_FOUND, USER_NOT_FOUNDBad ID, or the key’s user can’t see that resource — private projects return 404, not 403, to avoid leaking existence
409PROJECT_ARCHIVEDWrites against an archived project; restore it first
409NO_SEATS_AVAILABLEInvite would exceed the seat count; add seats or free one
409DUPLICATE_WEBHOOKA subscription with the same URL and events already exists
422STATE_NOT_IN_WORKFLOWThe state value doesn’t exist in that project’s workflow — fetch valid states via GET /v1/projects/{projectId}

429 and 5xx Errors: Safe to Retry

StatusCodeBehavior
429RATE_LIMIT_EXCEEDEDWait the Retry-After seconds, then retry
500INTERNAL_ERRORTransient server fault — retry with backoff
503SERVICE_UNAVAILABLEMaintenance or overload — retry with backoff, check status.loomstack.com

A solid retry policy: retry only 429, 500, and 503; use exponential backoff with jitter (e.g., 1s, 2s, 4s, 8s); cap at 5 attempts; and make write retries idempotent by passing an Idempotency-Key header:

curl -X POST https://api.loomstack.com/v1/projects/proj_884/tasks \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Idempotency-Key: 7f3a9c1e-order-4402" \
  -H "Content-Type: application/json" \
  -d '{"title": "Investigate alert #4402"}'

If a retry re-sends the same Idempotency-Key within 24 hours, the API returns the original result instead of creating a duplicate.

Handling Partial Failures in Batch Requests

Batch endpoints (POST /v1/projects/{projectId}/tasks/batch) return 207 when some items fail:

{
  "success": false,
  "results": [
    { "index": 0, "success": true, "data": { "id": "task_901" } },
    { "index": 1, "success": false, "error": { "code": "VALIDATION_FAILED", "field": "due_date" } }
  ]
}

Iterate results and re-submit only the failed indexes after fixing them — never re-send the whole batch, or you’ll duplicate the successful items.

Logging Recommendations

  • Log code, request_id, and the endpoint for every error — not the full request body, which may contain sensitive content
  • Alert on sustained 401/403 (a rotated or revoked key) and on 5xx rates above ~1%
  • Treat a sudden spike of 404s after a deploy as a likely ID-mapping bug on your side

Summary

Branch on error.code, never on message text. Treat 4xx as permanent until the request changes, retry 429/500/503 with jittered backoff, and use Idempotency-Key so retried writes can’t duplicate. For batch calls, handle per-item results, and always keep the request_id — it’s your fast path through support.

Was this helpful?