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.

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
- Check your balance with /me.
- POST a generation and store the returned id.
- Open the stream and wait for a terminal status.
- GET the generation, download each file, store it.
- 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
- MeshForge API reference — every endpoint, parameter and error code.
- MDN: Using server-sent events — how SSE streams work.
- Khronos glTF 2.0 specification — the GLB format you receive by default.
