Warpflow
For Developers

Errors

HTTP status codes, error response format, and common error codes for the Warpflow Signals API.

Error response format

Standard application errors use this JSON structure:

{
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable description of what went wrong"
  }
}
FieldTypeDescription
error.codestringMachine-readable error code (uppercase, underscored)
error.messagestringHuman-readable explanation
error.detailsunknownPresent on some errors—for a 400, the failing fields

The HTTP status carries the status code; there is no status field in the body. Branch on error.code, not on the message text.

Standalone Zapier action failures are an exception: they return 400 with { "success": false, "error": "action failure text" }. Successful actions return success and data. Inspect the endpoint contract before assuming a nested error object.

HTTP status codes

2xx — Success

StatusMeaning
200Request processed successfully
201Resource created or email sent successfully
202Accepted — event queued for async processing

4xx — Client errors

StatusCodeMeaningWhat to do
400VALIDATION_ERRORRequest body failed schema validation. The message field describes which field is missing or malformedCheck the payload against the endpoint's expected schema
401UNAUTHORIZEDMissing or invalid Authorization headerVerify your API key is correct and active. Check that the header format is Bearer <key>
403FORBIDDENValid authentication but insufficient permissions for this operationCheck that your key has access to the requested tenant
403HIPAA_RESTRICTEDThis endpoint is disabled for HIPAA-enabled tenantsEmail remains unavailable, including healthcare industry presets; OAuth does not bypass this restriction. Other protected-health-data integrations require supported authenticated access
404NOT_FOUNDThe requested resource doesn't existCheck the tenant_id, lead_id, contact_id, or other identifiers in the URL
409CONFLICTResource conflict (e.g., attempting to create a duplicate)The resource already exists. Use PATCH to update instead
429RATE_LIMITEDToo many requestsWait for the duration specified in the Retry-After header before retrying

5xx — Server errors

StatusCodeMeaningWhat to do
500INTERNAL_ERRORUnexpected server errorRetry after a short delay. If persistent, contact support
503SERVICE_UNAVAILABLETemporary service disruption (upstream dependency failure)Retry with exponential backoff

Common scenarios

The examples illustrate the standard error envelope. Message text can vary; branch on the error code and HTTP status.

Invalid API key

401 Unauthorized
{
  "error": { "code": "UNAUTHORIZED", "message": "Invalid or expired token" }
}

Causes:

  • Key was revoked or rotated past the 72-hour grace period
  • Key prefix doesn't match any active key
  • Missing Bearer prefix in the Authorization header

Missing required field

400 Bad Request
{
  "error": { "code": "VALIDATION_ERROR", "message": "Invalid payload" }
}

Fix: For the Zapier pipeline and standalone actions, include a nonempty top-level message. See Zapier integration for the request schema.

HIPAA tenant accessing email

403 Forbidden
{
  "error": { "code": "HIPAA_RESTRICTED", "message": "Email integration is not available for HIPAA-compliant tenants" }
}

Why: The product does not support this email integration for HIPAA-enabled tenants. Using another credential does not enable it. Contact support to discuss supported alternatives.

Rate limited

429 Too Many Requests
Retry-After: 30
{
  "error": { "code": "RATE_LIMITED", "message": "Too many requests. Please try again later." }
}

Fix: Implement exponential backoff or throttle your request rate. For bulk operations, add a short delay between requests.

Retry strategy

For read-only GET requests with transient errors (429, 500, 503), use exponential backoff. Do not automatically repeat mutations: a failed response can follow a completed send or write. Retry those only when the endpoint supports an idempotency mechanism.

async function fetchWithRetry(url, options = {}, maxRetries = 3) {
  if (options.method && options.method.toUpperCase() !== 'GET') {
    throw new Error('This retry helper supports read-only GET requests')
  }
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    const response = await fetch(url, options)

    if (response.ok) return response.json()

    if (response.status === 429 || response.status >= 500) {
      const retryAfter = response.headers.get('Retry-After')
      const delay = retryAfter
        ? parseInt(retryAfter) * 1000
        : Math.min(1000 * Math.pow(2, attempt), 30000)
      await new Promise((resolve) => setTimeout(resolve, delay))
      continue
    }

    // Non-retryable error
    throw new Error(`API error: ${response.status}`)
  }
  throw new Error('Max retries exceeded')
}

Do not retry 400, 401, 403, or 404 errors — these indicate a problem with the request that won't be fixed by retrying.

On this page

We use cookies to understand how you use our site and improve your experience. Privacy Policy