Developer integration reference
Handle FARPY API errors safely
This reference covers error-envelope parsing, retry decisions, request tracing, rate limits, idempotency, terminal render states, and recovery boundaries. For the shorter operational map, use the API error guide.
Error-envelope fields
FARPY errors expose a machine-readable code, a human-readable message, a retryable decision, a suggested action, and a request identifier. Integrations should parse these values instead of branching only on English message text.
{
"error": {
"code": "machine_readable_code",
"message": "Human-readable explanation",
"retryable": false,
"suggested_action": "Correct the request and submit again",
"request_id": "request identifier"
}
}codeidentifies the error category for program logic.messageexplains the condition to a human operator.retryabletells the caller whether another attempt may succeed without changing the request.suggested_actiondescribes the next corrective step.request_idconnects client logs to one server request.
Parse non-success responses defensively
Read the response body once, attempt JSON parsing, retain the HTTP status, and preserve the Retry-After header when present. Do not assume that every proxy, timeout, or upstream failure will contain the full normal application error shape.
class FarpyApiError extends Error {
constructor(response, body) {
const detail = body?.error ?? body ?? {};
super(detail.message ?? `HTTP ${response.status}`);
this.status = response.status;
this.code = detail.code ?? "unknown_error";
this.retryable = detail.retryable === true;
this.suggestedAction = detail.suggested_action ?? null;
this.requestId = detail.request_id ?? null;
this.retryAfter = response.headers.get("retry-after");
}
}
async function farpyRequest(url, options = {}) {
const response = await fetch(url, options);
const text = await response.text();
let body = null;
try {
body = text ? JSON.parse(text) : null;
} catch {
body = { message: text || "Non-JSON response" };
}
if (!response.ok) {
throw new FarpyApiError(response, body);
}
return body;
}Application logs should retain status, code, request ID, retryable, and suggested action. Do not log API keys, session cookies, uploaded file contents, signing secrets, or full authorization headers.
Separate transport errors from render outcomes
An HTTP failure means the current API operation did not complete as requested. A terminal render state is different: render creation or submission may succeed, after which the job can later become completed, failed, or cancelled.
Do not classify a render.failed webhook or canonical failed job object as an HTTP transport exception. Store it as the terminal outcome of an existing render. Likewise, cancellation is a distinct terminal state and should not be merged into generic failure reporting.
Retry decision order
- Confirm that the operation actually failed.
- Read the HTTP status and machine-readable error code.
- Check the retryable field.
- Apply the suggested action when correction is required.
- Respect Retry-After for rate-limited responses.
- Confirm that repeating the operation is idempotent.
- Use bounded attempts with increasing delay.
- Stop and surface the request ID when the condition persists.
try {
const render = await farpyRequest(
"https://farpy.com/v1/renders",
requestOptions
);
return render;
} catch (error) {
console.error({
status: error.status,
code: error.code,
request_id: error.requestId,
suggested_action: error.suggestedAction,
});
if (!error.retryable) {
throw error;
}
if (error.status === 429 && error.retryAfter) {
// Respect Retry-After before retrying.
}
// Retry only with bounded attempts and idempotency protection.
throw error;
}HTTP recovery categories
Authentication and authorization failures
HTTP 401 generally requires valid authentication before another attempt. Repeating the same invalid or revoked credential is not a useful retry. Resolve the API key or authenticated session first.
Missing resources
HTTP 404 means the referenced resource was not found or is not available to the authenticated caller. Confirm the identifier, workspace ownership, and route before retrying.
Request validation failures
HTTP 400 and related client-input responses require request correction. Validate fields, frame boundaries, file metadata, supported renderer values, and required state transitions.
Upload limits
HTTP 413 means the upload exceeds the supported limit. The current public upload ceiling is 100 MiB. Retrying the same oversized payload without changing it cannot succeed.
Rate limiting
HTTP 429 is a temporary traffic-control response. Respect Retry-After, reduce request pressure, and avoid multiple workers immediately repeating the same operation.
Temporary server conditions
A retryable server-side condition may succeed later. Use bounded exponential delay, preserve idempotency controls, and stop after a defined attempt limit instead of retrying forever.
Idempotency and request fingerprints
Render creation supports idempotency protection. Reuse the same idempotency key only for the same logical operation. Do not attach one key to different files, frame ranges, prices, or renderer settings.
The request fingerprint protects the identity of the intended request. If an attempt times out after reaching FARPY, first determine whether the render was already created. Blindly issuing a new unprotected creation request can create duplicate work.
State-transition failures
Some operations are valid only in specific render states. Submission, cancellation, download, receipt, and proof retrieval each depend on the canonical job lifecycle. When a transition is rejected, fetch the current render object and decide from its actual state.
Cancellation is supported before worker claim. A cancellation request made after that boundary should not be repeated indefinitely. Read the current state and allow the active job to reach its terminal result.
Safe recovery checklist
- Preserve HTTP status and request ID.
- Parse machine-readable code before message text.
- Retry only when retryable is true.
- Respect Retry-After for HTTP 429.
- Use bounded retries with delay.
- Protect creation retries with idempotency controls.
- Fetch canonical render state after ambiguous outcomes.
- Keep failed, cancelled, and transport errors distinct.
- Never log credentials or webhook secrets.
Frequently asked questions
Should every error be retried?
No. Retry only when the response identifies the condition as retryable and the operation can be repeated safely.
What should be logged?
Log status, code, request ID, retryable, suggested action, route, and local attempt count. Exclude credentials and secrets.
How should rate limits be handled?
Respect Retry-After, reduce request pressure, and use bounded retry behavior.
Is render.failed an API transport error?
No. It is a terminal outcome of an existing render and should be reconciled through canonical render status.
How are duplicate creations avoided?
Use supported idempotency and request-fingerprint controls when repeating an ambiguous render-creation attempt.
Error overview · Developer reference · Quickstart · Webhook receiver reference · OpenAPI