Guide
REST API
Authenticate, send a file, a URL or parameters, and retry safely with idempotency keys.
Authentication
The base URL is https://api.mcpbytes.com/v1. Authenticate every request with your API key as a bearer token. Keys are created and revoked in the console.
# Every request authenticates with an API key
curl https://api.mcpbytes.com/v1/me \
-H "Authorization: Bearer $MCPBYTES_API_KEY"Endpoints
- GET
/v1/meYour account, plan limits and usage
- GET
/v1/toolsThe tools you can run, with their options and your limits
- POST
/v1/uploadsCreate a one-hour URL to PUT a file to
- POST
/v1/tools/{tool}/jobsStart a job using its catalog-declared inputs and options: a file body, or JSON
- GET
/v1/jobsList your jobs, newest first (?tool= and ?status= filter it)
- GET
/v1/jobs/{id}A job's status, result and fresh download URLs
- GET
/v1/jobs/{id}/files/{name}Read a text output (.txt .json .md .csv) in chunks
- POST
/v1/jobs/{id}/cancelCancel a queued job or a cancellable workflow; safe to retry
- DELETE
/v1/jobs/{id}Cancel a queued job, or delete a finished job and its files
{tool} is a tool's id, such as split_3d_model; each tool's page lists its id, options and outputs.
Sending input
GET /v1/tools describes what each tool takes: input.kind is file or parameters, and input.sources lists the ways a file can arrive.
A file
Send the file itself as the request body with ?filename= and the options in the query string, use an upload URL, or give a public https URL. The JSON forms take the options in an options object.
# 1. Create an upload URL (valid for one hour)
curl https://api.mcpbytes.com/v1/uploads \
-H "Authorization: Bearer $MCPBYTES_API_KEY" \
-H "Content-Type: application/json" \
-d '{"filename": "airplane.glb"}'
# 2. PUT the file to the "url" from the response
curl -X PUT --data-binary @airplane.glb "$UPLOAD_URL"
# 3. Start the job with the "upload_id"
curl https://api.mcpbytes.com/v1/tools/split_3d_model/jobs \
-H "Authorization: Bearer $MCPBYTES_API_KEY" \
-H "Content-Type: application/json" \
-d "{
\"upload_id\": \"$UPLOAD_ID\",
\"options\": {
\"detail\": \"high\"
}
}"When input.sources includes job_file, JSON can instead reference one of your unexpired completed outputs with "job_file": {"job_id": "…", "name": "…"}. The file is copied into the new job; a signed download URL is not an external URL input. Tools that take it: Create a 3D model from an image, Optimize a 3D model.
Parameters
When input.kind is parameters, send only the options as JSON, without a file. Keep private text such as prompts out of query strings.
# idempotency_key is required: repeating the same request returns the same job
curl https://api.mcpbytes.com/v1/tools/create_image/jobs \
-H "Authorization: Bearer $MCPBYTES_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"options": {
"prompt": "a ceramic teapot with a blue glaze",
"transparent_background": true,
"seed": 42
},
"idempotency_key": "image-example-001"
}'Retries and idempotency
To retry safely, send an Idempotency-Key header, or idempotency_key in a JSON body. A repeated key returns the original job with 200 instead of starting a new one. Reuse it only for the same input and options, including after a network error; a key reused for a different request returns 409 idempotency_conflict.
The key is required when GET /v1/tools advertises idempotency_required: Create a 3D model, Create an image, Create a 3D model from an image, Optimize a 3D model, Get random numbers. With a file body, send it as the header. For these tools, the key of a deleted job cannot start new paid work for a while (410 job_deleted): use a new key.
A complete example
Start a job with a file, poll it until it finishes, and list the download URLs of its outputs:
import { readFile } from "node:fs/promises";
const api = "https://api.mcpbytes.com/v1";
const headers = {
Authorization: `Bearer ${process.env.MCPBYTES_API_KEY}`,
};
async function call(path, init = {}) {
const res = await fetch(api + path, { ...init, headers });
const body = await res.json();
if (!res.ok) throw new Error(body.error.message);
return body;
}
// The model file is the request body
let job = await call("/tools/split_3d_model/jobs?filename=airplane.glb", {
method: "POST",
body: await readFile("airplane.glb"),
});
// Poll until the job finishes
while (["queued", "running"].includes(job.status)) {
await new Promise((r) => setTimeout(r, 5000));
job = await call(`/jobs/${job.id}`);
}
if (job.status !== "succeeded") {
throw new Error(job.error.message);
}
for (const file of job.result.files) {
console.log(file.name, file.url);
}OpenAPI
The full contract, with every field, response and error, is in the OpenAPI description. Errors are listed in Limits & errors.
- GET /v1/me
- Your account, credit balance, plan limits and current usage.
- GET /v1/tools
- Every tool you can run: input, options as JSON Schema, price and your limits.
- GET /v1/jobs?tool=
- Your recent jobs, newest first, optionally of one tool.