All news

Generating 3D models from your own code

September 23, 2026 · 5 min read

The MeshForge REST API lets you start generations, stream progress over server-sent events and download results. A walkthrough from API key to finished file, with the limits and error handling you need.

Code on a screen flowing through a cloud into generated 3D models of a chair, a robot and a plant

Everything the studio does to create a model is available over a small REST API: JSON over HTTPS, one header for authentication, and the same credits and prices as the studio. This guide walks from creating a key to downloading a finished model, and covers streaming, rate limits and error handling. The complete reference is on the API page.

1. Create an API key

Go to Settings → API keys and create a key. Keys start with mf_live_ and are shown once — MeshForge stores only a hash. Keep the key in a secret store or environment variable, never in client-side code or a public repository. You can revoke a key at any time; revoked keys, and keys of suspended accounts, are rejected.

Check that the key works:

curl https://your-meshforge-domain/api/v1/me \
  -H "X-API-Key: $MESHFORGE_API_KEY"

2. Start a generation

Send a POST to /api/v1/generations. For text-to-3D:

curl -X POST https://your-meshforge-domain/api/v1/generations \
  -H "X-API-Key: $MESHFORGE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "text",
    "prompt": "a weathered bronze viking helmet with horns",
    "options": { "texture": "PBR", "formats": ["GLB", "USDZ"] }
  }'

For image-to-3D, send "type": "image" with an image_url pointing at a public JPEG, PNG or WebP of up to 10 MB. The worker downloads it; if it cannot be fetched, the generation fails and is refunded.

The response is 202 Accepted with the job id, its status and the credits held. Generation is asynchronous: you now either poll or stream.

Useful options

Option What it does
texture NONE, STANDARD or PBR
texture_quality STANDARD, HD (4K maps) or EXTREME (8K maps)
model STANDARD, LOWPOLY or LOWPOLY_PRO
quality FAST, STANDARD or ULTRA (detailed geometry)
polycount Target triangle count; omit for adaptive
formats Any of GLB, FBX, OBJ, USDZ, STL (default GLB)
negative_prompt Text prompts only; things to avoid
seed Same seed and input give the same mesh
t_pose Image input only; reposes the subject first
parent_asset_id Remix one of your models or a public one

3. Follow progress

Streaming (recommended)

GET /api/v1/generations/:id/stream returns server-sent events. Each event is a JSON line with the status and progress; comment lines (": ping") keep the connection alive. The stream ends once the job reaches a terminal status.

curl -N https://your-meshforge-domain/api/v1/generations/JOB_ID/stream \
  -H "X-API-Key: $MESHFORGE_API_KEY"

In a browser, the built-in EventSource API cannot send custom headers, so call the stream from your server and relay progress to your front end.

Polling

GET /api/v1/generations/:id returns the current status, progress, credits charged and, once finished, the asset and its files. Poll every few seconds rather than in a tight loop; each poll counts towards the rate limit.

4. Download the files

A finished generation lists a files array with one entry per format: format, size, a signed URL and its expiry time. Download promptly and store the files in your own storage; fetch the generation again if a link has expired.

Credits and billing over the API

The API uses exactly the same pricing as the studio. Creating a generation holds the quoted credits; when it succeeds you are charged what the job actually used, never more than the quote, and the difference comes back automatically. A failed generation is refunded in full. GET /api/v1/me returns your balance, which is useful to check before starting a batch.

Rate limits

Each key is limited to 60 requests per minute (a sliding window). Every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset headers; over the limit you receive 429 with a Retry-After header in seconds. Separately, your plan caps how many generations can be queued or running at once — /me reports it as max_active_jobs. Streams are the most efficient way to follow a job because one connection replaces many polls.

Handling errors

Status Error code Meaning What to do
400 invalid_request Invalid request body Fix the parameters; the message says which
401 unauthorized Missing, invalid or revoked key Check the X-API-Key header
402 insufficient_credits Not enough credits Top up, or reduce the options
403 forbidden Account suspended, or the resource is not yours Check the account and the id
404 not_found Generation not found Check the id
409 too_many_active_jobs Your plan's parallel-job limit is reached Wait for a running job to finish
429 rate_limited Rate limit exceeded Wait for Retry-After, then retry
500 internal_error Server error Retry later; credits for a failed job are returned

A robust client retries only on 429 and 5xx, with exponential backoff, and treats 4xx as a bug to fix.

A minimal workflow

  1. Check your balance with /me.
  2. POST a generation and store the returned id.
  3. Open the stream and wait for a terminal status.
  4. GET the generation, download each file, store it.
  5. Log credits charged for your own accounting.

Keeping keys safe

  • Use a separate key per application or environment (for example one for a staging server and one for production), so revoking one does not break the others.
  • Store keys in your platform's secret manager or environment variables. Never commit them to version control.
  • Rotate keys by creating a new one, deploying it, then revoking the old one.
  • Never call the API directly from a browser or mobile app with your key: put a small server in between that holds the key and enforces your own limits.

Idempotency and retries

Creating a generation holds credits and queues work, so be careful when retrying a failed request. If a POST times out, check your recent generations (or your balance with /me) before sending the same request again, so a network glitch does not start two jobs.

Sources & further reading