Developers v1

Industrial API · v1

Build Bolt optimization into your own systems.

Bolt Cut and Bolt Nest are available as web apps and as an industrial REST API. Send parts and stock as JSON from your ERP, MES or CAM pipeline, and get back sheet layouts you can route straight to production.

Base URLhttps://www.bolt-optimizations.com
x-api-keyScoped account keysEach key enables only the operations allowed by its current account plan.
202 → pollAsynchronous jobsSubmit a job, receive a jobId, poll until it finishes.
application/jsonJSON in, JSON outMillimetre coordinates for every placed part, per sheet.

Get started

Authentication

Every request must include your secret API key in the x-api-key header. CLGS keys begin with clg_; standalone Bolt keys begin with bolt_ and are shown only once when they are created — store them in a secrets manager, never in client-side code or a public repository.

Requests without a key, or with a revoked key, return 401 Unauthorized.

Create and manage keys in the Developer API tab after a verified API subscription. Creating, rotating or adding keys never creates extra quota. Web-only subscriptions and Day Passes do not grant commercial API access.
Header
x-api-key: clg_<your-60-character-key>
401 Unauthorized
{ "error": "Invalid or inactive API key" }

Get started

Asynchronous jobs

For every submission, send an Idempotency-Key of 1–160 letters, numbers, underscores, dots, colons or hyphens. Save it before sending and reuse it for retries of the same input. A new key means new work. Changing input under a used key returns a conflict; uncertain work keeps its reservation for review.

Optimization is compute-heavy, so both APIs use the same job model. A submit request returns 202 Accepted immediately with a jobId; the engine runs in the background and you poll the job until it reaches a final state.

  • Poll with a short delay (1–3 seconds). Polling is free — it never counts against your quota.
  • Finished jobs are kept in memory for a limited time and may be removed under load or on a server restart. Collect results promptly and store them on your side.
  • A 404 means this credential cannot find an owned job. Keep the original request key; do not start duplicate work to recover an uncertain outcome.
  • Jobs belong to the account and product. Another active key on that same account may read them only with the required current operation permission. Another account cannot read them.

Get started

Quotas & limits

API keys share one monthly allowance for the account and product. Bolt uses its account API-unit allowance. Nest starts with at least one available credit, then deducts ceil(active engine seconds / 200) credits after measured work. A usable partial layout is billed normally; a confirmed failed or cancelled job returns unused reservations. Nest shortfalls become negative credits carried into the next monthly allowance. Polling and downloads do not add usage. Enterprise web/API channels share their bundle wallets.

When the quota is used up, submissions return 429 Too Many Requests until the next reset. The engine also has a bounded queue: if it is saturated, a submission can be rejected with 429 or 503 — retry with back-off.

429 Too Many Requests
{
  "error": "Account allowance exhausted",
  "code": "USAGE_QUOTA_EXHAUSTED"
}

Get started

Errors

Errors use conventional HTTP status codes with a JSON body that explains what went wrong.

StatusMeaningWhat to do
400The request body failed validation.Read error — it names the invalid field or array index.
401Missing, invalid or revoked API key.Check the x-api-key header.
404Job not found for this account, or engine outcome awaiting review.Keep the same request key and contact support for uncertain work.
413Request body too large.Split the job or reduce geometry detail.
429Account allowance exhausted, insufficient Nest start credit, or the engine queue is full.Wait for the reset or retry with back-off.
5xxEngine or server error.Retry with the same request key; contact support for unknown outcomes and include the jobId.

Bolt Cut API

Rectangular panel & sheet optimization

Cut lists of rectangular parts → sheet layouts with part coordinates, saw cuts and offcuts. The same engine as the Bolt Cut web app.

Open web app →

Send the parts you need (pieces) and the stock you have (inventory). All dimensions are in millimetres. Each job optimizes one material; submit one job per material.

POST/api/v1/optimize

Submit an optimization job

Validates the request and queues it. Returns 202 with a jobId. Uses one account Bolt API unit on successful completion under the current job-unit policy.

Body

materialoptionalstring
Label for the material, echoed back in the job.
payloadrequiredobject
Job settings plus the parts and stock (below).

payload settings

payloadrequiredobject
Contains the pieces and inventory arrays.
bladeThicknessnumber ≥ 0
Saw kerf in mm. Default 0.
cuttingMode0 | 1 | 2
0 guillotine (table / panel saw) · 1 free nesting (CNC router, laser) · 2 multistage saw. Default 0. optimizationType is accepted as an alias; if both are sent they must match.
optimizationProfile"quick" | "production" | "max"
Search depth. production is what the web app uses.
searchTimeBudgetSecondsinteger 0–300
Search-time budget for the optimizer.

payload.payload.pieces[] — parts to cut

lengthrequirednumber > 0
Finished length in mm (grain direction when rotation is locked).
widthrequirednumber > 0
Finished width in mm.
canrotaterequired0 | 1
1 lets the part rotate 90°; 0 preserves grain.
pieceExternalIdrequiredinteger, unique
Your ID for the part, returned in the result. One entry per physical part.
priorityinteger
Placement priority. Default 0.

payload.payload.inventory[] — stock sheets

length, widthrequirednumber > 0
Sheet size in mm.
inventoryExternalIdrequiredinteger, unique
Your ID for the sheet or offcut.
TrimTop TrimLeft
TrimBottom TrimRight
number ≥ 0
Edge trims in mm. The usable area after trims must be positive.
priorityinteger
Use order: offcuts/remnants before full boards, for example.
Request
curl -X POST https://www.bolt-optimizations.com/api/v1/optimize \
  -H "x-api-key: $BOLT_API_KEY" \
  -H "Idempotency-Key: $JOB_REQUEST_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "material": "18mm MDF White",
  "payload": {
    "payload": {
      "pieces": [
        { "length": 600, "width": 400, "canrotate": 1, "pieceExternalId": 101 },
        { "length": 600, "width": 400, "canrotate": 1, "pieceExternalId": 102 },
        { "length": 800, "width": 300, "canrotate": 0, "pieceExternalId": 103 }
      ],
      "inventory": [
        { "length": 2800, "width": 2070,
          "TrimTop": 0, "TrimLeft": 0, "TrimBottom": 0, "TrimRight": 0,
          "inventoryExternalId": 1001, "priority": 1 }
      ]
    },
    "bladeThickness": 4,
    "cuttingMode": 0,
    "optimizationProfile": "production"
  }
}'
202 Accepted
{
  "jobId": "72d1e2c2-eb9a-4f6e-97cb-cc2b6871c5d1",
  "status": "queued",
  "message": "Optimization queued"
}
GET/api/v1/optimize/status/:jobId

Get job status & result

Returns the job's current state. Poll until status is completed or error. Free — does not use quota.

queuedprocessingcompletederror
statusstring
One of the states above.
materialstring
Echo of the submitted label.
resultarray | null
One entry per used sheet — see Result schema.
dxf_filestring | null
Full cut-sheet DXF as text (also available from the DXF endpoint).
error, errorCode, retryablePopulated when status is error. If retryable is true, resubmitting may succeed.
queuedAt, startedAt, completedAtepoch ms
Lifecycle timestamps.
Request
curl https://www.bolt-optimizations.com/api/v1/optimize/status/$JOB_ID \
  -H "x-api-key: $BOLT_API_KEY"
200 OK · completed
{
  "status": "completed",
  "material": "18mm MDF White",
  "result": [
    {
      "inventoryExternalId": 1001,
      "length": 2800, "width": 2070,
      "pieces": {
        "0": { "pieceExternalId": 101, "topX": 0, "topY": 0,
               "bottomX": 600, "bottomY": 400 },
        …
      },
      "cuts":   { "1": { "topX": 600, "topY": 0, "bottomX": 600, "bottomY": 2070 }, … },
      "wastes": { "1": { "topX": 1410, "topY": 0, "bottomX": 2800, "bottomY": 2070 }, … }
    }
  ],
  "dxf_file": "0\nSECTION\n…",
  "error": null
}
GET/api/v1/optimize/:jobId/dxf

Download the cut-sheet DXF

Returns the DXF for a completed job as a file download (application/dxf), ready for CAM or machine software. Returns 400 if the job has not completed yet. Free.

Request
curl -o cutsheet.dxf \
  https://www.bolt-optimizations.com/api/v1/optimize/$JOB_ID/dxf \
  -H "x-api-key: $BOLT_API_KEY"

Result schema

Each result entry is one sheet. Coordinates are in mm from the sheet's top-left corner.

inventoryExternalIdThe stock sheet used. length, width and trims are echoed.
piecesPlaced parts keyed "0", "1"… Each has pieceExternalId and its bounding box topX, topY, bottomX, bottomY. A part is rotated when bottomX − topX differs from its submitted length.
cutsOrdered saw passes keyed "1", "2"… Each is a line from (topX, topY) to (bottomX, bottomY).
wastesLeftover rectangles — use them to track reusable offcuts.
Every layout passes a server-side geometry check before the job is marked completed. A layout that fails the check ends as error rather than returning bad geometry.

Bolt Nest API

True-shape nesting

Free-form part outlines — with holes — → nested sheets with the exact placed geometry of every part. The same engine as the Bolt Nest web app.

Open web app →

Describe the sheet and each part as a polygon outline (plus optional inner holes). Coordinates are in millimetres with the origin at the sheet's bottom-left corner and Y pointing up. Every result is geometrically validated by the engine before it's returned.

Nest errors use a structured body: { "error": { "code": "INVALID_INPUT", "message": "…" } }. A submission the engine rejects — invalid input, a full queue, or the engine being unavailable — is not charged against your quota.
POST/api/v1/nest/jobs

Submit a nesting job

Validates and queues the job. Returns 202 with a jobId and a one-credit start reservation. Invalid input returns 422 with the exact field and part at fault.

Body

sheet.widthnumber > 0
Sheet width (X) in mm. Default 2440.
sheet.heightnumber > 0
Sheet height (Y) in mm. Default 1220.
sheet.marginnumber ≥ 0
Edge clearance kept free on all sides. Default 15.
kerfnumber ≥ 0
Minimum spacing between parts (tool / cut width). Default 6. 0 is allowed.
rotationStepsinteger 1–360
Number of evenly spaced rotations to try for rotatable parts — 4 means 0°, 90°, 180°, 270°. Default 4.
partsrequiredarray, 1–5000
Part definitions (below).
optimizationobject
Advanced search tuning, e.g. passes (1–64) and seed for reproducible runs. Unknown keys are rejected.

parts[]

idrequiredinteger, unique
Your ID for the part definition, returned on every placement.
verticesrequired[{ x, y }], 3–1024
Outer outline as a closed polygon (don't repeat the first point).
holes[[{ x, y }]], ≤ 256
Inner cut-outs, each a polygon. Holes are preserved in the output.
quantityinteger 0–10000
How many copies to place. Default 1.
canRotateboolean
false keeps the part at its drawn orientation (grain, print direction). Default true.

Limits per job

  • Up to 10,000 part instances and 5,000 part definitions.
  • Up to 50,000 input vertices in total, outlines and holes combined.
  • Request body up to 10 MB; each job runs for up to 180 seconds.
Request
curl -X POST https://www.bolt-optimizations.com/api/v1/nest/jobs \
  -H "x-api-key: $BOLT_API_KEY" \
  -H "Idempotency-Key: $JOB_REQUEST_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "sheet": { "width": 1200, "height": 800, "margin": 10 },
  "kerf": 4,
  "rotationSteps": 4,
  "parts": [
    { "id": 1, "quantity": 3,
      "vertices": [ {"x":0,"y":0}, {"x":300,"y":0},
                    {"x":300,"y":200}, {"x":0,"y":200} ] },
    { "id": 2, "quantity": 2,
      "vertices": [ {"x":0,"y":0}, {"x":250,"y":0}, {"x":125,"y":220} ] },
    { "id": 3, "quantity": 2,
      "vertices": [ {"x":0,"y":0}, {"x":200,"y":0},
                    {"x":200,"y":200}, {"x":0,"y":200} ],
      "holes": [ [ {"x":70,"y":70}, {"x":130,"y":70},
                   {"x":130,"y":130}, {"x":70,"y":130} ] ] }
  ]
}'
202 Accepted
{
  "jobId": "c1c8de2f-5ad0-41dd-a102-f6e55b85f08c",
  "status": "queued",
  "billing": { "reservedToStart": 1, "secondsPerCredit": 200, "overdraft": "carry_to_next_allowance" }
}
GET/api/v1/nest/jobs/:jobId

Get job status & result

Poll until the job reaches a final state. Free — does not use quota. Saved billing results are read by account ownership. Final customer retention and recovery policies remain under review.

queuedrunningcompletedpartialerrorcancelled
completedEvery requested part was placed.
partialA valid layout was produced, but some parts could not fit — they're listed in result.unplacedParts with a reason. Check this before sending to production.
errorThe job failed; see error.code and error.message.
queuePositionPosition in the engine queue while queued, otherwise 0.
elapsedSecondsRun time so far, or total run time once finished.
Request
curl https://www.bolt-optimizations.com/api/v1/nest/jobs/$JOB_ID \
  -H "x-api-key: $BOLT_API_KEY"
200 OK · completed (abridged)
{
  "jobId": "c1c8de2f-5ad0-41dd-a102-f6e55b85f08c",
  "status": "completed",
  "elapsedSeconds": 1.4,
  "result": {
    "status": "ok", "success": true,
    "sheets": [{
      "sheetIndex": 0, "width": 1200, "height": 800,
      "utilizationPercent": 32.06,
      "placedParts": [{
        "id": 3, "instanceId": 6,
        "x": 314, "y": 234, "rotation": 0,
        "vertices": [{"x":314,"y":234}, {"x":514,"y":234}, …],
        "holes": [[{"x":384,"y":304}, …]],
        "netArea": 36400
      }, …]
    }],
    "unplacedParts": [],
    "statistics": { "validated": true, "requestedParts": 7, "placedParts": 7, … },
    "warnings": [ … ]
  },
  "error": null
}
DELETE/api/v1/nest/jobs/:jobId

Cancel a job

Stops a queued or running job and returns its current state. The job ends as cancelled within a moment. Free.

Request
curl -X DELETE https://www.bolt-optimizations.com/api/v1/nest/jobs/$JOB_ID \
  -H "x-api-key: $BOLT_API_KEY"
GET/api/v1/nest/health

Engine status & limits

Whether the engine is ready, how busy it is, and the input limits it enforces. Useful as a pre-flight check. Free.

200 OK
{
  "status": "ok",
  "engineReady": true,
  "engineTimeoutSeconds": 180,
  "activeJobs": 0, "queuedJobs": 0,
  "limits": { "instances": 10000, "definitions": 5000,
              "verticesPerPart": 1024, "inputVertices": 50000,
              "holesPerPart": 256 }
}

Result schema

sheets[]One entry per used sheet: sheetIndex, width, height, utilizationPercent (net of holes) and placedParts.
placedParts[]id (your part ID) and instanceId (which copy), the placement x, y and rotation in degrees, plus the final placed vertices and holes in sheet coordinates — ready to write to DXF or send to CAM. outerArea, holeArea and netArea are in mm².
unplacedParts[]Copies that couldn't be placed, each with id, instanceId, a machine-readable reason and a readable message.
statisticsRun details. validated: true confirms the layout passed the engine's final geometry audit; requestedParts and placedParts give the counts.
warnings[]Notes about the run to show to operators — for example, that parts are not nested inside other parts' holes.
unplacedParts · partial job
[{
  "id": 9, "instanceId": 2,
  "reason": "DOES_NOT_FIT_EMPTY_SHEET_IN_ALLOWED_ROTATIONS",
  "message": "Part cannot fit the usable sheet in any allowed orientation"
}]

Guides

Client examples

A complete submit-and-poll loop. The same pattern works for both products — only the paths and body change.

const BASE = 'https://www.bolt-optimizations.com';
const KEY  = process.env.BOLT_API_KEY;
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));

async function optimize(body, requestKey) {
  // 1. Submit
  const res = await fetch(`${BASE}/api/v1/optimize`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json', 'x-api-key': KEY, 'Idempotency-Key': requestKey },
    body: JSON.stringify(body),
  });
  if (res.status !== 202) throw new Error((await res.json()).error);
  const { jobId } = await res.json();

  // 2. Poll until a final state
  for (;;) {
    await sleep(2000);
    const job = await (await fetch(`${BASE}/api/v1/optimize/status/${jobId}`, {
      headers: { 'x-api-key': KEY },
    })).json();
    if (job.status === 'completed') return job.result;
    if (job.status === 'error') throw new Error(job.error);
  }
}

Guides

Support

Questions about an integration, higher quotas or a failed job? Email support@bolt-optimizations.com and include the jobId and the time of the request.

© 2026 Bolt OptimizationsEFFICIENCY, ENGINEERED.