Shop Commander · Developers

Errors & Workflow Blockers

One error envelope; 409s explain exactly what business rule stopped the request and what would unblock it.

Every error, from any layer, has the same shape:

{
  "error": {
    "type": "conflict",
    "code": "job_blocked",
    "message": "This job cannot be started yet.",
    "request_id": "req_4a13d1f7a5494e7b89249f32b4436d79",
    "param": null,
    "details": { … },
    "blockers": [
      { "type": "authorization", "reason": "not_authorized",
        "message": "The customer has not approved this work.",
        "resolution": ["Send the estimate for approval from Shop Commander."] }
    ]
  }
}
Field Meaning
type Coarse class: invalid_request, authentication, permission, not_found, conflict, rate_limited, api_error
code Stable machine code — branch on this, never on message
message Human explanation, safe to log and show to an operator
request_id Quote it to the shop or support; it is traceable end to end
param For validation errors: the offending field (dotted path)
details Structured extras (required_scope, supported values, retry_after_seconds, …)
blockers For conflict: every business rule in the way, each with a reason and a list of possible resolutions

Status codes

Status type When
400 invalid_request Malformed id, bad cursor, bad limit, missing Idempotency-Key
422 invalid_request Body validation failed (code: validation_failed, one entry per field in details.errors)
401 authentication Missing/invalid/revoked key
403 permission Missing scope, suspended integration, inactive shop
404 not_found No such resource for this shop — a record in another shop is indistinguishable from a nonexistent one
409 conflict / idempotency Stale expected_version (version_conflict), a reused Idempotency-Key with a different body (idempotency_key_reused), a duplicate, or a workflow blocker
429 rate_limited Budget exhausted; honour Retry-After
5xx api_error Ours; retry with backoff, then report the request_id

Workflow blockers

Shop Commander enforces the shop's operating rules: work cannot start before the customer approves it, an appointment cannot be booked outside business hours or over a technician's capacity, a job cannot complete with unresolved parts, and so on. When a rule stops a write the API answers 409 with blockers listing every rule in the way, so you can show an operator the whole picture rather than discovering them one by one.

Blocker types you will meet: authorization, parts, shop_hours, technician_capacity, appointment, state. Each carries a reason code you can branch on and a resolution list written for a person.

The API also tells you in advance what is possible: appointments and jobs include available_actions, the list of domain actions valid right now for this caller. Prefer checking it to guessing.

Validation errors

422 invalid_request with code: "validation_failed" includes details.errors, one entry per field with its dotted param path and message. Unknown fields are rejected on purpose — a typo must not be silently ignored.

Retrying