{"openapi":"3.0.3","info":{"title":"ObjectID Digital Twin Integration Server","version":"0.1.0","description":"Stateless on-premise integration and interoperability layer for ObjectID Digital Twins."},"servers":[{"url":"/"}],"components":{"securitySchemes":{"ApiKey":{"type":"apiKey","in":"header","name":"x-api-key"},"TwinReadSession":{"type":"http","scheme":"bearer","description":"Opaque Twin-scoped DID session returned by shared/twins/{id}/verify. Not a tenant API key or JWT."},"Bearer":{"type":"http","scheme":"bearer","bearerFormat":"JWT"},"TwinScopeCreation":{"type":"apiKey","in":"header","name":"x-twinscope-creation","description":"Trusted TwinScope backend assertion, audience dtis-twin-create, bound to body, plant/node scope and Idempotency-Key. Not a general API key."}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","required":["code","message","category"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"category":{"type":"string"},"details":{"type":"object"}}}}}}},"paths":{"/api/v1/files":{"post":{"tags":["Encrypted files"],"summary":"Store an immutable private file without a Twin or IOTA transaction","security":[{"ApiKey":[]},{"Bearer":[]}],"description":"Raw bytes (not multipart/base64), max 16 MiB; no Content-Encoding. Dedicated server-side AES-256-GCM encryption. Non-idempotent: retries create new IDs. Tenant owner REST API key or configured JWT with matching sub required.","parameters":[{"name":"X-File-Name","in":"header","required":true,"description":"Percent-encoded UTF-8 filename, no path/control characters, max 240 decoded UTF-8 bytes","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}},"*/*":{"schema":{"type":"string","format":"binary"}}}},"responses":{"201":{"description":"Stored; Location points to metadata","content":{"application/json":{"schema":{"type":"object","required":["id","name","contentType","size","sha256","createdAt","createdBy"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"contentType":{"type":"string"},"size":{"type":"integer","minimum":0,"maximum":16777216},"sha256":{"type":"string","pattern":"^[0-9a-f]{64}$"},"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","description":"Authenticated tenant owner DID"}}}}}},"400":{"description":"Invalid filename/MIME type"},"401":{"description":"Missing or invalid credentials"},"403":{"description":"Tenant owner required; no global/device/disabled-auth access"},"413":{"description":"File exceeds 16 MiB"},"415":{"description":"Compressed request bodies unsupported"},"503":{"description":"Encryption key/storage unavailable or authenticated integrity check failed"}}},"get":{"tags":["Encrypted files"],"summary":"List only the authenticated tenant's file metadata","security":[{"ApiKey":[]},{"Bearer":[]}],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"after","in":"query","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Lexicographic ID page, not a chronological snapshot","content":{"application/json":{"schema":{"type":"object","properties":{"files":{"type":"array","items":{"type":"object","required":["id","name","contentType","size","sha256","createdAt","createdBy"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"contentType":{"type":"string"},"size":{"type":"integer","minimum":0,"maximum":16777216},"sha256":{"type":"string","pattern":"^[0-9a-f]{64}$"},"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","description":"Authenticated tenant owner DID"}}}},"nextCursor":{"type":"string","nullable":true}}}}}},"400":{"description":"Invalid pagination"},"401":{"description":"Missing or invalid credentials"},"403":{"description":"Tenant owner required; no global/device/disabled-auth access"},"503":{"description":"Encryption key/storage unavailable or authenticated integrity check failed"}}}},"/api/v1/files/{id}":{"get":{"tags":["Encrypted files"],"summary":"Read authenticated file metadata","security":[{"ApiKey":[]},{"Bearer":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Decrypted metadata (no storage URI)","content":{"application/json":{"schema":{"type":"object","required":["id","name","contentType","size","sha256","createdAt","createdBy"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"contentType":{"type":"string"},"size":{"type":"integer","minimum":0,"maximum":16777216},"sha256":{"type":"string","pattern":"^[0-9a-f]{64}$"},"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","description":"Authenticated tenant owner DID"}}}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"Tenant owner required; no global/device/disabled-auth access"},"404":{"description":"Unknown ID or another tenant's file"},"503":{"description":"Encryption key/storage unavailable or authenticated integrity check failed"}}}},"/api/v1/files/{id}/content":{"get":{"tags":["Encrypted files"],"summary":"Download verified original bytes as an attachment","security":[{"ApiKey":[]},{"Bearer":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"AES-GCM authenticated bytes; Cache-Control no-store, nosniff, attachment, X-File-SHA256","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"Tenant owner required; no global/device/disabled-auth access"},"404":{"description":"Unknown ID or another tenant's file"},"503":{"description":"Encryption key/storage unavailable or authenticated integrity check failed"}}}},"/api/tenant-access/":{"get":{"summary":"Inspect your tenant application credential status (native DID cookie; no secrets)","description":"Uses the network-specific __Secure-oid_dtis_<network> session cookie. No owner or tenant selector is accepted.","responses":{"200":{"description":"Authorized result; never cache credentials or samples"},"401":{"description":"DID workbench session required or expired"},"403":{"description":"Owner/scope mismatch, revoked device or decryption denied"},"409":{"description":"Waiting for samples, conflicting operation or creation needs reconciliation"}}}},"/api/tenant-access/{action}":{"post":{"summary":"Rotate or revoke your tenant application credentials","description":"Native DID cookie and exact configured Origin required. Body confirm must be true. Rotation checks the existing on-chain subscription; no purchase, activation or renewal is performed. Rotation returns a secret objectid.tenant-access.v1 JSON once. Revocation here preserves separate device credentials.","parameters":[{"name":"action","in":"path","required":true,"schema":{"type":"string","enum":["rotate","revoke"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["confirm"],"properties":{"confirm":{"type":"boolean","enum":[true]}}}}}},"responses":{"200":{"description":"Authorized result; never cache credentials or samples"},"401":{"description":"DID workbench session required or expired"},"402":{"description":"Active subscription required for rotation; manage it in DT"},"403":{"description":"Owner/scope mismatch, revoked device or decryption denied"},"409":{"description":"Waiting for samples, conflicting operation or creation needs reconciliation"},"422":{"description":"Explicit confirmation required"}}}},"/api/device-auth/session":{"get":{"summary":"Get native DID session and linked-subscription status, or public login availability","responses":{"200":{"description":"Authorized result; never cache credentials or samples"},"401":{"description":"DID workbench session required or expired"},"403":{"description":"Owner/scope mismatch, revoked device or decryption denied"},"409":{"description":"Waiting for samples, conflicting operation or creation needs reconciliation"}}}},"/api/device-auth/challenge":{"post":{"summary":"Start native DID login; same-origin browser only, five-minute one-time challenge","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Authorized result; never cache credentials or samples"},"401":{"description":"DID workbench session required or expired"},"403":{"description":"Owner/scope mismatch, revoked device or decryption denied"},"409":{"description":"Waiting for samples, conflicting operation or creation needs reconciliation"}}}},"/api/device-auth/verify":{"post":{"summary":"Verify local personal-message signature and on-chain ControllerCap; issue 30-minute Secure HttpOnly SameSite=Strict cookie","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Authorized result; never cache credentials or samples"},"401":{"description":"DID workbench session required or expired"},"403":{"description":"Owner/scope mismatch, revoked device or decryption denied"},"409":{"description":"Waiting for samples, conflicting operation or creation needs reconciliation"}}}},"/api/device-auth/logout":{"post":{"summary":"Revoke native DID cookie session; same-origin only","responses":{"204":{"description":"Logged out"}}}},"/api/v1/device-workbench/session":{"post":{"summary":"Create a five-minute workbench session from owner tenant authentication; no global admin key","security":[{"ApiKey":[]}],"responses":{"200":{"description":"Authorized result; never cache credentials or samples"},"401":{"description":"DID workbench session required or expired"},"403":{"description":"Owner/scope mismatch, revoked device or decryption denied"},"409":{"description":"Waiting for samples, conflicting operation or creation needs reconciliation"}}}},"/api/plants/device-workbench/session":{"post":{"summary":"Create a scoped delegated workbench session after TwinScope AAA","security":[{"TwinScopeCreation":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Authorized result; never cache credentials or samples"},"401":{"description":"DID workbench session required or expired"},"403":{"description":"Owner/scope mismatch, revoked device or decryption denied"},"409":{"description":"Waiting for samples, conflicting operation or creation needs reconciliation"}}}},"/api/device-workbench/devices":{"get":{"summary":"List accessible devices; credentials never returned","security":[{"Bearer":[]}],"responses":{"200":{"description":"Authorized result; never cache credentials or samples"},"401":{"description":"DID workbench session required or expired"},"403":{"description":"Owner/scope mismatch, revoked device or decryption denied"},"409":{"description":"Waiting for samples, conflicting operation or creation needs reconciliation"}}},"post":{"summary":"Register device before a Twin exists; return one-time device credentials and optional encryption configuration","security":[{"Bearer":[]}],"responses":{"200":{"description":"Authorized result; never cache credentials or samples"},"201":{"description":"objectid.device-onboarding.v1, contains device secrets"},"401":{"description":"DID workbench session required or expired"},"403":{"description":"Owner/scope mismatch, revoked device or decryption denied"},"409":{"description":"Waiting for samples, conflicting operation or creation needs reconciliation"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/api/device-workbench/devices/{id}/inspect":{"post":{"summary":"Decrypt latest sample with supplied password and discover scalar signal paths","security":[{"Bearer":[]}],"responses":{"200":{"description":"Authorized result; never cache credentials or samples"},"401":{"description":"DID workbench session required or expired"},"403":{"description":"Owner/scope mismatch, revoked device or decryption denied"},"409":{"description":"Waiting for samples, conflicting operation or creation needs reconciliation"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^device-[a-f0-9-]{36}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/api/device-workbench/devices/{id}/classify":{"post":{"summary":"Validate signals and owner subscription, create private Twin once, persist classified schema","security":[{"Bearer":[]}],"responses":{"200":{"description":"Authorized result; never cache credentials or samples"},"401":{"description":"DID workbench session required or expired"},"403":{"description":"Owner/scope mismatch, revoked device or decryption denied"},"409":{"description":"Waiting for samples, conflicting operation or creation needs reconciliation"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^device-[a-f0-9-]{36}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/api/device-workbench/devices/{id}/export":{"get":{"summary":"Export objectid.twin-catalog.v1 references and schema without credentials","security":[{"Bearer":[]}],"responses":{"200":{"description":"Authorized result; never cache credentials or samples"},"401":{"description":"DID workbench session required or expired"},"403":{"description":"Owner/scope mismatch, revoked device or decryption denied"},"409":{"description":"Waiting for samples, conflicting operation or creation needs reconciliation"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^device-[a-f0-9-]{36}$"}}]}},"/api/device-workbench/devices/{id}/revoke":{"post":{"summary":"Revoke device HTTP and MQTT ingestion; does not delete the Twin","security":[{"Bearer":[]}],"responses":{"200":{"description":"Authorized result; never cache credentials or samples"},"401":{"description":"DID workbench session required or expired"},"403":{"description":"Owner/scope mismatch, revoked device or decryption denied"},"409":{"description":"Waiting for samples, conflicting operation or creation needs reconciliation"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^device-[a-f0-9-]{36}$"}}]}},"/api/device-workbench/catalog":{"get":{"summary":"List classified Twins in the authenticated device scope","security":[{"Bearer":[]}],"responses":{"200":{"description":"Authorized result; never cache credentials or samples"},"401":{"description":"DID workbench session required or expired"},"403":{"description":"Owner/scope mismatch, revoked device or decryption denied"},"409":{"description":"Waiting for samples, conflicting operation or creation needs reconciliation"}}}},"/device-input/{tenantId}/{deviceId}":{"post":{"summary":"Publish device sample over HTTPS with device-scoped opaque bearer credential","security":[{"Bearer":[]}],"parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"}},{"name":"deviceId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Authorized result; never cache credentials or samples"},"202":{"description":"Sample accepted; at most one sample per device per second"},"401":{"description":"DID workbench session required or expired"},"403":{"description":"Owner/scope mismatch, revoked device or decryption denied"},"409":{"description":"Waiting for samples, conflicting operation or creation needs reconciliation"}}}},"/.well-known/objectid-dataset-keys.json":{"get":{"summary":"Public Integration Server Ed25519 dataset signing identity; obtain approval independently before trusting it","security":[],"responses":{"200":{"description":"objectid.dataset-signers.v1: issuer, network, keyId (SHA256 SPKI), publicKey (base64 DER SPKI), algorithm, createdAt and status. No private key material."}}}},"/api/v1/shared/twins/{id}/datasets/context":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-f]{64}$"}}],"get":{"summary":"Read authorized historical bounds, measurement scope and export limits","security":[{"TwinReadSession":[]}],"responses":{"200":{"description":"serverTime, sessionExpiresAt, policyRevision, historyFrom, historyTo (exclusive; zero is unlimited), allMeasurements, measurements, maxRangeMs, maxArchiveBytes, ttlMs"},"401":{"description":"DID session missing or expired"},"403":{"description":"DID lacks the required on-chain scope, or access revoked"},"404":{"description":"Request not found or expired"},"429":{"description":"Request rate or export capacity exceeded"}}}},"/api/v1/shared/twins/{id}/history/query":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-f]{64}$"}}],"post":{"summary":"Query filtered retained samples using history scope 2; no ZIP is created","security":[{"TwinReadSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["fromTimestamp","toTimestamp"],"properties":{"measurements":{"type":"array","minItems":1,"maxItems":64,"uniqueItems":true,"items":{"type":"string","pattern":"^[A-Za-z][A-Za-z0-9_]{0,63}$"},"description":"Optional exact keys, a subset of the authorized measures. Omit for all authorized measures. constructor and prototype are not allowed."},"fromTimestamp":{"type":"integer","minimum":0},"toTimestamp":{"type":"integer","minimum":0}}}}}},"responses":{"200":{"description":"Samples, exact selection and current policy revision. Maximum 31 days within the granted history interval; timestamps in UTC milliseconds, query endpoints inclusive."},"401":{"description":"DID session missing or expired"},"403":{"description":"DID lacks the required on-chain scope, or access revoked"},"404":{"description":"Request not found or expired"},"409":{"description":"Source cannot be decrypted or filtered"},"429":{"description":"Request rate or export capacity exceeded"}}}},"/api/v1/shared/twins/{id}/location/latest":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-f]{64}$"}}],"get":{"summary":"Read latest structured position with location scope 8","security":[{"TwinReadSession":[]}],"responses":{"200":{"description":"Twin ID and position, or null if unavailable"},"401":{"description":"DID session missing or expired"},"403":{"description":"DID lacks the required on-chain scope, or access revoked"},"404":{"description":"Request not found or expired"},"429":{"description":"Request rate or export capacity exceeded"}}}},"/api/v1/shared/twins/{id}/realtime/latest":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-f]{64}$"}}],"get":{"summary":"Read telemetry filtered by realtime scope 1 and exact measure keys","security":[{"TwinReadSession":[]}],"responses":{"200":{"description":"Filtered payload; location omitted unless scope 8 is granted"},"401":{"description":"DID session missing or expired"},"403":{"description":"DID lacks the required on-chain scope, or access revoked"},"404":{"description":"Request not found or expired"},"409":{"description":"Source cannot be decrypted or filtered"},"429":{"description":"Request rate or export capacity exceeded"}}}},"/api/v1/shared/twins/{id}/realtime/stream":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-f]{64}$"}}],"get":{"summary":"SSE with scope and revision checks on every sample and heartbeat","security":[{"TwinReadSession":[]}],"responses":{"200":{"description":"telemetry events; revoked event closes the stream on loss of access","content":{"text/event-stream":{"schema":{"type":"string"}}}},"401":{"description":"DID session missing or expired"},"403":{"description":"DID lacks the required on-chain scope, or access revoked"},"404":{"description":"Request not found or expired"},"429":{"description":"Request rate or export capacity exceeded"}}}},"/api/v1/twins/{id}/data-access":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-f]{64}$"}},{"name":"x-objectid-caller-did","in":"header","required":true,"schema":{"type":"string"}}],"get":{"summary":"Owner: read canonical on-chain policy or the legacy activation draft","security":[{"ApiKey":[]},{"Bearer":[]}],"responses":{"200":{"description":"Policy revision, mode, publicScopes, readers with scope bitmask, time bounds and exact measurement keys; legacy Twins return the previous flags"},"401":{"description":"DID session missing or expired"},"403":{"description":"DID lacks the required on-chain scope, or access revoked"},"404":{"description":"Request not found or expired"},"429":{"description":"Request rate or export capacity exceeded"}}},"put":{"summary":"Legacy v1 only: set off-chain permissions; v2 requires an owner-signed Move transaction","security":[{"ApiKey":[]},{"Bearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["mode","visibility","liveLocationVisibility","allowedDids","revision"],"properties":{"mode":{"enum":["private","restricted","public"]},"visibility":{"enum":["private","public"]},"liveLocationVisibility":{"enum":["private","public"]},"allowedDids":{"type":"array","maxItems":100,"items":{"type":"string"}},"storageDids":{"type":"array","maxItems":100,"items":{"type":"string"},"description":"Subset of allowedDids explicitly granted historical access. Omission preserves flags for remaining DIDs of the same owner."},"revision":{"type":"string","nullable":true}}}}}},"responses":{"200":{"description":"Policy updated; earlier export requests invalidated"},"401":{"description":"DID session missing or expired"},"403":{"description":"DID lacks the required on-chain scope, or access revoked"},"404":{"description":"Request not found or expired"},"409":{"description":"Policy revision changed, or Twin uses owner-signed on-chain permissions"},"422":{"description":"Invalid policy"},"429":{"description":"Request rate or export capacity exceeded"}}}},"/api/v1/shared/twins/{id}/challenge":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-f]{64}$"}}],"post":{"summary":"Request a DID-controller personal-message challenge","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["did"],"properties":{"did":{"type":"string"}}}}}},"responses":{"200":{"description":"Challenge ID, exact message to sign and expiry"},"401":{"description":"DID session missing or expired"},"403":{"description":"DID lacks the required on-chain scope, or access revoked"},"404":{"description":"Request not found or expired"},"429":{"description":"Request rate or export capacity exceeded"}}}},"/api/v1/shared/twins/{id}/verify":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-f]{64}$"}}],"post":{"summary":"Verify DID signature and issue Twin-scoped reader session","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["did","challengeId","signature"],"properties":{"did":{"type":"string"},"challengeId":{"type":"string"},"signature":{"type":"string"}}}}}},"responses":{"200":{"description":"Opaque bearer token and expiry. Use token in Authorization header only."},"401":{"description":"DID session missing or expired"},"403":{"description":"DID lacks the required on-chain scope, or access revoked"},"404":{"description":"Request not found or expired"},"429":{"description":"Request rate or export capacity exceeded"}}}},"/api/v1/shared/twins/{id}/dashboard":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-f]{64}$"}}],"get":{"summary":"Restricted Twin identity and current reader permissions","security":[{"TwinReadSession":[]}],"responses":{"200":{"description":"Sanitized identity and permissions.realtime/history/export/location/evidence"},"401":{"description":"DID session missing or expired"},"403":{"description":"DID lacks the required on-chain scope, or access revoked"},"404":{"description":"Request not found or expired"},"429":{"description":"Request rate or export capacity exceeded"}}}},"/api/v1/shared/twins/{id}/datasets":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-f]{64}$"}}],"post":{"summary":"Prepare an ephemeral ZIP of retained telemetry (export scope 4 required, which also requires history scope 2)","security":[{"TwinReadSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["fromTimestamp","toTimestamp"],"properties":{"measurements":{"type":"array","minItems":1,"maxItems":64,"uniqueItems":true,"items":{"type":"string","pattern":"^[A-Za-z][A-Za-z0-9_]{0,63}$"},"description":"Optional exact keys, a subset of the authorized measures. Omit for all authorized measures. constructor and prototype are not allowed."},"fromTimestamp":{"type":"integer","format":"int64","minimum":0,"description":"Inclusive observation time, Unix milliseconds"},"toTimestamp":{"type":"integer","format":"int64","minimum":0,"description":"Inclusive observation time, no future dates, at most 31 days after fromTimestamp"}}}}}},"responses":{"202":{"description":"Preparing: requestId, statusUrl, expiresAt. Poll statusUrl every 2 seconds."},"401":{"description":"DID session missing or expired"},"403":{"description":"DID lacks the required on-chain scope, or access revoked"},"404":{"description":"Request not found or expired"},"422":{"description":"Invalid selection"},"429":{"description":"Request rate or export capacity exceeded"}}}},"/api/v1/shared/twins/{id}/datasets/{requestId}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-f]{64}$"}},{"name":"requestId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"summary":"Read status using the original DID session","security":[{"TwinReadSession":[]}],"responses":{"200":{"description":"preparing/ready/failed; ready includes downloadUrl, sha256 and sampleCount; failed includes safe error"},"401":{"description":"DID session missing or expired"},"403":{"description":"DID lacks the required on-chain scope, or access revoked"},"404":{"description":"Request not found or expired"},"429":{"description":"Request rate or export capacity exceeded"}}},"delete":{"summary":"Cancel and discard a temporary dataset","security":[{"TwinReadSession":[]}],"responses":{"204":{"description":"Discarded"},"401":{"description":"DID session missing or expired"},"403":{"description":"DID lacks the required on-chain scope, or access revoked"},"404":{"description":"Request not found or expired"},"429":{"description":"Request rate or export capacity exceeded"}}}},"/api/v1/shared/twins/{id}/datasets/{requestId}/download":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-f]{64}$"}},{"name":"requestId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"summary":"Download ZIP using original DID session; rechecks on-chain export scope, revision and owner","security":[{"TwinReadSession":[]}],"responses":{"200":{"description":"Filtered CSV, JSON and hash manifest; no new on-chain attestation. v2 encrypted sources are decrypted internally when the source key is configured, otherwise denied","headers":{"X-Dataset-SHA256":{"schema":{"type":"string"}}},"content":{"application/zip":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"DID session missing or expired"},"403":{"description":"DID lacks the required on-chain scope, or access revoked"},"404":{"description":"Request not found or expired"},"409":{"description":"Dataset not ready"},"429":{"description":"Request rate or export capacity exceeded"}}}},"/health":{"get":{"summary":"Liveness","responses":{"200":{"description":"Alive"}}}},"/ready":{"get":{"summary":"ObjectID and required dependency readiness","responses":{"200":{"description":"Ready"},"503":{"description":"Not ready"}}}},"/status.json":{"get":{"summary":"Sanitized public DTIS service status and aggregate metrics","responses":{"200":{"description":"Public operations status"}}}},"/api/v1/twins/{id}":{"get":{"summary":"Get Twin","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Twin"}}},"patch":{"summary":"Update Twin name, description and mutable metadata (owner/steward policy enforced)","responses":{"200":{"description":"Updated on-chain"},"403":{"description":"Twin policy denied"}}}},"/api/v1/capabilities":{"get":{"summary":"Discover Integration Server capabilities","responses":{"200":{"description":"Capabilities"}}}},"/api/v1/subscription":{"get":{"summary":"Get the authenticated tenant's on-chain subscription plan, period and usage","responses":{"200":{"description":"Tenant subscription accounting"},"403":{"description":"Tenant/subscription mismatch"},"503":{"description":"Subscription unavailable"}}}},"/api/v1/storage/retention/status":{"get":{"summary":"Inspect automatic managed-storage retention status","responses":{"200":{"description":"Retention policy and last pruning run"}}}},"/api/v1/twins/{id}/realtime/status":{"get":{"summary":"Get realtime availability for a Twin","responses":{"200":{"description":"Realtime status"}}}},"/api/v1/public/twins/{id}/realtime/status":{"get":{"summary":"Get sanitized realtime availability for an on-chain public Twin (no authentication)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{64}$"}}],"responses":{"200":{"description":"Sanitized public realtime status"},"404":{"description":"Twin is absent, invalid or not public on-chain"}}}},"/api/v1/public/twins/{id}/realtime/latest":{"get":{"summary":"Get the latest payload when both Twin and operational-data visibility are public on-chain","responses":{"200":{"description":"Public realtime event without connector or tenant details"},"404":{"description":"Public operational data is unavailable or not enabled"}}}},"/api/v1/public/twins/{id}/location/latest":{"get":{"summary":"Get the latest normalized position when public live-location access is enabled on-chain","responses":{"200":{"description":"Public CRS84 position without telemetry or connector details"},"404":{"description":"Public live location is unavailable or not enabled"}}}},"/api/v1/public/twins/{id}/realtime/stream":{"get":{"summary":"Stream public operational data using SSE while the on-chain policy remains public","responses":{"200":{"description":"Sanitized public SSE stream"},"404":{"description":"Public operational data is not enabled"}}}},"/api/v1/twins/{id}/realtime/latest":{"get":{"summary":"Get the latest mapped realtime event","responses":{"200":{"description":"Realtime event"},"404":{"description":"No realtime data"}}}},"/api/v1/twins/{id}/location/latest":{"get":{"summary":"Get the latest normalized CRS84 position","responses":{"200":{"description":"Latest live position"},"404":{"description":"No live position"}}}},"/api/v1/twins/{id}/realtime/stream":{"get":{"summary":"Stream mapped realtime events using SSE","responses":{"200":{"description":"SSE stream"}}}},"/api/v1/twins/{id}/command-catalog":{"get":{"summary":"Get the policy-filtered command catalog","responses":{"200":{"description":"Command catalog"},"403":{"description":"Twin policy denied"}}}},"/api/v1/twins/{id}/commands":{"get":{"summary":"List recent commands","responses":{"200":{"description":"Command history"}}},"post":{"summary":"Authorize, persist and dispatch a catalog command","responses":{"202":{"description":"Command dispatched"},"403":{"description":"Twin policy denied"},"422":{"description":"Invalid or unlisted command"}}}},"/api/v1/twins/{id}/commands/{commandId}":{"get":{"summary":"Get command status","responses":{"200":{"description":"Command record"},"404":{"description":"Command not found"}}}},"/api/v1/dids/{did}/twins":{"get":{"summary":"List Twins associated with a DID","responses":{"200":{"description":"Twin summaries and DID roles"}}}},"/api/v1/twins":{"post":{"summary":"Create a personal Twin with the authenticated owner's subscription","description":"Requires the subscription owner. DTIS creates/reuses a private owner-isolated personal plant when plantId is omitted; organizational tenantId is null. The owner subscription must be active with Twin capacity and credits.","parameters":[{"name":"Idempotency-Key","in":"header","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"201":{"description":"Created, including twinId, plantId, ownerDid, requesterDid and tenantId"},"402":{"description":"Subscription inactive or exhausted"},"403":{"description":"Not the subscription or plant owner"}}}},"/api/plants/twins":{"post":{"summary":"Create a plant-owned Twin after delegated TwinScope AAA authorization","security":[{"TwinScopeCreation":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["plantId","nodeId","name"],"properties":{"plantId":{"type":"string"},"nodeId":{"type":"string"},"name":{"type":"string"}}}}}},"responses":{"201":{"description":"Created for the pinned plant owner's subscription; requester tracked separately"},"401":{"description":"Missing or invalid scoped assertion"},"402":{"description":"Plant owner subscription unavailable or exhausted"},"403":{"description":"Scope or owner mismatch"},"404":{"description":"Plant or node not present on this IS"},"409":{"description":"Node already bound or idempotency conflict"}}}},"/api/v1/twins/{id}/states":{"post":{"summary":"Publish Twin state (policy enforced)","responses":{"202":{"description":"Submitted"},"403":{"description":"Twin policy denied"}}}},"/api/v1/twins/{id}/datasets":{"post":{"summary":"Register Twin dataset (policy enforced)","responses":{"202":{"description":"Submitted"},"403":{"description":"Twin policy denied"}}}},"/api/v1/twins/{id}/models":{"post":{"summary":"Register Twin model (policy enforced)","responses":{"202":{"description":"Submitted"},"403":{"description":"Twin policy denied"}}}},"/api/v1/twins/{id}/interfaces":{"post":{"summary":"Register Twin interface (policy enforced)","responses":{"202":{"description":"Submitted"},"403":{"description":"Twin policy denied"}}}},"/api/v1/twins/{id}/events":{"post":{"summary":"Register business or maintenance event (policy enforced)","responses":{"202":{"description":"Submitted"},"403":{"description":"Twin policy denied"}}}},"/api/v1/twins/{id}/thread":{"get":{"summary":"Get Digital Thread","responses":{"200":{"description":"Events"}}}},"/api/v1/twins/{id}/thread/verify":{"get":{"summary":"Verify Digital Thread","responses":{"200":{"description":"Verification"}}}},"/api/v1/twins/{id}/thread/verify/report":{"get":{"summary":"Export Digital Thread audit evidence","responses":{"200":{"description":"Evidence report"}}}},"/api/v1/twins/{id}/evidence-bundles":{"post":{"summary":"Create one on-demand Dataset snapshot and its Digital Thread anchor","responses":{"201":{"description":"Created Dataset reference"}}}},"/api/v1/twins/{id}/evidence-bundles/{datasetId}":{"get":{"summary":"Download the ZIP for one previously created Dataset snapshot","responses":{"200":{"description":"ZIP evidence bundle"}}}},"/api/v1/twins/{id}/evidence-bundles/validate":{"post":{"summary":"Validate a locally hashed snapshot ZIP against its live IOTA Dataset object and Digital Thread event","responses":{"200":{"description":"Evidence validation result"}}}},"/api/v1/twins/{id}/validate-profile":{"post":{"summary":"Validate a payload against a versioned ISO-alignment profile","responses":{"200":{"description":"Validation result"}}}},"/api/v1/profiles/{profileId}/validate":{"post":{"summary":"Validate a payload without Twin context","responses":{"200":{"description":"Validation result"},"422":{"description":"Profile is not validatable"}}}},"/api/v1/profiles":{"get":{"summary":"List versioned profiles","responses":{"200":{"description":"Profiles"}}}},"/api/v1/twins/{id}/identifiers":{"get":{"summary":"Get identifiers","responses":{"200":{"description":"Identifiers"}}}},"/api/v1/resolve/{scheme}/{value}":{"get":{"summary":"Resolve globally through the ObjectID indexer or use the bounded twinId fallback","parameters":[{"name":"twinId","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Matches"},"501":{"description":"Indexer required"}}}},"/api/v1/resolve/{sourceScheme}/{value}/to/{targetScheme}":{"get":{"summary":"Resolve a cross-scheme mapping globally or within twinId","parameters":[{"name":"twinId","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Resolution"},"501":{"description":"Indexer required"}}}},"/api/v1/twins/{id}/maturity/evaluate":{"post":{"summary":"Evaluate maturity profile","parameters":[{"name":"commit","in":"query","schema":{"type":"boolean"}}],"responses":{"200":{"description":"Assessment"}}}},"/api/v1/twins/{id}/maturity/assessments":{"post":{"summary":"Create maturity assessment (policy enforced)","responses":{"202":{"description":"Submitted"},"403":{"description":"Twin policy denied"}}}}}}