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.

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

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_ID

Copy-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.

bashsubmit-render.sh
#!/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.

GET/health

Service health.

GET/capabilities

Supported renderer, engine, formats, workflow, and proof capabilities.

GET/pricing

Canonical public pricing in USD cents.

GET/limits

Frame-count, format, and render-engine limits.

POST/renders/preflight

Validate metadata and calculate the canonical price before upload.

POST/renders

Upload and create a multipart Blender Cycles render.

POST/renders/{job_id}/submit

Submit the created render for execution.

POST/renders/{job_id}/cancel

Cancel a render before a worker claims it.

GET/renders/{job_id}

Read render status and result metadata.

GET/renders/{job_id}/download

Retrieve signed download information.

GET/renders/{job_id}/receipt

Retrieve signed receipt information.

GET/renders/{job_id}/proof

Retrieve receipt-backed proof information.

GET/workspace/renders

List renders for the authenticated workspace.

GET/api-keys

List API-key metadata. Browser session only.

POST/api-keys

Create an API key. Browser session only.

DELETE/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.