Skip to main content
Framelane is built for agents that operate without a developer in the loop. An agent that finds Framelane via a web search can go from zero to a downloaded render on its own. The whole loop is unauthenticated up to the point it holds a verified key.
The one thing an agent needs is a programmatic inbox it can read (the AgentMail pattern). The API key is minted at signup but stays inert until the agent confirms a 6-digit code emailed to that inbox — so control of the inbox is what proves the workspace is really yours.

The loop

The machine-readable version of these steps is served (unauthenticated) at GET /v1/capabilities under the onboarding key, so a capabilities-first agent never has to read this page.

1. Discover

The response includes an onboarding block: self_serve: true, the two steps below (both auth_required: false), and verification_gates_usage: true — i.e. the key does nothing until you verify.

2. Sign up

Returns 201 with api_key.key (an fl_… token) and otp_delivered. The key is inert: any authenticated call returns 403 email_not_verified until step 3. If otp_delivered is false, the email could not be sent — the key can’t be verified, so retry with a reachable inbox. Calling signup again with the same email rotates the key and re-sends the OTP, so knowing an email alone never yields a working key.

3. Verify the emailed OTP

Read the 6-digit code from the inbox you signed up with, then:
On 200, the key from step 2 works immediately. (Five wrong guesses burn the code; call /v1/signup again for a fresh one.)

4. Render

From here, follow the Quickstart for composing renders, or connect the hosted MCP server to drive Framelane as tools.

Waiting for a job to finish

An autonomous agent has no public endpoint to receive webhooks, so it waits by long-polling. Call GET /v1/renders/{id}?wait=25 (or GET /v1/tasks/{id}?wait=25): the request blocks until the job reaches a terminal status (completed, failed, or cancelled) or ~25 seconds elapse, then returns the current status. One call replaces a poll loop — which matters most over MCP, where every poll is a separate tool call. If it returns still in flight (Retry-After: 0 is set), just call again. The same ?wait= works for preview renders.