{"openapi":"3.1.0","info":{"title":"FARPY Public API","version":"1.0.0","description":"Blender Cycles rendering at one USD cent per frame."},"servers":[{"url":"https://farpy.com/v1"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"FARPY API key"},"sessionCookie":{"type":"apiKey","in":"cookie","name":"farpy_session"}},"schemas":{"Health":{"type":"object","required":["ok","service","ts"],"properties":{"ok":{"type":"boolean","const":true},"service":{"type":"string"},"ts":{"type":"string","format":"date-time"}}},"Pricing":{"type":"object","required":["ok","contract","currency","model","price_per_frame_cents"],"properties":{"ok":{"type":"boolean","const":true},"contract":{"type":"string","const":"FARPY-PUBLIC-API-V1"},"currency":{"type":"string","const":"USD"},"model":{"type":"string","const":"per_frame"},"price_per_frame_cents":{"type":"integer","const":1},"minimum_charge_cents":{"type":"integer","const":1}}},"Capabilities":{"type":"object","properties":{"ok":{"type":"boolean","const":true},"contract":{"type":"string","const":"FARPY-PUBLIC-API-V1"},"renderers":{"type":"array","minItems":1,"maxItems":1,"items":{"type":"object","required":["id","application","version","engines","input_formats","output_format","render_device"],"properties":{"id":{"type":"string","const":"blender"},"application":{"type":"string","const":"Blender"},"version":{"type":"string","const":"4.1.1"},"engines":{"type":"array","minItems":1,"maxItems":1,"items":{"type":"string","const":"CYCLES"}},"input_formats":{"type":"array","minItems":1,"maxItems":1,"items":{"type":"string","const":".blend"}},"output_format":{"type":"string","const":".zip"},"render_device":{"type":"string","const":"GPU"}}}},"availability":{"type":"object","required":["classification","accepting_jobs","queue_state"],"properties":{"classification":{"type":"string","const":"LIVE_PUBLIC_ALPHA"},"accepting_jobs":{"type":"boolean"},"queue_state":{"type":"string"}}},"pricing":{"type":"object"},"limits":{"type":"object"},"cancellation":{"type":"object"},"workflow":{"type":"array","items":{"type":"string"}},"proof":{"type":"object"},"webhooks":{"type":"object","additionalProperties":false,"required":["supported","signed","transport","terminal_events","delivery_model","redirects_allowed","private_network_targets_allowed"],"properties":{"supported":{"type":"boolean","const":true},"signed":{"type":"boolean","const":true},"transport":{"type":"string","const":"HTTPS"},"terminal_events":{"type":"array","minItems":3,"maxItems":3,"uniqueItems":true,"items":{"type":"string","enum":["render.completed","render.failed","render.cancelled"]}},"delivery_model":{"type":"string","const":"durable_queue"},"redirects_allowed":{"type":"boolean","const":false},"private_network_targets_allowed":{"type":"boolean","const":false}}}}},"Limits":{"type":"object","properties":{"ok":{"type":"boolean","const":true},"contract":{"type":"string","const":"FARPY-PUBLIC-API-V1"},"frame_count":{"type":"object","properties":{"minimum":{"type":"integer","const":1},"maximum":{"type":"integer","const":10000}}},"accepted_extensions":{"type":"array","items":{"type":"string","const":".blend"}},"required_render_engine":{"type":"string","const":"CYCLES"},"render_backend":{"type":"string","const":"GPU"},"maximum_upload_size_bytes":{"type":"integer","const":104857600},"availability":{"type":"object","required":["classification"],"properties":{"classification":{"type":"string","const":"LIVE_PUBLIC_ALPHA"}}},"rate_limit":{"type":"object","required":["requests_per_minute_per_client","burst"],"properties":{"requests_per_minute_per_client":{"type":"integer","const":60},"burst":{"type":"integer","const":20}}}}},"ApiKeyMetadata":{"type":"object","required":["key_id","name","masked_prefix","created_at","last_used_at","revoked_at"],"properties":{"key_id":{"type":"string","pattern":"^key_[a-f0-9]{32}$"},"name":{"type":"string","minLength":1,"maxLength":80},"masked_prefix":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"last_used_at":{"type":["string","null"],"format":"date-time"},"revoked_at":{"type":["string","null"],"format":"date-time"}}},"ApiKeyList":{"type":"object","required":["ok","keys"],"properties":{"ok":{"type":"boolean","const":true},"keys":{"type":"array","items":{"$ref":"#/components/schemas/ApiKeyMetadata"}}}},"ApiKeyCreateRequest":{"type":"object","required":["name"],"properties":{"name":{"type":"string","minLength":1,"maxLength":80}}},"ApiKeyCreated":{"type":"object","required":["ok","key","key_id","name","created_at"],"properties":{"ok":{"type":"boolean","const":true},"key":{"type":"string","pattern":"^farpy_"},"key_id":{"type":"string","pattern":"^key_[a-f0-9]{32}$"},"name":{"type":"string"},"created_at":{"type":"string","format":"date-time"}}},"ApiKeyRevoked":{"type":"object","required":["ok","key_id","revoked"],"properties":{"ok":{"type":"boolean","const":true},"key_id":{"type":"string","pattern":"^key_[a-f0-9]{32}$"},"revoked":{"type":"boolean","const":true}}},"RenderObject":{"type":"object","additionalProperties":true,"properties":{"webhook_configured":{"type":"boolean","description":"True when terminal render webhooks are configured."}}},"RenderUploadRequest":{"type":"object","required":["file"],"properties":{"file":{"type":"string","format":"binary"},"webhook_url":{"type":"string","format":"uri","maxLength":2048,"description":"HTTPS endpoint for render.completed, render.failed, and render.cancelled events."},"webhook_secret":{"type":"string","minLength":16,"writeOnly":true,"description":"Optional signing secret. FARPY generates one when omitted."}}},"RenderProof":{"type":"object","required":["ok","job_id","proof","receipt_url"],"properties":{"ok":{"type":"boolean","const":true},"job_id":{"type":"string"},"proof":{"type":"string","const":"receipt_backed"},"receipt_url":{"type":"string"}}},"WorkspaceRenders":{"type":"object","required":["ok","renders"],"properties":{"ok":{"type":"boolean","const":true},"renders":{"type":"array","items":{"$ref":"#/components/schemas/RenderObject"}}}},"PreflightRequest":{"type":"object","required":["filename"],"properties":{"filename":{"type":"string","pattern":"\\.blend$"},"renderer":{"type":"string","const":"blender","default":"blender"},"frame_start":{"type":"integer","minimum":1,"default":1},"frame_end":{"type":"integer","minimum":1},"frame_count":{"type":"integer","minimum":1,"maximum":10000}}},"Error":{"type":"object","required":["ok","error"],"properties":{"ok":{"type":"boolean","const":false},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"retryable":{"type":"boolean"},"suggested_action":{"type":"string"},"request_id":{"type":"string"},"retry_after_seconds":{"type":"number","minimum":0},"detail":{}}}}}}},"paths":{"/health":{"get":{"operationId":"getHealth","responses":{"200":{"description":"Service health","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Health"}}}}}}},"/capabilities":{"get":{"operationId":"getCapabilities","responses":{"200":{"description":"Supported render capabilities","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Capabilities"}}}}}}},"/pricing":{"get":{"operationId":"getPricing","responses":{"200":{"description":"Current pricing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Pricing"}}}}}}},"/limits":{"get":{"operationId":"getLimits","responses":{"200":{"description":"Current limits","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Limits"}}}}}}},"/renders/preflight":{"post":{"operationId":"preflightRender","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreflightRequest"}}}},"responses":{"200":{"description":"Eligible render request"},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/renders":{"post":{"operationId":"createRender","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string"},"description":"Reuse only when retrying the same logical request."}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/RenderUploadRequest"}}}},"responses":{"200":{"description":"Render job created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RenderObject"}}}},"401":{"description":"Invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Multipart form data required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/renders/{job_id}/submit":{"post":{"operationId":"submitRender","security":[{"bearerAuth":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string"},"description":"Reuse only when retrying the same logical request."}],"responses":{"200":{"description":"Render submitted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RenderObject"}}}},"401":{"description":"Invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/renders/{job_id}/cancel":{"post":{"operationId":"cancelRender","security":[{"bearerAuth":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Render cancelled"},"404":{"description":"Render not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Render cannot be cancelled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/renders/{job_id}":{"get":{"operationId":"getRender","security":[{"bearerAuth":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Render status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RenderObject"}}}},"401":{"description":"Invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/renders/{job_id}/download":{"get":{"operationId":"getRenderDownload","security":[{"bearerAuth":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Download URL","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RenderObject"}}}},"401":{"description":"Invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/renders/{job_id}/receipt":{"get":{"operationId":"getRenderReceipt","security":[{"bearerAuth":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Receipt URL","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RenderObject"}}}},"401":{"description":"Invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/renders/{job_id}/proof":{"get":{"operationId":"getRenderProof","security":[{"bearerAuth":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Receipt-backed proof","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RenderProof"}}}},"401":{"description":"Invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/workspace/renders":{"get":{"operationId":"listWorkspaceRenders","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Workspace render history","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceRenders"}}}},"401":{"description":"Invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api-keys":{"get":{"operationId":"listApiKeys","security":[{"sessionCookie":[]}],"responses":{"200":{"description":"API key metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyList"}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createApiKey","security":[{"sessionCookie":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyCreateRequest"}}}},"responses":{"201":{"description":"API key created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyCreated"}}}},"400":{"description":"Invalid key name","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Active key limit reached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api-keys/{key_id}":{"delete":{"operationId":"revokeApiKey","security":[{"sessionCookie":[]}],"parameters":[{"name":"key_id","in":"path","required":true,"schema":{"type":"string","pattern":"^key_[a-f0-9]{32}$"}}],"responses":{"200":{"description":"API key revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyRevoked"}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"API key not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}