Skip to content
NestSolver Docs
Browse the docs

Start

Errors

Every refusal has the same shape: a list of problems, each naming its field in the web form's words, and the plan that lifts a cap.

A call to the REST API that does not succeed answers with a status in the 4xx or 5xx range and one body shape, whichever call it was. The MCP server answers its refusals as JSON-RPC errors instead, and a 405 with an empty body; Tools lists them.

The shape

{
  "errors": [
    { "field": "parts[2].length", "message": "Part 3 length is required.", "upgrade": null },
    { "field": null, "message": "This job has 640 cuts; the limit is 500 a job.", "upgrade": "bench" }
  ]
}
  • field is where in the request the problem is, written as a path like parts[2].length or sheets[0].trim_left, or null when it is about the whole request.
  • message is the problem in the words the web form uses, so a person who knows the optimizer recognises it. Rows are counted from 1 in the words and from 0 in the path.
  • upgrade is the lowest plan that takes the request, when a cap or a plan-only option is the reason, else null.

An option the workspace's tier does not include is answered on its own: those problems come back alone, with 403, before the request's rules are checked.

Status codes

Status When
400 The Idempotency-Key is not 1 to 255 characters. On the MCP server also: an MCP-Protocol-Version it does not speak, or a body that is not one JSON-RPC 2.0 message.
401 No live API key.
403 The workspace's tier does not include an option or feature the request asks for: a plan-only option, nesting, linked load stages, or the deep lane. upgrade names the plan that does. Also a sixth load in a month on Free, with upgrade naming the Bench plan. On the MCP server also: a browser request from an origin other than the MCP server's or the portal's.
404 No job, plan or export at that id, or one the workspace's tier cannot read; or no such route.
405 The MCP server was asked with anything but POST. The body is empty.
409 A request with this Idempotency-Key is still running.
413 The body is over 4 MB.
422 The request breaks a rule, each problem naming its field; a job past its tier's cap on cuts, stock lengths, sheet sizes or nest parts, with upgrade set; a body that is not one JSON object, or holds more rows or longer text than the API takes; or the Idempotency-Key was used for another request.
429 Over a per-minute budget; every solve slot of the workspace is busy ("The optimizer is busy right now."); or the workspace already has 5 nests, or 5 loads, waiting.
500 Something went wrong on our side. Retry with the same Idempotency-Key.

Checks answer 200

POST /v1/linear/validate and POST /v1/sheet/validate read the body as a solve does, so they refuse what a solve refuses before any rule is checked: an option the tier does not include (403), a body that is too large or not one JSON object (422), and a spent free-call budget (429). A cut list they can read is answered 200 with a verdict and the same problem list, so a client can show the problems inline:

{ "valid": false, "errors": [{ "field": "parts[0].quantity", "message": "Part 1 quantity is required.", "upgrade": null }] }

Checks are free calls and do not count as solves.

Handling them

  • Show message to the person and point at field. The words already match the web.
  • When upgrade is set, offer the plan; the request is right, the tier is short.
  • Treat 404 on a plan or export as "no such plan": the id is wrong, or belongs to another workspace.
  • Treat 409, 429 and 500 as retryable, 4xx otherwise as a request to fix. Idempotency and retries has the pattern.