API

FARPY Render API quickstart

Inspect a .blend, read the locked quote, start only after you accept it with FARPY_LEGAL_V1, then download the ZIP and receipt. Start is the spend boundary.

FAST PATH

  1. Create a Job API farpy_agent_ key (Account Settings farpy_ keys are a different store).
  2. Download farpy_client.py.
  3. Run:
export FARPY_AGENT_KEY="farpy_agent_..."
python3 farpy_client.py prepare scene.blend
python3 farpy_client.py start UPLOAD_ID --quote-id QTE-... --legal-acceptance FARPY_LEGAL_V1

prepare / inspect / quote do not spend. start is the reservation boundary. Pass legal_acceptance=FARPY_LEGAL_V1 explicitly.

Explicit API flow

Use the full curl workflow when you want to see and control every request.

1. Auth (three systems)

Browser: session cookie. Inspect/start: Job API farpy_agent_… Bearer key. Public API V1 /v1/renders: Account Settings farpy_… key. These stores are not the same. Identity convergence is later work.

export FARPY_AGENT_KEY="farpy_agent_..."

2. Inspect, read the quote, then start

Save this as a shell script. inspect does not reserve funds. start withquote_id and legal_acceptance=FARPY_LEGAL_V1 is the spend boundary. Do not send price_cents.

set -euo pipefail

ORIGIN="https://farpy.com"
FILE="\${1:-scene.blend}"

: "\${FARPY_AGENT_KEY:?Export FARPY_AGENT_KEY (Job API farpy_agent_ key) first}"

AUTH="Authorization: Bearer $FARPY_AGENT_KEY"
test -f "$FILE"

echo "NO SPEND: inspect"
INSPECT="$(curl -fsS "$ORIGIN/node/v1/uploads/inspect" -H "$AUTH" -F "file=@$FILE")"
echo "$INSPECT" | jq '{upload_id, quote_id, frame_start, frame_end, frame_count, price_cents, qualified_1c, pricing_version}'

UPLOAD_ID="$(printf '%s' "$INSPECT" | jq -er '.upload_id')"
QUOTE_ID="$(printf '%s' "$INSPECT" | jq -er '.quote_id // .quote.quote_id')"

echo "SPEND BOUNDARY: start with quote_id and FARPY_LEGAL_V1. Do not send price_cents."
START="$(curl -fsS -X POST "$ORIGIN/node/v1/uploads/$UPLOAD_ID/start" \
  -H "$AUTH" \
  -H "Content-Type: application/json" \
  --data "$(jq -nc --arg quote_id "$QUOTE_ID" '{quote_id:$quote_id, legal_acceptance:"FARPY_LEGAL_V1"}')")"
echo "$START" | jq '{job_id, quote_id, price_cents, payment_status}'

JOB_ID="$(printf '%s' "$START" | jq -er '.job_id')"
echo "Poll GET $ORIGIN/node/v1/jobs/$JOB_ID then download ZIP + receipt."

MCP V1 is live

HTTP MCP at https://api.farpy.com/mcp is live. Let an AI agent inspect, quote, run, and return a verified result. Same contract as REST. See MCP for agents. Tools:farpy_inspect, farpy_quote, farpy_start, farpy_status, farpy_download, farpy_receipt.farpy_start is the only spend tool. Do not use farpy_render or farpy_submit_render.

Discover current service facts first

Call the public health endpoint before sending an API key or uploading a supported render file. If it does not return HTTP 200, stop and retry later.

curl -fsS https://api.farpy.com/v1/health

After health succeeds, inspect current renderer capabilities, public pricing, request limits, and the OpenAPI contract.

Production flow

inspect (.blend)
read locked quote (NO SPEND)
decide
start (quote_id + FARPY_LEGAL_V1) — SPEND
status
download ZIP
receipt / proof

API properties

  • Public health preflight before authenticated work
  • API-key authentication
  • Public price: $0.01 per completed Blender Cycles frame
  • Frame ranges from 1 to 10,000 frames per request
  • 100 MiB upload limit
  • Idempotent submission support
  • 60 requests per minute plus burst capacity
  • Cancellation before worker claim
  • Signed terminal webhooks
  • Receipts and proof artifacts
  • Machine-readable OpenAPI 3.1 specification

Python client

Download the dependency-free Python 3 client. prepare does not spend. start is the spend boundary. Do not use FarpyClient.render() as the recommended path.

import os
from farpy_client import LEGAL_ACCEPTANCE_V1, FarpyClient, FarpyError

client = FarpyClient(os.environ.get("FARPY_AGENT_KEY") or os.environ["FARPY_API_KEY"])

prepared = client.prepare("scene.blend")  # NO SPEND
print(prepared["quote_id"], prepared["price_cents"], prepared["qualified_1c"])

started = client.start(
    prepared["upload_id"],
    quote_id=prepared["quote_id"],
    legal_acceptance=LEGAL_ACCEPTANCE_V1,  # SPEND BOUNDARY
)
print(started["job_id"])

Download farpy_client.py · Open the Python example · Verify SHA-256 checksums

Related guides