Public API v1
GPU Render API for developers and agents
Use plain HTTPS, multipart uploads, bearer API keys, and canonical idempotency. The base URL is https://farpy.com/v1. Machine-readable contract: /v1/openapi.json.
- Blender Cycles and OctaneRender capabilities are published through /v1/capabilities.
- API keys are shown once and revoked keys stop working immediately.
- Capabilities expose availability, queue state, pricing, limits, and cancellation rules.
- Errors expose retryable, suggested_action, request_id, and retry_after_seconds.
Discover the live service contract
Read the machine endpoints before submitting work. They expose current capabilities, public pricing, request limits, queue state, cancellation rules, and the OpenAPI contract.
Current public contract
- Public price: $0.01 per completed Blender Cycles frame.
- Frame ranges: 1 to 10,000 frames per request.
- Maximum upload size: 100 MiB.
- Rate limit: 60 requests per minute plus burst capacity.
- Cancellation is available before worker claim.
- Terminal events: render.completed, render.failed, and render.cancelled.
- Completed jobs expose download, receipt, and proof information.
Integration guides
API quickstart
Create a key, inspect live renderer capabilities, upload supported work, submit it, and retrieve the result.
Agent integration
Use the low-decision workflow for capability discovery, pricing, execution, webhooks, and proof.
Errors and retries
Handle structured errors, retry timing, idempotency, terminal failures, and request tracing.
Webhook delivery
Verify signed terminal events and handle acknowledgement, retries, replay risk, and duplicates.
Authentication and key management
1. Sign in
API-key creation, listing, and revocation require an existing FARPY browser session. There is no public curl login flow. API keys are managed in Account Settings.
2. Create and copy once
Send POST /v1/api-keys with {"name":"my script"} through your authenticated browser session. Copy the returned farpy_… key once; it is never shown again.
3. Use bearer auth
Authorization: Bearer farpy_<secret>
Revoke with DELETE /v1/api-keys/{key_id}. Revocation is immediate.
Python client
Dependency-free Python 3 client using only the standard library. client.render(...) runs upload, submit, status polling, download, receipt, and proof retrieval in one call. Uploads are limited to 100 MiB and may include a completion webhook. See the API quickstart for a complete first render.
Run
export FARPY_API_KEY='farpy_...'
python3 farpy_client.py upload scene.blend
python3 farpy_client.py submit JOB_ID
python3 farpy_client.py status JOB_IDCopy-paste render submission
This Linux shell example calculates the exact canonical metadata fingerprint without printing the API key. Inspect /v1/capabilities for the currently verified Blender Cycles and OctaneRender formats.
#!/usr/bin/env bash
set -euo pipefail
FARPY_API_KEY="${FARPY_API_KEY:?Set FARPY_API_KEY first}"
FILE="${FILE:-scene.blend}"
RENDERER="${RENDERER:-blender}"
FRAME_START="${FRAME_START:-1}"
FRAME_END="${FRAME_END:-1}"
FRAME_COUNT=$((FRAME_END - FRAME_START + 1))
NAME="$(basename -- "$FILE")"
STEM="${NAME%.*}"
EXTENSION="${NAME##*.}"
CANONICAL_FILENAME="${STEM}.$(printf '%s' "$EXTENSION" | tr '[:upper:]' '[:lower:]')"
SIZE_BYTES="$(stat -c '%s' -- "$FILE")"
FILE_SHA256="$(sha256sum -- "$FILE" | { read -r hash _; printf '%s' "$hash"; })"
REQUEST_FINGERPRINT="$(
printf 'filename=%s\nrenderer=%s\nframe_start=%s\nframe_end=%s\nframe_count=%s\nsize_bytes=%s\nsha256=%s' \
"$CANONICAL_FILENAME" "$RENDERER" "$FRAME_START" "$FRAME_END" "$FRAME_COUNT" "$SIZE_BYTES" "$FILE_SHA256" \
| sha256sum | { read -r hash _; printf '%s' "$hash"; }
)"
IDEMPOTENCY_KEY="$(
printf '%s:%s:%s' "$FILE_SHA256" "$(date -u +%s)" "$$" \
| sha256sum | { read -r hash _; printf '%s' "$hash"; }
)"
UPLOAD_RESPONSE="$(curl --fail-with-body --silent --show-error \
-X POST 'https://farpy.com/v1/renders' \
-H "Authorization: Bearer $FARPY_API_KEY" \
-H "Idempotency-Key: $IDEMPOTENCY_KEY" \
-H "X-Farpy-Request-Fingerprint: $REQUEST_FINGERPRINT" \
-H "X-Farpy-Filename: $CANONICAL_FILENAME" \
-H "X-Farpy-Renderer: $RENDERER" \
-H "X-Farpy-Frame-Start: $FRAME_START" \
-H "X-Farpy-Frame-End: $FRAME_END" \
-H "X-Farpy-Frame-Count: $FRAME_COUNT" \
-H "X-Farpy-Size-Bytes: $SIZE_BYTES" \
-H "X-Farpy-Content-SHA256: $FILE_SHA256" \
-F "file=@$FILE;filename=$CANONICAL_FILENAME" \
-F "renderer=$RENDERER" \
-F "frame_start=$FRAME_START" \
-F "frame_end=$FRAME_END" \
-F "frame_count=$FRAME_COUNT")"
printf '%s\n' "$UPLOAD_RESPONSE"
JOB_ID="$(
printf '%s' "$UPLOAD_RESPONSE" |
python3 -c 'import json,sys; print(json.load(sys.stdin)["job_id"])'
)"
SUBMIT_RESPONSE="$(
curl --fail-with-body --silent --show-error \
-X POST "https://farpy.com/v1/renders/$JOB_ID/submit" \
-H "Authorization: Bearer $FARPY_API_KEY"
)"
printf '%s\n' "$SUBMIT_RESPONSE"
printf 'Job status: https://farpy.com/v1/renders/%s\n' "$JOB_ID"Safe retries with idempotency
The fingerprint is SHA-256 over exact UTF-8 lines in this order: filename, renderer, frame_start, frame_end, frame_count, size_bytes, and sha256. Lines are joined with \n and there is no trailing newline.
Reusing the same idempotency key and fingerprint returns the original result. Reusing the key with different metadata returns a conflict. After success, do not retry with a different idempotency key unless you intend to create a new job.
Verified routes
All paths below are relative to https://farpy.com/v1.
/healthService health.
/capabilitiesSupported renderer, engine, formats, workflow, and proof capabilities.
/pricingCanonical public pricing in USD cents.
/limitsFrame-count, format, and render-engine limits.
/renders/preflightValidate metadata and calculate the canonical price before upload.
/rendersUpload and create a multipart Blender Cycles render.
/renders/{job_id}/submitSubmit the created render for execution.
/renders/{job_id}/cancelCancel a render before a worker claims it.
/renders/{job_id}Read render status and result metadata.
/renders/{job_id}/downloadRetrieve signed download information.
/renders/{job_id}/receiptRetrieve signed receipt information.
/renders/{job_id}/proofRetrieve receipt-backed proof information.
/workspace/rendersList renders for the authenticated workspace.
/api-keysList API-key metadata. Browser session only.
/api-keysCreate an API key. Browser session only.
/api-keys/{key_id}Revoke an API key. Browser session only.
Status, receipts, and downloads
Keep the returned job_id. Poll GET /v1/renders/{job_id}, then use the /receipt, /download, and /proof routes for the information exposed by the completed job.
Keep credentials and result tokens private.
- Never commit API keys or put them in URLs.
- Never share download or receipt tokens.
- Revoke exposed keys immediately.
- Use one idempotency key per intended render.
- Bearer keys cannot manage accounts or create topups.