Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.replyful.com/llms.txt

Use this file to discover all available pages before exploring further.

Every non-2xx response from the API uses the same envelope. Branch on the HTTP status code and the error.type enum — never on error.message, which is human-readable and may change.

Envelope

{
  "error": {
    "type": "validation_error",
    "code": "invalid_query_parameter",
    "message": "Number must be less than or equal to 100",
    "param": "limit",
    "docUrl": "https://docs.replyful.com/errors/invalid_query_parameter",
    "requestId": "req_01HK7GD3H6ZSQ0Y2A5B3C4DEFG"
  }
}
FieldTypeDescription
typestringHigh-level category. Stable enum — branch on this.
codestringSpecific machine-readable reason. Stable — branch on this for fine-grained handling.
messagestringHuman-readable explanation. May change between releases. Do not parse.
paramstring | undefinedDotted path to the offending field, when applicable.
docUrlstringDeep link to the docs page for this code.
requestIdstringEchoes the response Request-Id header. Quote this in support tickets.
Status code is the source of truth. The API will never return 200 OK with an error body. If your status check passes, the response is success.

Error types

The error.type enum:
TypeStatusWhen it fires
authentication_error401Missing or invalid API key.
validation_error422Request was well-formed but failed validation.
rate_limit_error429Too many requests. See Rate limits.
api_error5xxServer-side fault. Safe to retry idempotent calls with backoff.
Additional type values (invalid_request_error, permission_error, not_found, idempotency_error) are reserved for endpoints that are not yet shipped.

Error codes shipped today

CodeTypeMeaning
missing_api_keyauthentication_errorThe Authorization header is absent or does not start with Bearer .
invalid_api_keyauthentication_errorThe key is malformed, unknown, or archived.
invalid_query_parametervalidation_errorA query parameter failed validation. The param field names the offender.
invalid_cursorvalidation_errorThe startingAfter cursor could not be decoded.
conflicting_date_rangevalidation_errorA request mixed createdAt[...] and updatedAt[...] filters. Pick one.
too_many_requestsrate_limit_errorRate limit exceeded. Honor Retry-After.
internal_server_errorapi_errorUnexpected server-side fault. Retry with backoff.

Examples

401 missing_api_key

{
  "error": {
    "type": "authentication_error",
    "code": "missing_api_key",
    "message": "Missing Authorization header. Provide `Authorization: Bearer rfl_…`.",
    "docUrl": "https://docs.replyful.com/errors/missing_api_key",
    "requestId": "req_..."
  }
}

422 invalid_query_parameter

{
  "error": {
    "type": "validation_error",
    "code": "invalid_query_parameter",
    "message": "Number must be less than or equal to 100",
    "param": "limit",
    "docUrl": "https://docs.replyful.com/errors/invalid_query_parameter",
    "requestId": "req_..."
  }
}

422 conflicting_date_range

{
  "error": {
    "type": "validation_error",
    "code": "conflicting_date_range",
    "message": "Cannot filter by both createdAt and updatedAt date ranges.",
    "docUrl": "https://docs.replyful.com/errors/conflicting_date_range",
    "requestId": "req_..."
  }
}

429 too_many_requests

{
  "error": {
    "type": "rate_limit_error",
    "code": "too_many_requests",
    "message": "Rate limit exceeded. Slow down and try again shortly.",
    "docUrl": "https://docs.replyful.com/errors/too_many_requests",
    "requestId": "req_..."
  }
}

Handling errors

A pragmatic client:
async function callReplyful(path: string, init?: RequestInit) {
  const res = await fetch(`https://api.replyful.com${path}`, {
    ...init,
    headers: {
      Authorization: `Bearer ${process.env.REPLYFUL_API_KEY}`,
      ...init?.headers,
    },
  });

  if (res.ok) {
    return res.json();
  }

  const body = await res.json().catch(() => ({}));
  const requestId = res.headers.get("Request-Id") ?? body.error?.requestId;

  // Branch on type for high-level handling.
  switch (body.error?.type) {
    case "authentication_error":
      throw new Error(`Replyful auth failed (${requestId}). Check your API key.`);
    case "rate_limit_error": {
      const retryAfter = Number(res.headers.get("Retry-After") ?? "1");
      throw new RateLimitError(retryAfter, requestId);
    }
    case "validation_error":
      throw new Error(`Validation failed: ${body.error.message} (${requestId})`);
    default:
      throw new Error(`Replyful API error (${requestId}): ${body.error?.message ?? res.statusText}`);
  }
}

Request IDs

Every response carries a Request-Id header (e.g. req_01HK7GD3H6ZSQ0Y2A5B3C4DEFG). The same value appears in the error body’s requestId field. We retain request traces for 90 days — quote the ID in support emails to get the exact context of a failing call.