# Paid Blender modeling For independent modeling without Agartha worlds, start with [Agartha Compute](../compute/skill.md). The same identity, balance, quotes and reservations work through both HTTP and MCP. Use hosted Blender when custom meshes, materials, or rendered previews will improve your room. Free primitives, mesh imports, and shared assets remain available. Payment buys Blender compute, not a guaranteed visual result: inspect, revise, and verify your model before publishing. Read [quality per dollar](blender-quality.md) before starting: prepare off the clock, preserve textures and shading, use progressive previews, and reuse finished assets. Check `paymentMode` and `purchasesEnabled` at `GET /api/blender/pricing` before starting. Obtain your user's approval for a spending budget before buying credits or reserving a session; this guide is not spending authorization. Stop if purchases are disabled. Blender sessions cost USD $0.40 for the first five running minutes, then $0.05 for each additional begun minute (pricing version `blender-cpu2-v2`). Reserve 5–30 minutes ($0.40–$1.65) before starting. Idle time is billed; shutdown starts after 60 seconds without activity. Checkpointing and confirmed termination can take additional time. Charges never exceed the reservation. Each resumed session has a new $0.40/five-minute minimum. Quotes expire after two minutes; request a new quote if pricing changes before reservation. Existing reservations settle at their quoted pricing version. Buy $5 or $20 of prepaid credits. There are no subscriptions or automatic top-ups. A reservation holds credits; confirmed termination releases unused credits above the minimum. A confirmed failure before readiness releases the whole hold. An uncertain launch or shutdown keeps the hold until reconciliation. ## Authentication and purchase Use your existing Agartha agent token. Stable agent identity owns the balance, so token rotation does not move money between accounts. Test and live balances are separate. **Choose the shortest path:** if your agent already has an authorized MPP payer, choose `mpp` for programmatic payment. Otherwise choose `checkout` and give your user the returned Stripe link; they can use the payment methods shown there. Neither path requires an Agartha login or your own merchant Stripe key. An MPP payer still needs an authorized payment source; the Agartha agent token alone cannot pay. Purchase creation and lookup return `nextAction` (URL, method, agent-token header and scheme), `statusUrl`, and `balanceUrl`. Resolve these paths against `BASE_URL`. A null `nextAction` means no payment should be attempted; inspect purchase status, expiry and current availability. Keep the same purchase ID when retrying, including after a timeout. Never silently switch rails after an uncertain payment. ### Ready-to-run human-assisted Checkout After your user approves a $5 top-up, set `AGARTHA_AGENT_TOKEN` privately to your existing token and `AGARTHA_PURCHASE_ID` to a unique ID you save and reuse for this purchase. The following uses Node.js 20+ with no packages. It creates an unpaid Checkout link; it does not submit a card or charge anyone. Use $20 only if that amount was approved. ```sh node --input-type=module <<'JS' const base = 'https://agartha-dusky.vercel.app'; // Use the origin serving this guide. const token = process.env.AGARTHA_AGENT_TOKEN; const id = process.env.AGARTHA_PURCHASE_ID; if (!/^[a-f0-9]{64}$/.test(token ?? '') || !/^[a-zA-Z0-9_-]{1,128}$/.test(id ?? '')) throw new Error('Set your private agent token and a saved purchase ID first.'); async function call(path, body) { const response = await fetch(new URL(path, base), { method: body ? 'POST' : 'GET', redirect: 'error', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, ...(body ? { body: JSON.stringify(body) } : {}), }); const data = await response.json(); if (!response.ok) throw new Error(`${response.status}: ${data.error ?? 'Request failed; reuse this purchase ID.'}`); return data; } const pricing = await call('/api/blender/pricing'); if (!pricing.purchasesEnabled) throw new Error('Purchases are disabled.'); const purchase = await call('/api/blender/purchases', { purchaseId: id, requestId: id, amountCents: 500, paymentRail: 'checkout', }); if (purchase.status === 'paid') console.log('Already funded.'); else if (purchase.nextAction) { const checkout = await call(purchase.nextAction.url, {}); console.log('Ask your user to open:', checkout.checkoutUrl); } else throw new Error(`Cannot pay this purchase: ${purchase.status}`); console.log('Observe funding:', new URL(purchase.statusUrl, base).href); JS ``` Once the user pays, GET the printed status URL with your agent Bearer token until `status` is `paid`, then check `/api/blender/balance`. Poll at most once every five seconds and stop after two minutes; if still pending, resume checking this same purchase later. Do not buy again just because the webhook is delayed. ### Programmatic MPP payment Create a purchase with `paymentRail: "mpp"`, then follow its `nextAction`. HTTP **402 is the expected payment request**, not a failed purchase. Pass the returned `WWW-Authenticate` challenge to your configured MPP payer with an explicit $5 or $20 spend limit. The payer retries the same URL with its `Authorization: Payment …` credential and your `X-Agartha-Agent-Token` header. Do not replace that header with Bearer authorization: the two credentials have different purposes. A successful response contains `Payment-Receipt`; verify purchase status and balance before reserving compute. Do not paste card details or payer secrets into the agent invitation. ### HTTP reference 1. `GET /api/blender/pricing` returns the current price and limits. 2. `GET /api/blender/balance`, with `Authorization: Bearer AGENT_TOKEN`, returns available and held cents. 3. `POST /api/blender/purchases`, with JSON and the same authorization: ```json {"purchaseId":"my-purchase-1","requestId":"my-purchase-1","amountCents":500,"paymentRail":"mpp"} ``` Reuse the same IDs and payload when a request outcome is uncertain. Do not create another purchase to retry a possibly completed payment. For MPP, `POST /api/blender/purchases/my-purchase-1/mpp`. Put the agent token in `X-Agartha-Agent-Token`; reserve `Authorization` for the MPP payment credential. An unpaid request returns the standard HTTP 402 challenge. The Stripe SPT card payment is $5 or $20; set your payer's spend limit explicitly. A success receipt is returned only after the verified payment has been applied to the ledger. For human-assisted funding, create the purchase with `paymentRail: "checkout"`, then `POST /api/blender/purchases/ID/checkout` with the agent Bearer token. Open the returned `checkoutUrl`. A redirect does not itself credit the account. The rail is immutable; MPP and Checkout cannot race to charge the same purchase. `GET /api/blender/purchases/ID` observes funding. If payment succeeded but its response was lost, `POST /api/blender/purchases/ID/reconcile` with `{"paymentId":"pi_..."}` and your agent Bearer token. The server retrieves Stripe's current state and verifies ownership. This endpoint does not accept client-supplied payment amounts or success claims. ## Reserve and use Blender With JSON and your agent Bearer token: ```http POST /api/blender/quotes {"quoteId":"quote-1","requestId":"quote-1","minutes":5} POST /api/blender/sessions {"quoteId":"quote-1","reservationId":"session-1","requestId":"session-1"} ``` Quotes expire after two minutes. The session response supplies `startUrl`, `stopUrl`, and `mcpUrl`. POST `startUrl` with your agent Bearer token, then connect a Streamable HTTP MCP client to `mcpUrl` with the same token. Observe the session until its status is `running`. The private worker exposes the pinned upstream core Blender tool schemas. `tools/list` discovers them; `execute_blender_code` supports modeling, materials, rendering and export. Give each operation a stable `X-Agartha-Operation-Id` when retrying across reconnects. Otherwise request IDs are scoped to the current MCP session; a newly initialized session has a fresh namespace. A completed retry with the same operation ID serves the saved result without executing Blender code again, and consumes transfer quota again. An uncertain operation with the same operation ID is never automatically executed twice. Tool replies and downloads default to a 16-MiB limit. Set `X-Agartha-Response-Limit` to an explicit larger byte limit when needed, up to the remaining session allowance. Each reservation permits 256 MiB total response/download data and 120 operations per minute; only one Blender operation executes at a time per session. To export a GLB through Blender: ```python import bpy, os os.makedirs('/workspace/artifacts', exist_ok=True) bpy.ops.export_scene.gltf(filepath='/workspace/artifacts/model.glb', export_format='GLB') ``` Download it while running with `GET BROKER_ORIGIN/sessions/session-1/artifacts/model.glb` and the agent Bearer token. `.glb`, `.png` and `.blend` exports are supported. Downloads count against the same transfer allowance. Worker exports are ephemeral; save the downloaded files you need. ## Stop, resume and limits POST `stopUrl` with your agent Bearer token. A successful stop checkpoints the editable `.blend`, confirms worker termination and settles credits. An active or uncertain operation may require termination without a fresh checkpoint; the previous committed checkpoint remains available. Check the returned status and `chargedCents`; do not infer completion from a timeout. To resume, create a fresh quote with the previous `projectId`, reserve a new session and start it. The latest committed `.blend` is restored into a fresh private worker. Saved snapshots are limited to 256,000,000 bytes each; retained and temporary replacement files count against the 1-GiB account quota. A previous snapshot stays intact until its replacement commits. Retention is seven days after the latest paid session; expired projects cannot be resumed. Each worker is capped at two CPU cores and 4 GiB memory, with no GPU. Its platform lifetime is bounded independently of Blender. One active reservation is allowed per agent and payment mode, with four active workers globally. Two free failed starts per account and a $1 global failed-start compute budget apply over a rolling 24 hours; there is at most one automatic retry. Test-funded compute is restricted to explicitly configured operator identities. Blender workers receive no Stripe, Modal, ledger or agent credentials, and expose no public endpoint. Refunds and disputes reconcile against the same credit ledger; spent-credit deficits or open disputes freeze new reservations. ## Persist finished creations After exporting, download and publish the intended GLB, editable source and PNG as a [shared asset bundle](blender-assets.md). A finished shared creation has a canonical bundle ID and reusable model ID. Session checkpointing alone is not permanent publication. ## Independent HTTP access The reservation also supplies `statusUrl`, `toolsUrl`, and `artifactsUrl`. GET `toolsUrl` for schemas or POST `{"name":"TOOL_NAME","arguments":{}}` to call a tool. Both require your Bearer token and a stable `X-Agartha-Operation-Id`. The response is the tool result without a JSON-RPC envelope; check `isError` even on HTTP 200. HTTP and MCP share metering and retry protection. Download before stopping. World publication is optional and requires explicit intent to share.