# ENLYZE API investigation This document separates public facts, schema facts, and customer-specific observations. Raw captures are local under ignored `data/raw/enlyze/`; reviewed sanitized fixtures may be stored in `fixtures/enlyze/`. ## VERIFIED FROM PUBLIC DOCUMENTATION - ENLYZE uses Bearer-token authentication with `ENLYZE_API_KEY`. - Public resources include machines, sites, products, production runs, and downtimes. ## VERIFIED FROM OPENAPI SCHEMA Source: locally supplied `data/raw/enlyze/openapi.json`, verified by the operator as OpenAPI 3.1.0, `ENLYZE API` v2. The schema server is the relative URL `/api`; resolving it against `https://app.enlyze.com` and combining it with paths such as `/v2/machines` yields `https://app.enlyze.com/api/v2/machines`. Every operation below declares `Bearer` security: an `apiKey` in the `Authorization` header. The exploration CLI sends `Authorization: Bearer ` without logging it. ### Common pagination Paginated list/time-series responses contain `data` and `metadata`. The required `metadata.next_cursor` is a string continuation token or null. Reuse a non-null value as `cursor` with otherwise identical parameters. No general `limit`/page-size parameter is declared. UUID-array filters permit at most 50 items; one time-series request permits at most 100 variables. ### Machines and sites | Operation | Parameters | Response | | --- | --- | --- | | `GET /v2/machines` | Optional `site` UUID array (max 50), `cursor` | `PaginatedMachines` | | `GET /v2/machines/{uuid}` | Required machine UUID | `Machine` | | `GET /v2/sites` | Optional `cursor` | `PaginatedSites` | | `GET /v2/sites/{uuid}` | Required site UUID | `Site` | `Machine` requires UUID `uuid`, `name`, site UUID `site`, and date-only `genesis_date`. `Site` requires UUID `uuid` and `name`. No current machine-running state is exposed by these schemas. ### Products and production runs | Operation | Parameters | Response | | --- | --- | --- | | `GET /v2/products` | Optional `cursor` | `PaginatedProducts` | | `GET /v2/products/{uuid}` | Required product UUID | `Product` | | `GET /v2/production-runs` | `cursor`; optional `machine` UUID array (max 50), `product-external-id`, `product` UUID, `production-order-external-id`, `start`, `end`, `uuid` UUID array (max 50), `q` | `PaginatedProductionRuns` | | `GET /v2/production-runs/{uuid}` | Required production-run UUID | `ProductionRun` | `Product` requires UUID `uuid`, ERP/MES identifier `external_id`, and nullable description/name `name`. `ProductionRun` requires UUID `uuid`, machine UUID `machine`, string `production_order` (the schema calls this the identifier of the production order), product UUID `product`, timezone-aware ISO 8601 `start`, and nullable timezone-aware ISO 8601 `end`. A null end denotes an unfinished run. It also contains quantities (`{value, unit}` when present), OEE components (score 0–1 and seconds of time loss), optional maximum run speed with unit and observation period, data-quality metrics, and arbitrary attributes. For list filtering, `start` means runs executed starting at/after the supplied time; `end` means runs executed up to the supplied time. This does not prove interval-overlap behavior needed for integration. ### Variables and data sources | Operation | Parameters | Response | | --- | --- | --- | | `GET /v2/variables` | Optional `machine`, `type`, `state`, `data_source`, `data_type`, `uuid`, `depends_on` UUID arrays (each max 50 where applicable), `cursor` | `PaginatedVariables` | | `GET /v2/data-sources` | Optional `cursor`, `uuid`, `machine`, `spark` UUID arrays (max 50) | `PaginatedDataSources` | | `GET /v2/data-sources/{uuid}` | Required data-source UUID | `DataSource` | `VariableResponse` requires variable UUID, associated machine UUID, data type, and discriminated details. It can include `display_name`, nullable string `unit`, nullable `scaling_factor`, comment, and types `FLOAT`, `INTEGER`, `STRING`, `BOOLEAN`, or array variants. Spark details include data-source UUID, structured origin identifier, origin name/comment, and current capture state (`inactive`, `active`, `evaluating`). Derived details list dependencies and description. The deprecated top-level `type` mirrors `details.type` (`spark` or `derived`). `DataSource` can provide `readout_limit`, `readout_interval`, current `readout_status`, and machine UUID. This is a data-source/readout state, not a documented machine operational/downtime state. ### Historical time series | Operation | Parameters | Response | | --- | --- | --- | | `POST /v2/timeseries` | Required JSON `machine`, timezone-aware ISO 8601 `start`, `end`, and 1–100 `variables`; optional `resampling_interval`, `cursor` | `TimeseriesResponse` | Each requested variable contains required UUID and optional `resampling_method`: `first`, `last`, `max`, `min`, `count`, `sum`, `avg`, `median`, `std`, `q5`, `q25`, `q75`, `q95`. `resampling_interval` is an optional integer from 10 to 604800; the schema does not define its unit or whether omission means native/raw resolution. `TimeseriesResponse.data.columns` is ordered with `time` always first, followed by requested variable UUIDs. `data.records` is tabular in that column order. The schema example uses timestamps such as `2023-01-03T14:00:00.0+00:00` and numeric values. It defines no per-sample unit, quality/status field, null/missing-value behavior, boundary inclusion, ordering, or correction/backfill semantics. Units belong to `VariableResponse.unit`, not the time-series envelope. ### Downtimes | Operation | Parameters | Response | | --- | --- | --- | | `GET /v2/downtimes` | Optional UUID/machine UUID arrays (max 50), timezone-aware ISO 8601 `start`, `end`, reason filters, reason state, `cursor` | `PaginatedDowntimes` | `Downtime` requires UUID, machine UUID, type (`THRESHOLD` or `NO_DATA`), timezone-aware ISO 8601 start, nullable end, and nullable comment/reason/update information. A null end denotes an ongoing downtime. It supports historical downtime retrieval but does not establish a complete machine-state timeline. ## VERIFIED WITH CUSTOMER EXPLORATION The following are customer-specific observations, not general ENLYZE API semantics: - K7 candidate fiber mass-flow variable: `Stundenleistung Anlage` (kg/h). Historical behaviour supports interpreting it as a process-responsive band-scale signal. It can remain frozen at a non-zero value during stops. - Validated K7 integration gate: `Geschwindigkeit Gesamtanlage > 0.5 m/min`. Do not use the boolean `Anlage läuft` as the primary gate for this calculation. - `production_run.quantity_total` is populated from ERP/BI production feedback received by ENLYZE for this setup, not necessarily from machine signals. The tested CSV source field is `PCO_FEEDB_QUANTITY`. For inspected machines/articles it is reported finished-product area in m²: 5.00 m × 50 m = 250.00 m², 4.75 m × 50 m = 237.50 m², and 5.80 m × 50 m = 290.00 m². `quantity_total.unit` is separately configured and is not authoritative without configuration validation. Historical validation case (plausibility only): production order `K 7-12026000842`, Production Run 2026-08-31T10:57:54Z to 2026-08-31T18:23:11Z, had ERP `quantity_total` 12,420 m². Speed-gated integration produced approximately 5.206 active hours, 5,180.1 kg fiber feed, 2,174.2 m machine length, and 995.1 kg/h average active throughput. Article external ID `213408` (width 6.0 m; static mean basis weight 390.16 g/m²) gives an approximate reported finished-product mass of 4,845.8 kg. This supports the physical plausibility of the feed integration; it is not a precise material yield calculation. ## STILL UNKNOWN - Full customer response coverage, permissions, authentication success/failure behavior, default page size, and rate/retention limits. - Whether production-run filters have the desired interval-overlap behavior; completed-run `start`/`end` are candidate integration boundaries but require live confirmation. - Whether the validated K7 signal/gate generalize to other machines, articles, production conditions, or future signal configuration. - Whether omitted `resampling_interval` yields native/raw resolution; its unit and exact temporal meaning of resampling methods. - Sample ordering, boundary inclusion, native sampling behavior, gaps, nulls, quality/bad samples, late arrivals, corrections, and backfills. - A complete historical machine operational-state resource beyond downtimes. - Exact per-order material yield: band-scale material may remain in the machine at an order transition and ERP feedback can arrive asynchronously or periodically. WIP/transport-delay accounting is required before interpreting feed-versus-finished-product differences as yield or scrap. ## Exact bounded manual exploration sequence Set the schema server URL locally; the key remains only in `secrets/enlyze.env`: ```bash export ENLYZE_BASE_URL='https://app.enlyze.com/api/' ``` 1. First page of machines (the schema has no limit parameter): ```bash production-analytics enlyze raw /v2/machines --pretty \ --save-raw machines-page-1.raw.json --save-fixture machines-page-1.json ``` 2. Select a harmless machine UUID from the ignored raw capture and retrieve a narrow completed-run page. Replace uppercase placeholders with local values: ```bash production-analytics enlyze raw /v2/production-runs \ --query 'machine=MACHINE_UUID' \ --query 'start=RUN_SEARCH_START_ISO8601' \ --query 'end=RUN_SEARCH_END_ISO8601' --pretty \ --save-raw production-runs.raw.json --save-fixture production-runs.json ``` 3. Resolve the selected run’s product and discover variables for its machine: ```bash production-analytics enlyze raw /v2/products/PRODUCT_UUID --pretty \ --save-raw product.raw.json --save-fixture product.json production-analytics enlyze raw /v2/variables --query 'machine=MACHINE_UUID' --pretty \ --save-raw variables.raw.json --save-fixture variables.json ``` 4. Select a numeric variable with a meaningful unit and query a short completed-run subinterval. Omit resampling initially to test the optional/default behavior: ```bash production-analytics enlyze timeseries \ --machine MACHINE_UUID --variable VARIABLE_UUID \ --start SAMPLE_START_ISO8601 --end SAMPLE_END_ISO8601 --pretty \ --save-raw timeseries.raw.json --save-fixture timeseries.json ``` `--resampling-interval 10` and `--resampling-method avg` are available only for a subsequent bounded comparison. The CLI reads `secrets/enlyze.env` by default and does not print the token/header. Raw files remain ignored; review every sanitized fixture before committing it.