List a shift's defects
Required scope: shifts.read.
Return the defects production logs of a shift (its id as returned by GET /v1/shifts), oldest
first, in the same shape the defects POST routes return. It lists every defects log on the
shift's machine that lies within the shift, including ones created through
POST /v1/production-logs for part of the shift, so the shift's defects are the sum of the
quantity values.
Use it to check what a shift already has before adding more, for example before resending a
request whose outcome you do not know without its Idempotency-Key. The whole list is returned,
not paginated.
Errors:
404shift_not_found: the shift is not one of yours.
Path Parameters
The shift ID.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/v1/shifts/0/defects"[ { "id": "5b0f6a52-3c1e-4d5b-9f0e-8a7c6d5e4f3a", "shiftId": 48213, "machineId": 12, "quantity": 3, "start": "2026-10-12T06:00:00Z", "end": "2026-10-12T14:00:00Z", "sku": { "id": "9ce2c6b4-a1f4-4bf2-b5c8-10436d1018cc", "name": "SKU-1042" } }]List a shift's operators GET
Return who ran the machine during a shift (its id as returned by GET /v1/shifts), after every assignment so far: one entry per stretch, oldest first, each with the operator and when they took over and handed over. Once anyone is assigned, the entries normally cover the whole shift. A stretch with no operator has operatorId: null, and a shift nobody was assigned to returns an empty list. For the morning example under POST /v1/shifts/{shift_id}/operator, after the three accepted assignments it returns 1063 from 06:00 to 10:00, 2071 from 10:00 to 12:00 and 3300 from 12:00 to 14:00. Errors: * 404 shift_not_found: the shift is not one of yours.
Add shift defects POST
Add defective units of a SKU to a shift by its id (as returned by GET /v1/shifts), including shifts that have already ended. What a defect is. Defects are counted in defective units of the SKU, not in individual flaws: a unit with three scratches is one defective unit. How defects add up. Each request records an additional quantity of defective units against the entire shift, as a new defects production log of quantity units of the SKU. Quality and OEE metrics are recalculated asynchronously. Requests never replace earlier ones: * Sending quantity: 2 and then quantity: 3 records 5 defective units. * Sending the same request twice records the defects twice, unless both carry the same Idempotency-Key (see below). * A shift listed twice by GET /v1/shifts, from two consecutive ranges, is still one shift: process each id once, or list with match=start. * To undo a call, delete the log it returned with DELETE /v1/production-logs/{id}, which needs the production_logs.delete scope. To see what a shift already has, list its defects with GET /v1/shifts/{shift_id}/defects, which needs shifts.read. Grant both to an integration that reconciles or undoes what it sends; with shifts.update alone it can add defects but not check or remove them. Defects are not attributed to any operator, and they can be added to past shifts, including ones whose production was reviewed. The SKU is given by exactly one of id or name, and it must already be one of your SKUs: these endpoints never create one. The response's sku shows the SKU the defects went to. Errors carry a stable code (see the responses below): * 400 shift_not_found: no shift matches. * 400 shift_not_started: the shift has not started yet. * 400 insufficient_production: the shift does not have enough production of that SKU to hold the defects. * 404 sku_not_found: sku.id or sku.name is not one of your SKUs. * 409 idempotency_key_reused: the Idempotency-Key was already used with a different request. * 409 idempotency_key_in_progress: the original request with that Idempotency-Key is still being processed. Retries and Idempotency-Key. Whether a failed call recorded anything depends on how it failed: * A 4xx response means the request was rejected and nothing was recorded. Fix it and send it again. * A timeout, a dropped connection or a 5xx response leaves the outcome unknown: the request may have been recorded even though you never got the response. Sent again without an Idempotency-Key, it can be recorded twice, so first check whether it was recorded, for example with POST /v1/production-logs/filters. To retry safely instead, send an Idempotency-Key header with a unique value you generate for each request, such as a UUID, and send the same key and the same body on every retry of that request. The key is stored together with what the request recorded, so a retry never records it twice: * If the original request was recorded, the retry records nothing and returns the original response, with the header Idempotent-Replayed: true. * If the original was not recorded, whether it was rejected or failed, the retry is processed as a new request. * Reusing a key with a different request, another body or URL, returns 409. * In the rare case that the original is still being processed, the retry returns 409. Retry again shortly. Keys are scoped to your company, so all of its API keys share them, and each key is kept for 24 hours after the request that recorded it. After that, a request with the same key is processed as a new one, so retry within that window.