Turn briefs into apps
MonstarX Platform API
In shortAutomate MonstarX from your own scripts and services. Create an account API key, submit a brief and follow its job. Review the app before publishing.
Use ordinary HTTP to create apps, request changes and publish an approved revision. Connect MonstarX to a server, a CI pipeline or an automation tool. API builds use your normal account usage allowance.
What can you automate?
Section titled “What can you automate?”Connect your delivery pipeline
Follow work from your tools
API or MCP?
Section titled “API or MCP?”| Use | Best fit |
|---|---|
| Platform API | Scripts, services, CI and automation tools calling predictable HTTP endpoints. |
| MCP | A coding agent such as Claude Code, Codex or Cursor choosing tools during a conversation. |
| Your app’s REST API | Reading or changing records in an app you built. This uses separate project data keys. |
The Platform API and MCP share MonstarX’s application operations and project runner. The API uses account keys; MCP also supports browser sign-in. API version 1 covers the endpoints below. MCP and the workspace offer additional operations such as imports and secret management.
Quickstart
Section titled “Quickstart”Make a key in Settings → API & MCP. Store it as MONSTARX_API_KEY in your server’s secrets, then check your account. These examples run on a server; never put the key in browser code.
export MONSTARX_API_KEY='your-account-key'export MONSTARX_API_BASE='https://monstarx.com/api/v1'curl --fail-with-body "$MONSTARX_API_BASE/account" \ -H "Authorization: Bearer $MONSTARX_API_KEY"import jsonimport osimport urllib.request
request = urllib.request.Request( "https://monstarx.com/api/v1/account", headers={"Authorization": "Bearer " + os.environ["MONSTARX_API_KEY"]},)with urllib.request.urlopen(request, timeout=30) as response: print(json.load(response))const response = await fetch('https://monstarx.com/api/v1/account', { headers: { Authorization: `Bearer ${process.env.MONSTARX_API_KEY}` },});const data = await response.json();if (!response.ok) throw new Error(JSON.stringify(data));console.log(data);Authentication
Section titled “Authentication”Sign in and open Settings → API & MCP → API keys. Create a named key for each integration and copy it immediately; its value is shown once. Use the key as Authorization: Bearer bck_…. Revoke it in Settings to prevent new requests and queued work from starting. An AI turn already accepted by the project runner may finish; stop it in the workspace if needed.
Account keys act on projects owned by their account. Version 1 keys grant read, build, and publish access across those projects; there are no per-key permissions or project restrictions yet. Keep keys in your server’s secrets, never in browser code or a mobile bundle. MCP OAuth access tokens and project data API keys (mxapi_…) are not accepted here. This API operates MonstarX itself; Admin → APIs separately exposes a generated app’s data.
export MONSTARX_API_KEY='your-account-key'export MONSTARX_API_BASE='https://monstarx.com/api/v1'curl --fail-with-body "$MONSTARX_API_BASE/account" \ -H "Authorization: Bearer $MONSTARX_API_KEY"Create an app
Section titled “Create an app”curl --fail-with-body "$MONSTARX_API_BASE/projects" \ -H "Authorization: Bearer $MONSTARX_API_KEY" \ -H 'Content-Type: application/json' \ -H 'Idempotency-Key: client-brief-2026-001' \ -d '{"name":"Client portal","prompt":"Build a client portal with a project list and a contact form.","mode":"build"}'A 202 Accepted response means the job was saved, not that the app is ready. Location and status_url identify the status endpoint. For example:
{ "id": "job_0123456789abcdef0123456789abcdef", "operation": "create", "status": "queued", "project_id": "exampleprojectid12345", "request_id": "api_0123456789abcdef0123456789abcdef", "workspace_url": "https://monstarx.com/p/exampleprojectid12345", "status_url": "https://monstarx.com/api/v1/jobs/job_0123456789abcdef0123456789abcdef", "created_at": "2026-10-21T00:00:00.000Z", "updated_at": "2026-10-21T00:00:00.000Z", "result": null, "error": null}Optional file_urls accepts up to 10 public HTTPS document or image URLs, with the same attachment limits as MCP. A name is optional (up to 80 characters). The prompt uses the normal MonstarX request-size limit and must fit within the API’s 64 KB JSON body limit. Use attachments for larger briefs. mode is build (default) or plan; plan mode may ask for answers before building. Use GET /account to check the current usage allowance. A job accepted with 202 can still fail later because of usage limits, invalid attachments, or setup requirements.
Follow a job
Section titled “Follow a job”curl --fail-with-body "$MONSTARX_API_BASE/jobs/JOB_ID" \ -H "Authorization: Bearer $MONSTARX_API_KEY"Poll no more often than every five seconds, or register a webhook before submitting work. A completed build returns its reply text, available usage details, and the files revision and latest snapshot_id observed when the job is reconciled under result. Other work may have advanced the project by then; review the current workspace before publishing. The workspace_url opens the project and its interactive preview; it is not a public deployment URL.
| Status | Meaning |
|---|---|
queued | Saved and awaiting admission to the project runner. |
running | Submitted to the runner; it may be waiting in the project’s own queue. |
succeeded | The requested AI turn finished, or the deployment is live. A completed turn is not a guarantee of app correctness. |
needs_input | Questions, setup, or usage limits require attention. Open workspace_url to continue; this job is terminal. |
failed | The operation failed; inspect error and the workspace before submitting new work. |
cancelled | The request was stopped or removed, or its account, key, or project access changed. |
Job state survives site deploys. Builds run in the existing project runner, independently of the HTTP connection. Job admission and callback delivery recover through the existing maintenance pass every five minutes, so callbacks can arrive several minutes after completion. A crash during admission may leave a lease until it expires (up to 15 minutes). Unfinished jobs become failed after 24 hours when reconciled; this does not automatically stop a runner already working. Stop or resume work in the workspace in version 1.
Request changes
Section titled “Request changes”Find IDs with GET /projects?limit=30&query=portal, and inspect one with GET /projects/PROJECT_ID.
curl --fail-with-body "$MONSTARX_API_BASE/projects/PROJECT_ID/builds" \ -H "Authorization: Bearer $MONSTARX_API_KEY" \ -H 'Content-Type: application/json' \ -H 'Idempotency-Key: client-portal-add-calendar-001' \ -d '{"message":"Add a shared calendar page.","mode":"build"}'Build requests accept message, optional file_urls, and mode: build, plan, or chat. They return a job with the same lifecycle. Requests enter the normal project queue and use the account’s usual plan allowance. To answer a needs_input job, continue in the workspace, then submit a new API request when ready. Retrying the old job key returns that original job.
Publish an approved revision
Section titled “Publish an approved revision”Building does not publish an app. Fetch GET /projects/PROJECT_ID, review the workspace preview, and use the returned revision and latest_version.id as the deployment confirmation. A completed build’s result.revision and result.snapshot_id are also available, but another edit may already have advanced the project.
curl --fail-with-body "$MONSTARX_API_BASE/projects/PROJECT_ID/deployments" \ -H "Authorization: Bearer $MONSTARX_API_KEY" \ -H 'Content-Type: application/json' \ -H 'Idempotency-Key: publish-approved-client-portal-001' \ -d '{"revision":"r123","snapshot_id":"REVIEWED_SNAPSHOT_ID"}'The project coordinator checks the revision and snapshot before publishing. If they changed, the job fails instead of publishing unreviewed edits. Inspect the current project, review it again, and submit a new job with a new idempotency key. A successful deployment job returns result.url and result.deployment_id.
Version 1 supports publishing through MonstarX or a connected Cloudflare account. Apps requiring another host or unsupported hosting targets must be published through their existing workflow. Upload, GitHub import, secret management, and deleting projects remain in the workspace and MCP for this version.
Signed webhooks
Section titled “Signed webhooks”Register an account-wide callback before submitting work. Generate a separate random signing secret of at least 32 characters (for example, openssl rand -hex 32), store it in your receiver’s secrets, and supply it as signing_secret. MonstarX encrypts it at rest and never returns it. Do not use your account API key as the signing secret.
curl --fail-with-body "$MONSTARX_API_BASE/webhooks" \ -H "Authorization: Bearer $MONSTARX_API_KEY" \ -H 'Content-Type: application/json' \ -d '{"url":"https://automation.example.com/monstarx","signing_secret":"REPLACE_WITH_YOUR_RANDOM_SIGNING_SECRET"}'The answer contains id, url, and created_at. Every registered endpoint receives new terminal API job events for its account: job.succeeded, job.failed, job.cancelled, and job.needs_input. Existing completed jobs and jobs created through MCP or the workspace do not generate retroactive events.
Payloads contain { "id": "EVENT_ID", "type": "job.succeeded", "created_at": "ISO_TIMESTAMP", "data": JOB_OBJECT }. data has the same shape as the job status response. Headers include MonstarX-Event-Id and MonstarX-Signature: t=UNIX_SECONDS,v1=HEX_HMAC.
Verify the HMAC-SHA256 signature over timestamp + "." + raw_request_body using your signing secret. Check the timestamp is within five minutes, then parse JSON. This Node.js example verifies the exact body bytes (collect raw bytes before any JSON middleware):
import { createHmac, timingSafeEqual } from 'node:crypto';
export function verifyMonstarXWebhook(rawBody, signatureHeader, signingSecret) { const match = /^t=(\d{1,15}),v1=([a-f0-9]{64})$/.exec(signatureHeader ?? ''); if (!match || Math.abs(Date.now() / 1000 - Number(match[1])) > 300) { throw new Error('Invalid or expired webhook signature'); } const expected = createHmac('sha256', signingSecret) .update(match[1] + '.') .update(rawBody) .digest(); if (!timingSafeEqual(expected, Buffer.from(match[2], 'hex'))) { throw new Error('Invalid webhook signature'); } return JSON.parse(rawBody.toString('utf8'));}Persist or enqueue a verified event, then respond promptly with any 2xx status. Delivery is at least once: deduplicate durably by payload id, and do not assume events across different jobs arrive in order. Each attempt gets a fresh signature timestamp but keeps the same payload and event ID. If your response is lost after accepting it, MonstarX may send it again.
A non-2xx response, timeout, DNS failure, or redirect triggers a retry. Deliveries stop after eight attempts, with exponential delays starting at five minutes; the maintenance schedule may add delay. Destinations must use public HTTPS hostnames. Local/private addresses and automatic redirects are refused. Each attempt has a 10-second deadline. Poll the job if your receiver is unavailable.
Manage callbacks with:
GET /webhooks: list endpoints, without signing secrets.GET /webhooks/WEBHOOK_ID/deliveries: latest 50 deliveries, with attempt counts, last HTTP status, and next attempt time.DELETE /webhooks/WEBHOOK_ID: remove the endpoint and cancel its outstanding deliveries. Rotate a signing secret by registering a replacement and deleting the old endpoint.
Endpoint reference
Section titled “Endpoint reference”All paths are relative to /api/v1. Every endpoint except GET /openapi.json requires an account API key.
| Method | Path | Result |
|---|---|---|
GET | /account | Account details and current usage. |
GET | /projects | Owned projects; optional query and limit (1–100, default 30). |
POST | /projects | Create an app; returns a job with HTTP 202. |
GET | /projects/{project_id} | Current revision, latest version and project status. |
POST | /projects/{project_id}/builds | Request a change; returns a job with HTTP 202. |
POST | /projects/{project_id}/deployments | Publish the approved revision; returns a job with HTTP 202. |
GET | /jobs/{job_id} | Job status, result or error. |
GET | /webhooks | Registered endpoints, without signing secrets. |
POST | /webhooks | Register an endpoint; returns HTTP 201. |
DELETE | /webhooks/{webhook_id} | Remove an endpoint and cancel outstanding deliveries. |
GET | /webhooks/{webhook_id}/deliveries | Latest 50 delivery records. |
GET | /openapi.json | Public OpenAPI 3.1 schema. |
Request fields
Section titled “Request fields”Creation, build and deployment require an Idempotency-Key header. All POST bodies use Content-Type: application/json.
| Endpoint | Required fields | Optional fields |
|---|---|---|
| Create app | prompt | name (up to 80 characters), mode (build or plan), file_urls (up to 10). |
| Request changes | message | mode (build, plan or chat), file_urls (up to 10). |
| Publish | revision and snapshot_id from the project you reviewed | — |
| Register webhook | url (public HTTPS) and signing_secret (32–200 characters) | — |
The OpenAPI document contains complete request and response schemas. Get the guide as Markdown to use with a coding agent.
Retries, limits, and errors
Section titled “Retries, limits, and errors”Creation, build, and deployment requests require Idempotency-Key (1–200 characters). Keys are scoped to the account and operation/project. Repeating the same validated request returns the original job, including after completion; it never creates another app, AI turn, or deployment. Reusing a key with different content returns 409. Preserve the key after timeouts and network errors. Use a new key only for genuinely new work. Version 1 keeps these job identities until the account is deleted.
Limits: 120 authenticated requests per minute per account, 10 active API jobs per account, 10 webhook endpoints per account, 64 KB JSON bodies. List projects returns up to 100 results (default 30); query filters by name or description. Rate-limited requests return 429 and Retry-After. API jobs share normal billing and usage limits with the workspace and MCP; creating a key does not grant extra usage.
Errors use this shape:
{"error":{"code":"idempotency_conflict","message":"This Idempotency-Key was already used with different input."},"request_id":"TRACE_ID"}400 invalid request or missing retry key; 401 missing, expired, or revoked account key; 404 unknown endpoint or inaccessible project/job/webhook; 409 conflicting retry key or webhook limit; 413 body too large; 415 incorrect content type; 429 rate or concurrency limit; 500 unexpected server failure. Responses include X-Request-Id for support. A 202 response followed by a failed job is an asynchronous failure, not an HTTP submission error.
The API is versioned at /api/v1. Use the OpenAPI document in Postman or to generate a client. Requests use account keys from Settings; the API does not create account keys for other callers.