Machine Events API¶
Endpoint¶
text
GET /api/v1/machine-events
Read-only endpoint that returns cursor-paginated machine alarm events from the alarms collection for a resolved tenant and machine.
Contract reference: api/openapi.yaml
Authentication¶
When AUTH_ENABLED=true, requests must include a JWT Bearer access token:
http
Authorization: Bearer <access_token>
When AUTH_ENABLED=false, the endpoint is open for local development.
Missing tokens return 401 AUTHENTICATION_REQUIRED. Invalid or expired tokens return 401 INVALID_TOKEN.
Accept negotiation¶
| Value | Description |
|---|---|
application/json |
JSON response (default when Accept is omitted) |
application/xml |
XML response |
text/xml |
XML response |
*/* |
JSON response |
Unsupported Accept values return 406 Not Acceptable (NOT_ACCEPTABLE).
Tenant context¶
company_id and organization_id are optional query parameters. They are not derived from token claims.
| Situation | Result |
|---|---|
| Both query values present | Use the request pair |
| Neither query value present | Use DEFAULT_COMPANY_ID and DEFAULT_ORGANIZATION_ID when both environment values are configured |
| Exactly one query value present | 400 TENANT_CONTEXT_INCOMPLETE (environment defaults are not applied) |
| Neither query nor configured defaults | 400 TENANT_CONTEXT_REQUIRED |
| Invalid ObjectID in a provided value | 400 INVALID_TENANT_CONTEXT |
All reads are scoped to the resolved tenant. The service never operates without a tenant filter.
Configuration validation at startup:
- Both
DEFAULT_*values empty → allowed - Both set to valid ObjectIDs → allowed
- Exactly one set → startup validation error
See Configuration.
Query parameters¶
| Parameter | Required | Description |
|---|---|---|
machine_code |
Yes | Machine code within the resolved tenant |
company_id |
No | Tenant company ObjectID (pair rule applies) |
organization_id |
No | Tenant organization ObjectID (pair rule applies) |
project_code |
No | Filter by project code |
production_code |
No | Filter by production code |
production_stage_code |
No | Filter by production stage code |
start_time |
No | Lower bound (RFC 3339; offset accepted, normalized to UTC) |
end_time |
No | Upper bound (RFC 3339; offset accepted, normalized to UTC) |
limit |
No | Page size. Default 100, minimum 1, maximum 1000 |
cursor |
No | Opaque cursor from a previous response |
There is no maximum date-range limit. When start_time and end_time are both supplied, start_time must be strictly before end_time.
When end_time is omitted, the effective upper bound is the current UTC time at request processing.
Pagination¶
Keyset pagination uses (timestamp DESC, _id DESC).
effective_end_timein the response is pinned for the cursor chain- Cursors carry this bound and a filter fingerprint
pagination.next_cursorisnullon the last page- An empty result set returns HTTP 200 with
"items": []
Response mapping¶
| API field | Source / rule |
|---|---|
production_stage_code |
MongoDB production_stage field |
event_type, type_code |
Normalized canonical snake_case |
timestamp, effective_end_time |
RFC 3339 UTC with Z suffix |
status |
Excluded from the API response |
reconnecting events |
Included; legacy aliases (reconnect, re-connect, re_connect, any case) are normalized to canonical reconnecting only |
Each item may include nested employees, input_products, and output_products arrays.
Example request¶
http
GET /api/v1/machine-events?machine_code=MACHINE-001&company_id=6a2bc9fbeb8679852cddac2a&organization_id=6a2bd388eb8679852cddac2c&limit=50 HTTP/1.1
Host: localhost:8080
Authorization: Bearer <access_token>
Accept: application/json
Example response¶
json
{
"success": true,
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"effective_end_time": "2026-08-06T15:00:00Z",
"items": [
{
"machine_name": "CNC Makinesi",
"machine_code": "MACHINE-001",
"event_type": "stop",
"timestamp": "2026-08-06T14:30:00Z",
"employees": [],
"input_products": [],
"output_products": [],
"project_name": "Proje Adı",
"project_code": "PROJE-001",
"production_code": "URETIM-001",
"production_name": "Üretim Emri Adı",
"production_stage_code": "ASAMA-001",
"stop_answer_reason": "",
"type_code": "planned"
}
],
"pagination": {
"limit": 50,
"returned_count": 1,
"has_more": false,
"next_cursor": null
}
},
"error": null
}
Error responses¶
| HTTP | Code | When |
|---|---|---|
| 400 | MACHINE_CODE_REQUIRED |
machine_code missing or empty |
| 400 | TENANT_CONTEXT_REQUIRED |
No tenant in query and no configured defaults |
| 400 | TENANT_CONTEXT_INCOMPLETE |
Only one of company_id / organization_id in query |
| 400 | INVALID_TENANT_CONTEXT |
Invalid ObjectID in tenant fields |
| 400 | INVALID_START_TIME / INVALID_END_TIME |
Malformed time parameter |
| 400 | INVALID_TIME_RANGE |
start_time not before end_time |
| 400 | INVALID_LIMIT |
limit outside 1–1000 |
| 400 | INVALID_CURSOR |
Cursor invalid or filter mismatch |
| 401 | AUTHENTICATION_REQUIRED / INVALID_TOKEN |
Auth failure |
| 404 | MACHINE_NOT_FOUND |
No machine for tenant + machine_code |
| 406 | NOT_ACCEPTABLE |
Unsupported Accept |
| 503 | DATABASE_UNAVAILABLE |
MongoDB unavailable |
See Error Codes.
Database indexes¶
Non-unique alarm indexes are created by the migration CLI (not per request):
ix_alarms_machine_timestamp_id_desc— machine-events keyset paginationix_alarms_project_production_stage_machine_timestamp_id— scoped alarm scans
Run migrations according to your deployment process before relying on these endpoints in production.