Search Production Logs
Required scope: production_logs.read.
Search Production Logs by machine, shift, SKU, date, quantity or review state.
A POST because the filter body nests, but it only reads: the production_logs.read
scope is sufficient. Send {} to get the first page with the defaults (page 1,
limit 10). Filters are optional and combine with AND.
Pages. Logs are ordered by start, then by id. The response gives totalCount and
totalPages; request page 1, 2, … up to totalPages with the same filters and limit to
read them all. A log written while you page can shift later pages by one.
Dates. startDate filters on when a log starts and endDate on when it ends. after and
before exclude the time itself, between includes both ends, and equal matches the exact
time. Give times with a UTC offset.
A shift's logs. To read back what a shift holds, for example after adding defects to it,
filter by its id from GET /v1/shifts:
{"shifts": {"include": [48213]}, "type": {"include": ["defects"]}, "limit": 100, "page": 1}
A log is in a shift when it is on the shift's machine and lies within the shift. For only the
defects, GET /v1/shifts/{shift_id}/defects returns the same logs in one unpaginated list.
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/v1/production-logs/filters" \ -H "Content-Type: application/json" \ -d '{}'{ "totalCount": 100, "totalPages": 10, "currentPage": 1, "productionLogs": [ { "id": "36f7b519-d93e-4ec8-8245-7f4b8c123456", "type": "correct", "sensorCount": 500, "count": 1000, "nominalSpeed": 60, "countingFactor": 1, "start": "2024-01-01T00:00:00", "end": "2024-01-01T08:00:00", "isReviewed": true, "isAutomated": true, "machineId": 12, "createdAt": "2019-08-24T14:15:22Z", "updatedAt": "2019-08-24T14:15:22Z", "deletedAt": "2019-08-24T14:15:22Z", "live": true, "machine": { "id": 0, "name": "string", "isCountEnabled": true, "externalName": "string" }, "company": { "id": 0, "name": "string", "timezone": "string" }, "shift": { "id": 0, "name": "string", "start": "2019-08-24T14:15:22Z", "end": "2019-08-24T14:15:22Z", "isConsidered": true }, "operator": { "id": 0, "firstName": "string", "lastName": "string", "email": "string" }, "sku": { "id": "string", "name": "string", "description": "string", "unit": "string" }, "workOrder": { "id": "string", "name": "string", "description": "string", "status": "InProgress" }, "simpleWorkOrder": { "id": "string", "name": "string" } } ]}Create Production Logs POST
Create one or many Production Logs. The body is a JSON array, even for a single record. This is the endpoint an MES, ERP or shop-floor terminal uses to push production into Pulsar. machine and sku are references that accept either an id or a name, so a system that only knows line names and product codes does not have to resolve Pulsar ids first. A Production Log describes a closed interval: start and end are both required, end is at or after start, and both fall inside a single shift of the machine. Past shifts are accepted, so logs can be sent days after production. To record what is happening in the shift a machine is running right now, use the realtime endpoints instead. Defects (type: "defects") are additive. Several defects logs may cover the same range, in one request or across requests, and each one is recorded, so sending the same batch twice records it twice. Send each batch once, and retry it only as described under Retries and Idempotency-Key below. start and end may be the same instant for defects found at one point in time: `json [ {"type": "defects", "count": 3, "nominalSpeed": 60, "machine": {"name": "Press 4"}, "sku": {"name": "GAL-1042"}, "start": "2026-10-12T14:00:00Z", "end": "2026-10-12T22:00:00Z"}, {"type": "defects", "count": 1, "nominalSpeed": 60, "machine": {"name": "Press 4"}, "sku": {"name": "GAL-1042"}, "start": "2026-10-12T17:42:10Z", "end": "2026-10-12T17:42:10Z"} ] ` total and correct logs may not overlap another log of the same type, machine and SKU. The response lists the logs of this request. Quality and OEE for the affected shifts are recalculated in the background, usually within minutes. 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.
Retrieve a Production Log GET
Return one Production Log by id, with its related records expanded inline. An id belonging to another company is reported as 404, not 403.