DynoRaptor DynoRaptor Developers
API Core · v1

Industrial reporting data for your own scripts.

The DynoRaptor API lets active customers securely read delayed machine status, energy, sensor, counter, Solar, and recorded downtime data. It is designed for scheduled reports and custom server-side scripts.

Read-only and intentionally delayed. API Core does not provide live control or raw real-time telemetry. Results are delayed by at least 15 minutes and telemetry uses a minimum 30-minute resolution.
Manage API Access

Authentication

Company administrators enable API Access and create scoped credentials from Dashboard → Services → API Access. Send the credential in the HTTP Authorization header:

Authorization: Bearer dr_live_EXAMPLE_REPLACE_WITH_YOUR_KEY

Keys are shown once, stored by DynoRaptor only as a cryptographic hash, and can be revoked immediately. Never put a key in a query string, browser bundle, public repository, screenshot, or support message.

Solar endpoints require the separate solar.read scope and an active Solar Hub add-on. Machine restrictions do not apply to Solar assets. Create a new credential if an existing key does not include solar.read.

eGauge endpoints require egauge.read and an active eGauge add-on. Saved comparisons against Solar also require solar.read.

Quickstart

curl

curl --request GET \
  --url https://www.dynoraptors.ai/api/v1/machines \
  --header "Authorization: Bearer $DYNORAPTOR_API_KEY" \
  --header "Accept: application/json"

Python

import os
import requests

response = requests.get(
    "https://www.dynoraptors.ai/api/v1/status-snapshot",
    headers={"Authorization": f"Bearer {os.environ['DYNORAPTOR_API_KEY']}"},
    timeout=20,
)
response.raise_for_status()
for machine in response.json()["data"]:
    print(machine["machine_name"], machine["status"])

PowerShell

$headers = @{ Authorization = "Bearer $env:DYNORAPTOR_API_KEY" }
Invoke-RestMethod -Uri "https://www.dynoraptors.ai/api/v1/machines" -Headers $headers

Time, freshness, and resolution

  • All API timestamps use ISO 8601 with a timezone and are returned in UTC.
  • API Core never returns telemetry newer than now - 15 minutes.
  • Telemetry resolution cannot be finer than 30 minutes.
  • If a finer resolution or newer end time is requested, the response metadata reports the enforced values.
  • Default telemetry range: the previous 24 hours ending at the latest permitted time.

Endpoints

GET /api/v1/account

Plan policy, credential identity, and monthly usage.

GET /api/v1/machines

Authorized machine, group, and sensor configuration.

GET /api/v1/status-snapshot

Company-wide status evaluated at the delayed cutoff.

GET /api/v1/uptime

Uptime, downtime, and offline minutes for one machine.

GET /api/v1/telemetry

Aggregated energy, sensor, or counter data.

GET /api/v1/egauge/registers

Entitled eGauge register catalog.

GET /api/v1/egauge/energy

Complete hourly eGauge energy.

GET /api/v1/egauge/comparisons

Saved signed formulas and calculated comparisons.

GET /api/v1/solar/assets

Entitled Solar plant and inverter catalog.

GET /api/v1/solar/status-snapshot

Delayed inverter production status.

GET /api/v1/solar/production

Complete daily Solar production.

GET /api/v1/stop-events

Recorded downtime events with page pagination.

GET /api/v1/stop-events/summary

Recorded event count and duration by machine.

GET

/api/v1/account

usage.read

Returns the authenticated company, credential identity, enforced plan policy, and current monthly usage. It accepts no query parameters.

Request

curl https://www.dynoraptors.ai/api/v1/account \
  --header "Authorization: Bearer $DYNORAPTOR_API_KEY"

Response 200

{
  "company": {"name": "Example Manufacturing", "timezone": "America/Mexico_City"},
  "credential": {
    "id": "e28e70f4-98c6-4ab4-8f50-5648b38e7906",
    "name": "Monthly reporting script",
    "prefix": "a1b2c3d4e5f6",
    "scopes": ["machines.read", "status.read", "telemetry.read", "solar.read", "egauge.read", "stop_events.read", "usage.read"]
  },
  "policy": {
    "tier": "core", "enabled": true, "available": true,
    "freshness_delay_minutes": 15, "minimum_resolution_minutes": 30,
    "retention_days": 30, "maximum_range_days": 7,
    "maximum_rows": 1000, "maximum_machines_per_query": 15,
    "rate_limit_per_minute": 6, "monthly_request_limit": 5000,
    "webhooks_enabled": false
  },
  "usage": {"month_requests": 128, "month_limit": 5000}
}
GET

/api/v1/machines

machines.read

Lists the machines this credential may access. Use each public id in other API requests; internal database identifiers are never returned.

Request

curl https://www.dynoraptors.ai/api/v1/machines \
  --header "Authorization: Bearer $DYNORAPTOR_API_KEY"

Response 200

{
  "data": [{
    "id": "7404ab3c-5614-4a23-97bb-725d08d6a436",
    "name": "Injection Press 04", "model": "PX-220",
    "serial_number": "PX220-004", "year": 2024,
    "machine_type": "injection_molding", "description": "North production line",
    "groups": ["Injection", "North line"],
    "sensors": [{
      "key": "slot_1", "name": "Oil temperature", "kind": "temperature",
      "unit": "°C", "mode": "periodic", "enabled": true
    }]
  }]
}
GET

/api/v1/status-snapshot

status.read

Returns one delayed status row for every authorized machine. Status is working, stopped, offline, or unknown.

Request

curl https://www.dynoraptors.ai/api/v1/status-snapshot \
  --header "Authorization: Bearer $DYNORAPTOR_API_KEY"

Response 200

{
  "as_of": "2026-08-06T18:45:00Z",
  "freshness_delay_minutes": 15,
  "data": [{
    "machine_id": "7404ab3c-5614-4a23-97bb-725d08d6a436",
    "machine_name": "Injection Press 04", "status": "working",
    "status_code": 2, "effective_at": "2026-08-06T18:45:00Z",
    "status_started_at": "2026-08-06T16:12:31Z"
  }]
}
GET

/api/v1/uptime

status.read

Returns non-overlapping uptime, downtime, and offline totals for one machine. Pass the public machine id returned by /api/v1/machines. Uptime means the machine reported working, downtime means it reported stopped, and offline means no status session covered that part of the requested period.

machine_id
Required public machine UUID.
start / end
Optional ISO 8601 timestamps with timezone. Defaults to the latest permitted 24 hours. Maximum 7 days per query; data is retained for 30 days.

Request

curl "https://www.dynoraptors.ai/api/v1/uptime?machine_id=7404ab3c-5614-4a23-97bb-725d08d6a436&start=2026-08-05T00:00:00Z&end=2026-08-06T00:00:00Z" \
  --header "Authorization: Bearer $DYNORAPTOR_API_KEY"

Response 200

{
  "data": {
    "machine_id": "7404ab3c-5614-4a23-97bb-725d08d6a436",
    "machine_name": "Injection Press 04",
    "uptime_minutes": 980.0, "downtime_minutes": 275.0,
    "offline_minutes": 185.0, "total_minutes": 1440.0,
    "uptime_percent": 68.06, "downtime_percent": 19.1,
    "offline_percent": 12.85
  },
  "meta": {
    "start": "2026-08-05T00:00:00Z", "end": "2026-08-06T00:00:00Z",
    "latest_allowed": "2026-08-06T18:45:00Z",
    "freshness_delay_minutes": 15, "retention_days": 30,
    "maximum_range_days": 7
  }
}
GET

/api/v1/telemetry

telemetry.read

Returns aggregated energy, sensor, or counter rows. section is required and must be energy, sensors, or counters.

section
Required telemetry family.
start / end
Optional ISO 8601 timestamps with timezone. Defaults to the latest permitted 24 hours.
machine_ids
Optional comma-separated public machine UUIDs. Maximum 15 machines.
resolution_minutes
Optional bucket size. API Core enforces a minimum of 30.

Request

curl "https://www.dynoraptors.ai/api/v1/telemetry?section=sensors&machine_ids=7404ab3c-5614-4a23-97bb-725d08d6a436&start=2026-08-05T00:00:00Z&end=2026-08-06T00:00:00Z&resolution_minutes=30" \
  --header "Authorization: Bearer $DYNORAPTOR_API_KEY"

Response 200

{
  "data": [{
    "timestamp": "2026-08-05T00:00:00Z",
    "machine_id": "7404ab3c-5614-4a23-97bb-725d08d6a436",
    "metric": "temperature", "samples": 180,
    "average": 42.7, "minimum": 39.8, "maximum": 45.2, "sum": 7686.0,
    "sensor_key": "slot_1", "telemetry_type": "a_temperature"
  }],
  "meta": {
    "section": "sensors", "start": "2026-08-05T00:00:00Z", "end": "2026-08-06T00:00:00Z",
    "latest_allowed": "2026-08-06T18:45:00Z", "freshness_delay_minutes": 15,
    "requested_resolution_minutes": 30, "effective_resolution_minutes": 30,
    "limited": false, "maximum_rows": 1000, "cache": "miss"
  }
}

Energy rows may include source_id; sensor and counter rows may include sensor_key. When meta.limited is true, narrow the time range or machine selection.

GET

/api/v1/egauge/registers

egauge.read

Lists included eGauge registers using stable public UUIDs, along with semantic kind, polarity, connection status, and latest available data time.

Response 200

{"data":[{"id":"b32b99cc-21a7-4cd9-95d7-f01a80445480","name":"Consumo","semantic_kind":"grid_import","polarity":1}]}
GET

/api/v1/egauge/energy

egauge.read

Returns complete hourly buckets. Filter with register_id or comma-separated register_ids, plus optional ISO 8601 start and end.

Response 200

{"data":[{"timestamp":"2026-08-15T10:00:00Z","register_id":"b32b99cc-21a7-4cd9-95d7-f01a80445480","energy_kwh":184.2}],"meta":{"resolution":"hour"}}
GET

/api/v1/egauge/comparisons

egauge.read

Calculates saved signed register formulas and returns the eGauge total, reference total, difference, and coverage for complete hours. Use comparison_id to select one comparison.

Response 200

{"data":[{"name":"Consumo general","formula":[{"sign":"-","register_name":"Red"},{"sign":"+","register_name":"Inversores"}],"egauge_kwh":153389.0,"reference_kwh":99800.0}]}
GET

/api/v1/solar/assets

solar.read

Lists Solar plants and inverters covered by the company’s active Solar capacity. Public UUIDs from this response are used by the other Solar endpoints. An active Solar Hub add-on is required.

Request

curl https://www.dynoraptors.ai/api/v1/solar/assets \
  --header "Authorization: Bearer $DYNORAPTOR_API_KEY"

Response 200

{
  "plants": [{
    "id": "85130766-43de-46c7-b639-451d7d56cb29",
    "name": "Main Plant", "timezone": "America/Mexico_City",
    "installed_capacity_kw": 248.5, "inverter_count": 12
  }],
  "inverters": [{
    "id": "c286067e-3718-4f83-915e-14f233ae965d",
    "plant_id": "85130766-43de-46c7-b639-451d7d56cb29",
    "name": "Inverter 01", "serial_number": "INV-001",
    "model": "SUN2000", "installed_capacity_kw": 20.0, "enabled": true
  }],
  "meta": {"limited": false, "entitled_plants": 1, "entitled_inverters": 12}
}
GET

/api/v1/solar/status-snapshot

solar.read

Returns delayed production status derived from the latest eligible 15-minute bucket. Use plant_id, inverter_id, or comma-separated inverter_ids to narrow the selection.

Request

curl "https://www.dynoraptors.ai/api/v1/solar/status-snapshot?plant_id=85130766-43de-46c7-b639-451d7d56cb29" \
  --header "Authorization: Bearer $DYNORAPTOR_API_KEY"

Response 200

{
  "as_of": "2026-08-14T16:45:00Z", "freshness_delay_minutes": 15,
  "data": [{
    "plant_id": "85130766-43de-46c7-b639-451d7d56cb29",
    "inverter_id": "c286067e-3718-4f83-915e-14f233ae965d",
    "inverter_name": "Inverter 01", "status": "producing", "stale": false,
    "bucket_at": "2026-08-14T16:30:00Z", "average_power_kw": 14.8,
    "minimum_power_kw": 13.9, "maximum_power_kw": 15.4,
    "energy_kwh": 3.7, "samples": 3
  }]
}
GET

/api/v1/solar/production

solar.read

Returns complete daily production from stored Solar history. Current partial days are excluded. It accepts start, end, plant_id, inverter_id, and comma-separated inverter_ids. API plan retention, maximum range, row, and selection limits apply.

Request

curl "https://www.dynoraptors.ai/api/v1/solar/production?inverter_id=c286067e-3718-4f83-915e-14f233ae965d&start=2026-08-10T00:00:00-06:00&end=2026-08-14T00:00:00-06:00" \
  --header "Authorization: Bearer $DYNORAPTOR_API_KEY"

Response 200

{
  "data": [{
    "date": "2026-08-10",
    "plant_id": "85130766-43de-46c7-b639-451d7d56cb29",
    "inverter_id": "c286067e-3718-4f83-915e-14f233ae965d",
    "inverter_name": "Inverter 01", "energy_kwh": 118.42, "samples": 1
  }],
  "summary": {"energy_kwh": 118.42, "row_count": 1},
  "meta": {"resolution": "day", "complete_days_only": true, "limited": false}
}
GET

/api/v1/stop-events

stop_events.read

Returns recorded downtime events, newest first, with page-based pagination.

start / end
Optional ISO 8601 timestamps with timezone.
machine_id
Optional public machine UUID when requesting stops for one machine.
machine_ids
Optional comma-separated public machine UUIDs for multiple machines. Do not combine with machine_id.
page
Page number from 1 to 100. Default 1.
page_size
Rows per page from 1 to 100. Default 50.

Request

curl "https://www.dynoraptors.ai/api/v1/stop-events?machine_id=7404ab3c-5614-4a23-97bb-725d08d6a436&start=2026-08-05T00:00:00Z&end=2026-08-06T00:00:00Z&page=1&page_size=50" \
  --header "Authorization: Bearer $DYNORAPTOR_API_KEY"

Response 200

{
  "data": [{
    "id": "abf81ba0-df54-4ba4-a5f2-fea763f2728b",
    "machine_id": "7404ab3c-5614-4a23-97bb-725d08d6a436",
    "machine_name": "Injection Press 04",
    "start": "2026-08-05T14:10:00Z", "end": "2026-08-05T14:27:20Z",
    "duration_seconds": 1040, "description": "Material change",
    "state": "registered", "department": "Production",
    "event_type": "Planned stop", "tags": ["material_change"]
  }],
  "meta": {"page": 1, "page_size": 50, "next_page": null, "latest_allowed": "2026-08-06T18:45:00Z"}
}
GET

/api/v1/stop-events/summary

stop_events.read

Summarizes recorded stop count and overlapping stopped seconds. Use machine_id for one machine or machine_ids for multiple machines. It accepts the same start and end filters as the event list.

Request

curl "https://www.dynoraptors.ai/api/v1/stop-events/summary?machine_id=7404ab3c-5614-4a23-97bb-725d08d6a436&start=2026-08-05T00:00:00Z&end=2026-08-06T00:00:00Z" \
  --header "Authorization: Bearer $DYNORAPTOR_API_KEY"

Response 200

{
  "data": [{
    "machine_id": "7404ab3c-5614-4a23-97bb-725d08d6a436",
    "machine_name": "Injection Press 04",
    "stop_event_count": 3, "recorded_stop_seconds": 2860
  }],
  "meta": {
    "start": "2026-08-05T00:00:00Z", "end": "2026-08-06T00:00:00Z",
    "latest_allowed": "2026-08-06T18:45:00Z"
  }
}
Common response headers. Every response includes X-Request-ID, X-API-Version, rate-limit headers, monthly-quota headers, and Cache-Control: private, no-store. Log the request ID so support can correlate failures without receiving your credential.

Pagination

Stop events support page and page_size. Page size is capped at 100. The response includes meta.next_page when another page is available.

API Core limits

ControlAPI Core
Base subscriptionRequired and active
AccessRead-only
Freshness delay15 minutes
Minimum resolution30 minutes
Retention30 days
Maximum range/query7 days
Rate6 requests/minute/company
Monthly allowance5,000 requests/company
Telemetry rows1,000/request
Machines/telemetry query15
WebhooksNot included

Responses include RateLimit-Limit, RateLimit-Remaining, X-Monthly-Quota-Limit, and X-Monthly-Quota-Remaining headers. Limits may be tightened temporarily to protect platform stability or prevent abuse.

Errors and retries

StatusMeaning
400Invalid parameter or time range.
401Missing, invalid, expired, or revoked credential.
403Missing scope, disabled service, or inactive base subscription.
422Machine selection exceeds the safe plan limit.
429Rate or monthly request allowance exceeded.
503Safe aggregated telemetry is temporarily unavailable.

Error response format

Parameter and policy errors return a stable machine-readable error code and a human-readable detail. Authentication failures may return only detail.

{
  "error": "invalid_time_range",
  "detail": "The maximum range for this plan is 7 days."
}

Retry only 429 and 503 responses. Use exponential backoff and honor Retry-After when present.

OEE add-on · v1

Production operations through your own system

The OEE API records production and quality through the same services as the machine tablet. It requires an active OEE add-on and an OEE key created in OEE → Configuration → Integrations / API, with explicit machine access. API Core keys and its delayed telemetry limits are separate.

Read the complete OEE contract and request examples below. Requests use HTTPS and Authorization: Bearer <OEE key>. Keep credentials in your server-side integration.

Path under /api/oee/v1/OperationScope
context/GET authorized machine/asset UUIDs and pending recalculationoee.read
machines/{machine_id}/setup/GET approved standards, tools, orders, counters, defectsoee.read
runs/GET historical runs; POST ensure_shift, start, completed report, setup, pause, resume, finishoee.read / oee.runs.write
captures/GET receipts; POST production/quality and corrections; DELETE a contributionoee.read / oee.captures.write / oee.captures.void
results/GET rebuilt machine and authorized-factory resultsoee.read

A tablet-free workflow

  1. Activate OEE, enroll the machine, configure and approve its product standard, production counter and planning inputs.
  2. Create a scoped key and discover the machine/setup references. POST a run start, or a completed report with its real historical interval.
  3. Send each production report's batch quantity and explicit quality facts with stable identities. Save the response receipt.
  4. Retry the identical command or capture revision after an uncertain response. Corrections use a higher revision; deletions preserve the history and remove the contribution.
  5. Read results after historical rebuilding. Inspect missing-data warnings and computation times.

Inoquos is an external HTTP client using best-effort background delivery, with at most three attempts per event. Integration failures do not reject Inoquos operations; missed events are accepted loss. Its source ledger records delivery attempts, corrections, deletions and run-command receipts. An approved single-product shift mapping can create the required completed run without a tablet. Source cycle measurements are not treated as ideal speed or counter calibration.

Facts, retries and limits

Machine telemetry supplies configured counter output and availability. Operator/API entries supply production and quality declarations, product/setup changes and run boundaries. Approved configuration supplies ideal speed, output conversion and planned time. Counter output is never added again from barcode quantities.

Send one request per batch/report, not per bottle. OEE admits 10 requests/second and 120/minute per key, 30/second and 600/minute per company, and 100/second and 3,000/minute globally. Honor Retry-After on 429/503. A 409 needs content/setup review; do not retry changed content under the same identity.

Results accept complete five-minute boundaries for up to 31 days. Factory aggregates cover only machines allowed to the key. Missing evidence produces warnings or null factors; late corrections trigger historical rebuilding.

Activa el complemento OEE y configura la máquina antes de crear su clave. Inoquos envía reportes por HTTP y conserva el historial de intentos, correcciones y anulaciones. El contador no se duplica con las cantidades de códigos de barras. Los datos faltantes se muestran como pendientes, no como producción cero.

DynoRaptors OEE customer API v1

The OEE add-on supports production operations through authenticated HTTP requests and the tablet panel. Both use the same production services and PostgreSQL facts. API Core's delayed, read-only telemetry contract is a separate service; it does not describe OEE writes. This document describes the release candidate; production availability follows deployment and customer activation.

Credentials and discovery

An OEE administrator creates the key in Configuration → Integrations / API. Select explicit machines, permissions and expiration; save the one-time secret in the caller's credential store. Do not put it in URLs or log it. Requests use Authorization: Bearer <secret> over HTTPS; browser cookies do not authenticate integration calls. Active/trial OEE entitlement is required, not base API access. Outside local development (DEBUG=False), the authenticator rejects non-HTTPS requests before looking up credentials. Deployments behind a proxy must retain the project's trusted forwarded-protocol configuration. Never test this by sending a real key over HTTP: server rejection cannot undo transport exposure. Revocation and expiration take effect on subsequent requests. Issuer removal, deactivation or loss of required administrator access also disables use.

Paths below are relative to the DynoRaptors mount: / on its own domain, or /api/dyno_raptor/ on the shared staging/local host.

Catalog editors, CSV imports and API discovery

Catalog creation and CSV uploads use authenticated browser endpoints; an OEE bearer key does not grant catalog writes. Developers can read authorized setup data using GET api/oee/v1/machines/<machine UUID>/setup/?kind=products, kind=standards or kind=orders, with oee.read.

Product results include id,code,name,unit,description,revision,active. Standard results include the ideal targets, units_per_event, expected_setup_minutes, planning_efficiency_percent, revision and effective dates. Order results include product/standard IDs, quantity, state, planned_start,planned_end,due_at,priority,customer_reference,lot_reference,notes.

CSV standards accept existing product_code, machine_asset_id and tooling_asset_id. CSV orders accept required product_code and optional standard_id. Direct references need no prerequisite imports. Standards have 15 supported columns and orders have 13. Unsupported CSV columns are rejected, including alternative product UUID and external-reference columns. Product UUIDs remain valid in JSON API operations; this restriction applies to the catalog CSV format.

Manual and CSV standard saves use the same defaults: units/event 1, throughput period 3600 seconds, setup 0 minutes, planning efficiency 85%, revision 1. Event/batch requires positive ideal seconds; quantity requires positive ideal quantity. Inactive measurement fields are ignored. Manual mode has no ideal target. Name or at least one context is required. Setup minutes must be whole and nonnegative. Blank effective date uses now for new records and preserves it on updates. CSV timestamps use ISO 8601 with timezone; date pickers use the company timezone. Saved standards are approved.

Products preserve omitted optional fields on updates; blank text clears them. Orders require a product and positive target quantity; priority defaults to 2 and state to draft. Optional dates, notes, references, priority and state preserve existing values when omitted. Planned end must follow start. MO planning dates do not create planner reservations. CSV external_id provides repeatable import identity.

Discover machine and asset IDs

Call GET /api/oee/v1/context/ with Authorization: Bearer <OEE key> and scope oee.read. Each machines entry returns id (the machine UUID used as machine_id in OEE requests), name, and asset_id (the existing company asset UUID used in asset CSV mappings). These are different identifiers. Serial numbers are not guaranteed unique.

{"machines": [{"id": "<machine UUID>", "name": "Press", "asset_id": "<asset UUID>"}]}

Only enrolled machines authorized by the key are returned. A null asset_id means no company asset is linked; this endpoint does not create assets. To register an external machine reference, an administrator uploads the asset CSV with external_id,name,kind,asset_id and a consistent source such as csv. Unknown, foreign-company, archived or conflicting asset identities fail validation. The browser catalog GET /dashboard/assets/ returns the asset UUID as id, but requires a signed-in browser session, not an OEE bearer key.

Request Scope Purpose
GET api/oee/v1/context/ oee.read Authorized enabled machine UUIDs and linked asset UUIDs
GET api/oee/v1/machines/<machine UUID>/setup/ oee.read Paginated setup references for one authorized machine
GET api/oee/v1/runs/ oee.read Run UUIDs, state, order and current standard/output snapshots
POST api/oee/v1/runs/ oee.runs.write Start, report a completed interval, change setup, pause, resume or finish a run
GET api/oee/v1/results/ oee.read Rebuilt machine and authorized-factory results
GET api/oee/v1/captures/ oee.read Accepted revision history
POST api/oee/v1/captures/ oee.captures.write New capture or replacement revision
DELETE api/oee/v1/captures/ oee.captures.void Void capture or record deletion tombstone

Replacing a live capture requires oee.captures.void as well as write scope. Reads paginate at 50 entries with page, returning count, pages, page and results. Runs accept state, run_id, and machine_id; UUID filters stay inside the credential’s authorized machines. Capture history accepts source and external_id. An optional revision requires both identity filters and an integer from 1 to 9007199254740991; it selects that exact accepted revision before pagination. Invalid exact-lookup parameters return HTTP 400 invalid_revision_lookup. An empty scoped result does not prove the identity never existed outside the credential's current machine access. An accepted historical revision is not necessarily the current total: a later revision may replace or void it.

Use latest=1 with both source and external_id (and without revision) to read the identity's latest accepted revision and its contribution: active, void or reversed, with quantity/unit/kind. Native reversals reduce that identity's contribution to zero even if its last integration operation was a capture. This is the identity's contribution, not the whole machine's output. If the latest revision belongs to a machine outside the key's access, the API returns 403 rather than substituting an older accessible revision. A capture missing its underlying fact returns 409 capture_contribution_unavailable; it is not assumed to contribute zero. Invalid latest lookup parameters return 400 invalid_latest_lookup. The result describes the observed state and may change after the request.

If a native OEE correction already reversed the latest integration fact, a later same-run source replacement or void preserves that reversal instead of reversing twice. The replacement contributes its newly reviewed quantity; a void records the new source revision with no additional negative fact. Cross-run reassignment requires an active original capture and is rejected after a native reversal. Only machine-authorized, enabled OEE runs are available. Integration requests use atomic fixed-window admission budgets: 10/second and 120/minute per key, 30/second and 600/minute per company, and 100/second and 3,000/minute across the OEE integration API. These limits apply to reads, captures and voids, including retries. A batch quantity is one request; do not send one request per unit when a scan represents a batch. 429 includes Retry-After; retain the same identity and revision when retrying. Windows reset on second/minute boundaries, so adjacent windows can permit a boundary burst. Denied requests may consume earlier budget counters conservatively; clients must not continuously poll a denied request.

Production requires the shared Redis cache. Admission-cache failures return 503 with Retry-After: 5 before production processing. The sender should use bounded concurrency, exponential backoff and jitter. Rate admission follows authentication; it is not a replacement for edge-level invalid-credential/connection protection. Staging must validate Redis capacity/eviction behavior, worker clock alignment, end-to-end latency and delivery recovery before these budgets establish release capacity. OEE_API_KEY_BURST_LIMIT may tune the per-key burst from 1 through 120 through Django settings; minute/company/global budgets remain fixed.

Starting a run

POST runs with exactly source, command_id (UUID), machine_id (the DynoRaptors machine UUID, not its serial), action (start), occurred_at, reason, operator_external_id, standard_id, tooling_asset_id, active_outputs, order_id, and counter_binding_id. Tooling/order IDs are UUIDs or null; active outputs are a product UUID-to-quantity object (empty for nominal outputs). Counter binding is an integer ID or null. If the machine has enabled production counters, select one explicitly; null does not silently bypass automatic counting. An active linked company asset and approved, effective, compatible standard are required. Active or historical run overlaps are rejected. Timestamps require a timezone and cannot be future. Commands return run ID, state and version. Retry with the original command UUID and identical payload to retrieve its receipt without creating another run. Discover references using the machine setup endpoint with kind=standards (default), tools, orders, counters, or defects, and page (50 rows per page). Optional at is an aware, nonfuture production timestamp; standards and counters are filtered by effective dates. Standards exclude unapproved revisions and archived tools; orders exclude completed/cancelled states. Tools are active company tooling assets. References are candidates, not a guarantee that every combination is compatible: start/setup revalidate product, machine and tooling relationships at submission. UUIDs belong to DynoRaptors, not the source ERP.

Existing-run lifecycle commands

POST runs accepts exactly source, command_id (UUID), run_id (UUID), action (pause, resume, finish, setup), occurred_at, reason, operator_external_id, and expected_run_version. Use the version returned by GET runs or the preceding successful command; do not generate it yourself. Production time requires a timezone, cannot be future, and must follow the current run/setup/pause boundaries. Source/reason/operator limits are 80/300/160 characters. Each new operation uses a new command UUID. Retry an unconfirmed operation with the exact original payload. Accepted command receipts remain replayable after later state changes and key rotation within the same authorized company/machines. Reusing a command ID with changed content or submitting a stale version returns 409. Review current state before preparing a new command; never blindly substitute the new version. Commands use native workflows and persist their audit/rebuild jobs transactionally. A setup command additionally requires standard_id, tooling_asset_id (UUID or null to retain current tooling), and active_outputs (object mapping product UUIDs to active units, empty if no overrides). The standard must be approved/effective at production time; tools must be active company assets. Unknown products and invalid active quantities are rejected. Setup creates an effective-dated segment without rewriting prior snapshots.

Capture request payload

Reject captures may include defect_code, resolved case-insensitively against the company's active defect catalog (discover with setup kind=defects). Omit it for unclassified rejects. It is not accepted for good/output captures or DELETE requests. Existing receipts replay after catalog deactivation; new captures/replacements require an active code. Changing classification requires a new revision and replacement permission, preserving the original via reversal.

Use JSON (Content-Type: application/json). Example placeholders must be replaced by a discovered run UUID and its actual production timestamp/unit:

{
  "source": "inoquos",
  "external_id": "production-registration:100",
  "revision": 1,
  "run_id": "<run UUID>",
  "kind": "good",
  "quantity": "240",
  "unit": "pcs",
  "occurred_at": "2026-09-07T08:15:00-06:00",
  "operator_external_id": "employee:12",
  "reason": "Box registration"
}

All fields shown are required for timestamped captures; an explicit interval may replace occurred_at as described below. Unknown fields are rejected. Source and external ID have limits of 80/255 characters, operator reference 160, reason 300. Revision is a positive integer no larger than 9007199254740991. Quantity is positive with at most six decimals and less than 10^12. Kinds are good, reject, output. Use stable source-record IDs, not mutable display names or generated retry IDs.

occurred_at is production time, not necessarily scan time. It must include a timezone, not be in the future, and belong to the run's half-open interval [start, end). Unit must exactly match its effective standard; kilograms are not implicitly converted into pieces. Do not invent precise production timestamps from a later packaging scan; supply an explicit interval instead. The external operator reference is retained separately from the credential's authenticated issuer; it does not grant that operator platform permissions.

output is evidence/manual output under the same reconciliation policy as the native workspace. It is not added on top of a machine counter. Never mirror the same box as both additional machine output and accepted output to inflate totals.

Production intervals and allocation

When production time is known only as a period, replace occurred_at with:

"production_interval": {
  "start": "2026-09-07T06:00:00-06:00",
  "end": "2026-09-07T14:00:00-06:00",
  "method": "counter_proportional"
}

Provide exactly start, end, and method. Timestamps must have timezones; the interval must be nonempty, no longer than 24 hours, not future, contained in the run, and covered by setup history without a change of output unit. Split longer periods or periods spanning different output units into separate source records. occurred_at and production_interval are mutually exclusive.

Method Meaning
unallocated Keep the known interval total. Finer periods withhold affected metrics until allocation is supplied.
uniform_time Explicitly estimate an even distribution over the interval's elapsed time.
counter_proportional Explicitly estimate distribution in proportion to measured production output, using historical setup/counter snapshots. Requires a configured production counter throughout the interval; missing telemetry leaves allocation pending.

Neither estimate proves when individual good pieces or defects were produced. The dashboard/tablet disclose estimated allocation, and affected calculations remain provisional. A calculation covering an entire interval uses its exact captured quantity. For partial periods, cumulative rounding conserves the original total across adjacent buckets to six decimal places. Ordinary output captures remain excluded when a machine counter already supplies total output.

Receipts and capture history return the interval. Revisions and voids preserve the old interval through reversal and recalculate its full range, as well as the replacement range. Do not include timing fields in DELETE requests. API receipt time remains separate from production time. Native capture history exposes the period and allocation method; it does not present the legacy storage timestamp as a precise production event for interval captures.

Inoquos delivery preparation accepts an explicit timestamp or an explicit production interval. Prepared timing and allocation method are immutable across retries. Source shift/date-to-interval mapping and operator review are still required; the sender does not infer them or enable live delivery automatically. A source DELETE for an already prepared barcode is prepared automatically against that identity's latest prepared run, including a reviewed reassignment destination. It does not require a new production timestamp or valid replacement quantity. Its earlier revisions must still be acknowledged before the durable sender dispatches the DELETE. An unknown/unprepared barcode identity remains unresolved.

Revisions, deletion and retries

Historical run discovery: GET api/oee/v1/runs/ accepts a scoped machine_id plus either production_at or both production_start and production_end. Times must include an offset, cannot be future, and intervals must be positive and at most 24 hours. A point uses the run's half-open interval; a production interval must fit entirely within one run (ending exactly at its end is allowed). Cancelled runs are excluded. Existing 50-row pagination applies. The Inoquos read_production_run_for_time helper requires exactly one matching run, verifies the machine identity, then fetches full historical setup evidence. It returns an unresolved error for zero or multiple matches. Each HTTPS read has the existing deadline/body bounds. This lookup supplies no scan timing policy and does not itself prepare or send production. Local implementation pending deployment after v4025.

Identity is (company/workspace, source, external_id), independent of API key. Reusing that identity after key rotation does not duplicate production. A revision is a full replacement, not an increment; send the corrected total for that record.

  • New POST: 201, durable accepted event UUID and revision.
  • Optional expected_run_version pins reviewed setup evidence. A new capture with a stale version returns 409 before writing any facts. Identical retries of an accepted revision return its receipt even after the run changes. The source uses this for reviewed/automatic preparation. A separate X-OEE-Reviewed-Run-Version header can supply a freshly reviewed version for the identical version-pinned POST. It must match the locked run's current version; it never changes the capture body, revision/hash or required API permissions. The receiver records original/reviewed versions in capture audit metadata. Inoquos exposes an administrator preview/confirmation flow that verifies historical compatibility and records who authorized this retry and why. Each outbound attempt links to its review. This recovery path is local pending deployment and end-to-end staging acceptance.
  • Same revision and normalized payload: 200 with replayed: true; no new capture.
  • Same revision with changed contents: 409; correct the client or use a new revision.
  • Previously unseen revision lower than the latest: 409; do not resurrect stale data.
  • Higher replacement revision: reverses the previous entry at its original time and records the new quantity/time atomically, preserving both in audit history.
  • DELETE sends the same identity, revision, run, reason and operator fields, but omits kind/quantity/unit/occurred_at. Use a higher revision. Repeated DELETE is idempotent. DELETE before creation records a tombstone that rejects older POSTs.
  • A higher POST after a void is an explicit restoration. An acknowledged retry of an older revision returns that prior receipt without changing the latest state.

An ordinary replacement cannot change a record's run identity. For an explicitly reviewed reassignment, POST a higher revision with the same source/external ID, the destination run_id, valid destination quantity/unit/time, a correction reason, and reassignment: {"from_run_id": "<original run UUID>", "from_revision": 1}. The referenced revision must be the latest active capture. Both write and void scopes and access to both enrolled machines are required. The receiver reverses the original on its original run/time, writes the replacement on the destination, and queues both historical rebuilds in one PostgreSQL transaction. A replacement failure rolls back the reversal and both rebuild requests. Receipts/history expose the reassignment evidence, and retrying the exact revision never moves it twice. Subsequent ordinary corrections/deletion reference the destination run. A voided identity cannot be moved using reassignment; review its intended restoration first. Inoquos administrators can prepare this through the existing correction form: enter the destination run, explicit production timing and a reason. Preview and confirmation verify both runs over the scoped HTTPS API; a changed original or destination run invalidates the review. The source ledger appends a preparation audit and immutable revision, preserving its source observation hash. Ordered delivery waits for earlier revisions to be acknowledged. A subsequent source DELETE follows the latest prepared destination. These changes are deployed on staging v4025. Bounded source-view/HTTPS acceptance verified reassignment, replay and deletion across two runs on an isolated machine, with preserved history and completed rebuilds. Automatic source mapping and live synchronization remain off.

Queries expose revision history, not an unqualified claim that every old receipt is the current state. Reports recalculate asynchronously; an accepted receipt is not proof that a KPI has refreshed. Native captures/reversals now persist rebuild requests transactionally; Redis delivery failure leaves the request pending for five-minute recovery. Workers process at most 12 buckets per request invocation. Context exposes recalculation.pending_jobs, retrying_jobs, and oldest_pending_at within the key's machine scope. Counter-query failures retain the pending job. Real worker-restart/load acceptance remains a release gate; schedule/import invalidation and telemetry arrival must also be verified.

Handle 400 as validation failure; 401 as missing/invalid/expired/revoked key; 403 as missing scope, entitlement or machine access; 409 as revision/domain conflict. Retry network failures and 5xx with the same payload/revision. Persist outbound events atomically with source changes before asynchronous delivery. The planned Inoquos sender must not block production registration on HTTP or delete its local event until acknowledgment is durable.

Completed reports without a tablet

POST to api/oee/v1/runs/ with the same fields as action: start, using action: report and two additional required fields: ended_at and product_code. occurred_at is the actual start of the reported production interval. The interval must have ended, be at most 24 hours, and not overlap any non-cancelled run. A later active run does not block an earlier non-overlapping report. Product must match the single-product approved setup; the selected standard and counter must remain effective throughout the interval. Report separate setup intervals when a shift changed products or setup.

The receiver atomically creates a completed run and its immutable setup snapshot, records the command receipt and requests historical recalculation. It does not invent quantities, downtime, planning, or calibration. Submit production/quality captures separately using the returned run_id and version. Reuse the same source, command_id and exact content after a timeout; the receipt is replayed. Changing content under an existing command ID returns 409. This also permits recovery when the server committed but the client did not receive its response.

Inoquos keeps its own source ledger and run-command receipts. Its administrator can opt in a machine's completed-shift report mapping: one product, approved DynoRaptors standard UUID and configured counter ID. The mapping declares a single setup for that complete shift; no source cycle measurement becomes an ideal standard. This optional sender path waits for shift completion, then creates a missing run through HTTP and submits each barcode's batch quantity. Existing real-time runs can receive scans immediately. Native API start/setup/ finish is available to external clients throughout the shift. Ambiguous runs, changed mappings and mixed-product shifts remain visible for review.

Source quantity corrections and deletions use capture revisions and voids; they keep the run and audit history, then rebuild the affected historical intervals. They do not erase telemetry or delete a run's planning history. A changed source production date is an assignment correction requiring review of the destination run and original contribution. Automatic run provisioning never rewrites an uncertain command after a setup mapping changes.

Machine and factory results

GET api/oee/v1/results/?start=<ISO time>&end=<ISO time> with oee.read. Supply timezone-aware five-minute boundaries, a completed range up to 31 days, and optionally machine_id. A request is capped at 100,000 stored buckets; narrow the interval or machine selection after 422.

factory contains the aggregate of only the key's authorized, enrolled machines. It is not necessarily the customer's entire factory. machines returns external machine UUIDs, names, bucket counts and each aggregate. The response uses persisted recalculation results and includes computation times, source warnings, planning sources, estimated/pending allocation and provisional state. Pending recalculation counts are available from the context endpoint.

Availability uses running/planned time. Performance uses ideal productive time against running time. Quality and factory aggregation use compatible quantities or ideal production time as appropriate; percentages are never averaged. Counter output takes precedence over barcode/operator production quantities. Production captures reconcile against that output; they do not add a second copy. Missing counter evidence, unapproved standards, unallocated reports or unresolved quality can produce null factors. A null is not zero production.

Workspace units and ERP conversions

Unit fields use workspace catalog codes, not a fixed abbreviation enum. Discover units with GET api/oee/v1/machines/<machine UUID>/setup/?kind=units and an oee.read key authorized for that machine. Optional code filters by exact code; results are paginated (50/page). Each unit includes id, code, name, active, source, external_id, measurement.

Use code in CSV unit/output_unit, standards and capture requests; show name to people. Odoo identity is connection + ERP unit ID. Renaming Pce in Odoo does not change its identity. Products imported before this catalog retain their existing unit codes: always use the product's returned unit. Built-in codes remain valid and are not automatically merged with ERP labels.

In the workspace Units catalog, supervisors/admins can create custom units with an immutable code (1–20 ASCII letters/digits, dots, underscores or hyphens; first character alphanumeric) and a descriptive name (240 characters maximum). The u_ prefix is reserved. Cookie-authenticated production/units/ accepts POST {code,name} to create, POST {id,code,name} to rename a custom unit, and GET with optional paged=1, page and search. Manage imported units in the ERP. Integration keys use setup discovery instead.

Native units work without conversion metadata when the MO and product share an ERP unit ID. Differing MO units convert to the product unit only with compatible ERP references: category for Odoo ≤18, common root for Odoo 19. Measurement metadata contains group, to_reference (reference quantity per source unit), and rounding (ERP precision). Original MO quantities and conversion definitions are retained. Targets must fit six decimal places; no silent rounding to the ERP increment occurs.

  • unit_conversion_required: configure compatible units in the ERP or provide quantities in the product unit.
  • unit_precision_loss: conversion cannot fit the stored precision.
  • invalid_unit_metadata: invalid reference, ratio or rounding.
  • unit_definition_changed: upstream definition changed; review before resuming. Existing quantities and historical snapshots remain unchanged.

Custom units imply no automatic conversion. The caller must explicitly handle product-specific packaging, mass-to-piece conversion and yield assumptions. Capture endpoints still require the run's snapshotted output unit, and counters must be calibrated in the standard's output unit. ERP MO conversion does not convert production, defects or kilogram scrap submitted through capture endpoints.

Security practices

  • Create a separate key for every script or destination.
  • Grant only required scopes and machines.
  • Prefer 30- or 90-day expiration and rotate before expiry.
  • Keep keys in environment variables or a secrets manager.
  • Revoke a key immediately if it may have been exposed.
  • Do not call the API directly from public browser JavaScript.

API Core service terms

By enabling API Access, the company administrator confirms that the company has an active DynoRaptor subscription and is authorized to connect the selected systems to company data. The company is responsible for protecting credentials, limiting access to authorized personnel, and complying with applicable privacy and security obligations.

API Core is provided for the company’s internal reporting and integration purposes. Credentials may not be sold, published, transferred to unrelated organizations, used to access another customer’s data, or used to bypass product limits. Automated traffic must respect published limits and retry guidance.

DynoRaptor may throttle, suspend, or revoke API access to protect customer data, platform availability, or investigate misuse. API availability follows the active base subscription. The service is read-only, delayed, provided without a real-time control guarantee, and may evolve through versioned, documented changes.

Support and specification

Download the machine-readable OpenAPI 3.1 specification. For service help, contact soporte@dynoraptors.ai and provide the response request context—but never send your API key.

Resumen: API Core permite integrar scripts propios con datos retrasados de máquinas, telemetría y paros. Es de solo lectura, requiere una suscripción activa y se administra desde Servicios en el dashboard.