@thinger-io/cli-core 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +100 -0
- package/README.md +37 -5
- package/lib/api.js +3 -0
- package/lib/auth.js +29 -9
- package/lib/bucket.js +3 -0
- package/lib/cli.js +15 -2
- package/lib/config.js +55 -5
- package/lib/constants.js +8 -0
- package/lib/dashboard.js +605 -0
- package/lib/docs.js +182 -0
- package/lib/errors.js +29 -4
- package/lib/mcp/catalog.js +1235 -0
- package/lib/mcp/helpers.js +1 -1
- package/lib/mcp/registry.js +72 -30
- package/lib/mcp/resource-hooks.js +145 -0
- package/lib/mcp/server.js +46 -5
- package/lib/mcp/tools-buckets.js +79 -80
- package/lib/mcp/tools-dashboards.js +123 -0
- package/lib/mcp/tools-devices.js +88 -234
- package/lib/mcp/tools-misc.js +48 -0
- package/lib/mcp/tools-plugins.js +63 -0
- package/lib/mcp/tools-products.js +32 -385
- package/lib/mcp/tools-resource.js +760 -0
- package/lib/mcp/tools-storage.js +173 -0
- package/lib/openapi.js +169 -0
- package/lib/paths.js +8 -0
- package/lib/resource.js +2 -0
- package/lib/storage.js +2 -1
- package/openapi/swagger.json +1 -0
- package/package.json +3 -2
- package/lib/mcp/tools-alarms.js +0 -507
- package/lib/mcp/tools-profile.js +0 -635
- package/lib/mcp/tools-profiles.js +0 -30
- package/lib/mcp/tools-properties.js +0 -84
- package/lib/mcp/tools-resources.js +0 -83
- package/lib/mcp/tools-tokens.js +0 -370
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"components":{"schemas":{"alarm_rule":{"properties":{"activation":{"type":"object"},"check_interval":{"properties":{"magnitude":{"enum":["second","minute","hour","day","week","month","year"],"type":"string"},"value":{"minimum":0,"type":"number"}},"type":"object"},"data":{"type":"object"},"description":{"$ref":"#/components/schemas/resource_description"},"name":{"$ref":"#/components/schemas/resource_name"},"normalization":{"type":"object"},"reminder":{"type":"object"},"rule":{"$ref":"#/components/schemas/resource_id"},"severity":{"maximum":4,"minimum":0,"type":"number"}},"title":"Alarm Rule","type":"object"},"bucket_backend":{"description":"Specifies the database backend to use for storage, with an option for default (represented by an empty string), 'mongodb', or 'influxdb'.","enum":["","mongodb","influxdb","dynamodb"],"title":"Bucket Backend","type":"string"},"bucket_config":{"description":"Configuration schema for a data bucket specifying how data is sourced and updated. This schema supports multiple source types including devices and MQTT topics, each with its own set of required properties.","oneOf":[{"additionalProperties":false,"description":"Configuration for data sourced from a device. This requires specifying the device, user, resource, update interval, and optional tags.","properties":{"device":{"$ref":"#/components/schemas/resource_id","description":"The unique identifier for the device."},"interval":{"description":"The time between updates, in seconds.","type":"number"},"resource":{"description":"The specific resource from the device being tracked.","maxLength":255,"type":"string"},"source":{"description":"Indicates the data source is a device.","enum":["device"],"type":"string"},"tags":{"description":"A collection of tags for categorization, limited to 5.","items":{"$ref":"#/components/schemas/resource_id"},"maxItems":5,"type":"array"},"update":{"description":"Specifies that the bucket is updated at regular intervals.","enum":["interval"],"type":"string"},"user":{"$ref":"#/components/schemas/resource_id","description":"The unique identifier for the user associated with this bucket."}},"required":["source","device","resource","update","interval"],"type":"object"},{"additionalProperties":false,"description":"Configuration for data sourced from a device with event-based or no updates. This variation does not require an interval.","properties":{"device":{"$ref":"#/components/schemas/resource_id","description":"The unique identifier for the device."},"resource":{"description":"The specific resource from the device being tracked.","maxLength":255,"type":"string"},"source":{"description":"Indicates the data source is a device.","enum":["device"],"type":"string"},"tags":{"description":"A collection of tags for categorization, limited to 5.","items":{"$ref":"#/components/schemas/resource_id"},"maxItems":5,"type":"array"},"update":{"description":"Specifies how the bucket is updated: either by specific events or not updated automatically.","enum":["events","none"],"type":"string"},"user":{"$ref":"#/components/schemas/resource_id","description":"The unique identifier for the user associated with this bucket."}},"required":["source","device","resource","update"],"type":"object"},{"additionalProperties":false,"description":"Configuration for data sourced from an MQTT topic. This requires specifying the topic and allows optional tags.","properties":{"source":{"description":"Indicates the data source is an MQTT topic.","enum":["mqtt"],"type":"string"},"tags":{"description":"A collection of tags for categorization, limited to 5.","items":{"$ref":"#/components/schemas/resource_id"},"maxItems":5,"type":"array"},"topic":{"description":"The MQTT topic from which data is sourced.","maxLength":512,"type":"string"}},"required":["source","topic"],"type":"object"},{"additionalProperties":false,"description":"Configuration for data manually written or provided via an API. This variation only requires source specification and allows optional tags.","properties":{"source":{"description":"Indicates the data source is either manually written ('write') or sourced via an API ('api').","enum":["write","api"],"type":"string"},"tags":{"description":"A collection of tags for categorization, limited to 5.","items":{"$ref":"#/components/schemas/resource_id"},"maxItems":5,"type":"array"}},"required":["source"],"type":"object"}],"title":"Bucket Config"},"bucket_retention":{"description":"Configuration schema for data bucket retention policy.","properties":{"period":{"description":"The duration of the retention period. 0 for unlimited retention.","examples":[30],"minimum":0,"type":"integer"},"unit":{"description":"The unit of measurement for the retention period.","enum":["hours","days","weeks","months","years"],"examples":["days"],"type":"string"}},"required":[],"title":"Bucket Retention","type":"object"},"claim_config":{"additionalProperties":false,"properties":{"domain":{"pattern":"^([a-zA-Z0-9-_]+\\.)*[a-zA-Z0-9][a-zA-Z0-9-_]+\\.[a-zA-Z]{2,11}?$","type":"string"},"max_claims":{"minimum":0,"type":"integer"},"members":{"items":{"$ref":"#/components/schemas/resource_id"},"type":"array"},"members_roles":{"items":{"$ref":"#/components/schemas/resource_id"},"type":"array"},"projects":{"items":{"$ref":"#/components/schemas/resource_id"},"type":"array"},"resources":{"items":{"properties":{"identifiers":{"items":{"type":"string"},"type":"array"},"type":{"type":"string"}},"type":"object"},"type":"array"}},"required":["resources"],"title":"Claim Config","type":"object"},"comparison_expressions":{"description":"Comparison expressions for conditional evaluation. Every comparison but present / absent is false on a missing field.","enum":["above","below","equal","not_equal","inside","outside","present","absent"],"title":"Comparison Expressions","type":"string"},"operator_expressions":{"description":"Operator expressions for conditional evaluation","enum":["and","or"],"title":"Operator Expressions","type":"string"},"permission":{"patternProperties":{"^[a-zA-Z0-9_-]{1,32}$|^\\*$":{"minProperties":1,"patternProperties":{"^[a-zA-Z0-9_]{1,32}(?:@[a-zA-Z0-9_]{1,32})?$|^\\*$":{"oneOf":[{"pattern":"^[a-zA-Z0-9_\\*]{1,64}$|^\\*$","type":"string"},{"items":{"oneOf":[{"pattern":"^[a-zA-Z0-9_\\*]{1,64}$|^\\*$","type":"string"},{"patternProperties":{"^[a-zA-Z0-9_-]{1,32}$":{"oneOf":[{"pattern":"^[a-zA-Z0-9_\\*]{1,32}$|^\\*$","type":"string"},{"items":{"type":"string"},"type":"array"}]}},"type":"object"}]},"type":"array"}]}}}},"title":"Permission","type":"object"},"product_conditional_icon":{"additionalProperties":false,"description":"Conditional Icon schema for a product","properties":{"conditions":{"items":{"oneOf":[{"additionalProperties":false,"properties":{"comparison":{"$ref":"#/components/schemas/comparison_expressions"},"field":{"maxLength":255,"minLength":1,"type":"string"},"operator":{"$ref":"#/components/schemas/operator_expressions"},"tag":{"type":"string"},"value":{"maxLength":255,"minLength":1,"type":"string"}},"required":["value"]},{"additionalProperties":false,"properties":{"comparison":{"$ref":"#/components/schemas/comparison_expressions"},"field":{"maxLength":255,"minLength":1,"type":"string"},"max":{"maxLength":255,"minLength":1,"type":"string"},"min":{"maxLength":255,"minLength":1,"type":"string"},"operator":{"$ref":"#/components/schemas/operator_expressions"},"tag":{"type":"string"}},"required":["min","max"]}],"required":["comparison","field","operator","tag"],"type":"object"},"type":"array"},"icon":{"$ref":"#/components/schemas/product_icon"}},"required":["icon"],"title":"Product Conditional Icon","type":"object"},"product_config":{"additionalProperties":false,"description":"Configuration schema for a product","properties":{"fields":{"items":{"$ref":"#/components/schemas/product_field"},"type":"array"},"icons":{"items":{"$ref":"#/components/schemas/product_conditional_icon"},"type":"array"},"type":{"description":"Product type that determines the device status view","enum":["","thinremote"],"type":"string"}},"required":[],"title":"Product Config","type":"object"},"product_field":{"additionalProperties":false,"description":"Field schema for a product","properties":{"icon":{"$ref":"#/components/schemas/product_icon"},"name":{"maxLength":255,"minLength":1,"type":"string"},"primary":{"type":"boolean"},"type":{"enum":["string","number","date","time","datetime","timeago"],"type":"string"},"value":{"maxLength":255,"minLength":1,"type":"string"}},"required":["name","value"],"title":"Product Field","type":"object"},"product_icon":{"additionalProperties":false,"description":"Icon schema for a product","properties":{"background":{"type":"string"},"color":{"type":"string"},"size":{"type":"number"},"source":{"type":"string"},"type":{"description":"Icon type: font-awesome or svg","enum":["fa","svg"],"type":"string"}},"required":["type","source"],"title":"Product Icon","type":"object"},"product_profile_category":{"additionalProperties":{"$ref":"#/components/schemas/product_profile_entry"},"description":"Every entry of a category, by id. Replaces the whole category: entries missing from the body are removed (for properties, also the default property on the devices).","title":"Product profile category","type":["object","null"]},"product_profile_code":{"description":"JavaScript run by the server for this product: functions referenced by payload_function, device_id_resolver and function targets. Inline in `code`, or the files of a file storage in `storage` (takes precedence): its `index.js`, or `<path>/index.js` with `path`, so one storage can hold a whole application (dashboard, product code\u2026).","properties":{"code":{"type":["string","null"]},"path":{"description":"Folder of the storage with the code (its index.js and node_modules), relative to the storage root, e.g. \"code/meter\". Empty: the storage root.","type":["string","null"]},"storage":{"description":"File storage id with the product code.","type":["string","null"]}},"title":"Product profile code","type":["object","null"]},"product_profile_entry":{"description":"One entry of a product profile category; its id is the {resource} path parameter (or the key in a category body). Entries only run when `enabled` is true. Fields by category. properties: `data` fills the device property of the same id (optional), `default.value` (any value but null: {}, [], \"\", 0 and false count) / `form` / `perm` make it a property of the product, which every device of the product inherits (source: product) until it sets its own. buckets: `data` writes into the bucket with the entry id, created on the first write, outside any project (devices read it through GET /devices/{device}/buckets/{bucket}/data); an id containing {{device}} gives one bucket per device (such ids only fit the whole-category PUT, as the {resource} path parameter cannot hold braces), otherwise one shared bucket tagged with device (and group); `tags`, `backend`, `retention`. flows: `data` \u2192 `sink`, `split_data` sends each array element separately. api: resources added to every device of the product: `request.data` (target), `response.data` (response), `device_id_resolver` (function of the product code that returns the device id from the payload, needed to call the resource through POST /products/{product}/resources/{resource}), `handle_connectivity` (validate / auto-provision the device on calls; default true for resource_stream targets). autoprovisions: `config`. endpoints: deprecated, use flows with an endpoint_call sink.","properties":{"backend":{"description":"buckets: storage backend of the bucket when it is created (mongodb, influxdb, dynamodb; default the server's)."},"config":{"description":"autoprovisions: when a device that does not exist authenticates or calls a resource and its id matches `pattern`, it is created in this product (HTTP, or Subdevice for MQTT), with asset `type` / `group` and `project` if given.","properties":{"group":{"description":"Asset group for the new devices.","type":["string","null"]},"mode":{"description":"pattern","type":["string","null"]},"pattern":{"description":"Regular expression on the device id, e.g. ^meter_[0-9]{6}$.","type":["string","null"]},"project":{"description":"Project for the new devices.","type":["string","null"]},"type":{"description":"Asset type for the new devices.","type":["string","null"]}},"type":["object","null"]},"data":{"anyOf":[{"$ref":"#/components/schemas/product_profile_source"},{"items":{"$ref":"#/components/schemas/product_profile_source"},"type":["array","null"]},{"type":"null"}],"description":"Data source, or an array of sources."},"default":{"description":"properties: value of the product property that the devices inherit until they set their own, in `value`. Any value but null counts, {} and [] included.","properties":{"value":{}},"type":["object","null"]},"description":{"type":["string","null"]},"device_id_resolver":{"type":["string","null"]},"enabled":{"type":["boolean","null"]},"form":{"description":"properties: form used by the console to edit the value (`fields`).","type":["object","null"]},"handle_connectivity":{"type":["boolean","null"]},"name":{"type":["string","null"]},"perm":{"description":"properties: permissions for project members.","properties":{"hidden":{"type":["boolean","null"]},"readOnly":{"description":"owner | member"}},"type":["object","null"]},"request":{"properties":{"data":{"anyOf":[{"$ref":"#/components/schemas/product_profile_target"},{"type":"null"}]}},"type":["object","null"]},"response":{"properties":{"data":{"anyOf":[{"$ref":"#/components/schemas/product_profile_response"},{"type":"null"}]}},"type":["object","null"]},"retention":{"description":"buckets: retention of the bucket when it is created.","properties":{"period":{"description":"0 = unlimited.","type":["integer","string","null"]},"unit":{"description":"hours | days | weeks | months | years","type":["string","null"]}},"type":["object","null"]},"sink":{"anyOf":[{"$ref":"#/components/schemas/product_profile_target"},{"type":"null"}]},"split_data":{"type":["boolean","null"]},"tags":{"description":"buckets: record fields stored as tags (filterable), e.g. [\"line\"].","type":["array","null"]},"type":{"description":"properties: \"\" or configuration.","type":["string","null"]}},"title":"Product profile entry","type":["object","null"]},"product_profile_payload_type":{"description":"How the payload is built. template_payload (default): `payload` is a template that may use {{payload}}, {{payload.field}}, {{device}}, {{property.<name>}}, {{api.<resource>}} or {{meta.<device field>}}; without `payload` it yields nothing, so a properties or buckets entry writes nothing. source_payload: the data as received (the same as `payload` \"{{payload}}\"). source_event: the whole event (device, product, timestamps, payload\u2026). none: no payload.","type":["string","null"]},"product_profile_response":{"description":"What an API resource answers (`response.data`). `source` selects it: request_response: what the request target returned; topic \u2192 `topic`: wait for a message on that MQTT topic (from the same device, or any with `publish_source`: any); property \u2192 `property`; resource \u2192 `resource`; function \u2192 `function`; endpoint_call \u2192 `endpoint`; none. The answer can be shaped with `payload` / `payload_type` / `payload_function`.","properties":{"endpoint":{"type":["string","null"]},"function":{"type":["string","null"]},"payload":{"description":"Template string (payload_type template_payload) or JSON value."},"payload_function":{"type":["string","null"]},"payload_type":{"anyOf":[{"$ref":"#/components/schemas/product_profile_payload_type"},{"type":"null"}]},"property":{"type":["string","null"]},"publish_source":{"description":"source topic: empty (only the same device) or any.","type":["string","null"]},"resource":{"type":["string","null"]},"source":{"description":"request_response | topic | property | resource | function | endpoint_call | none","type":["string","null"]},"topic":{"type":["string","null"]}},"title":"Product profile API response","type":["object","null"]},"product_profile_source":{"description":"Where a properties / buckets / flows entry gets its data. `source` selects the fields used: topic \u2192 `topic` (MQTT topic, + and # wildcards; {{name}} placeholders match one level, and in buckets each one becomes a tag of the record, with {{field}} naming the record field so several topics merge into one record); resource \u2192 `resource`, `update` (interval | events) with `interval` + `magnitude`; resource_stream \u2192 `resource_stream` (the device pushes it); product_stream \u2192 `product_stream`; event \u2192 `event` with optional `filter`. Only devices of this product are listened to. The received data can then be transformed with `payload_type` / `payload` and `payload_function`.","properties":{"event":{"description":"source event: server event name, e.g. device_state_change, device_property_update, bucket_write.","type":["string","null"]},"filter":{"description":"source event: extra filters (event field: value or regex). The product filter is always added.","type":["object","null"]},"interval":{"description":"source resource with update interval: number of `magnitude` units between reads, e.g. 60.","type":["number","string","null"]},"magnitude":{"description":"second (default) | minute | hour | day | week | month | year","type":["string","null"]},"patch":{"description":"properties only: merge the value into the device property instead of replacing it.","type":["boolean","null"]},"payload":{"description":"Template string (payload_type template_payload) or JSON value."},"payload_function":{"description":"Name of a function of the product code that receives the payload and returns the value to use.","type":["string","null"]},"payload_type":{"anyOf":[{"$ref":"#/components/schemas/product_profile_payload_type"},{"type":"null"}]},"product_stream":{"description":"source product_stream: stream published by an API resource or flow of this product (target product_stream).","type":["string","null"]},"resource":{"description":"source resource: device resource read by the server.","type":["string","null"]},"resource_stream":{"description":"source resource_stream: device resource the device streams on its own.","type":["string","null"]},"source":{"description":"topic | resource | resource_stream | product_stream | event","type":["string","null"]},"topic":{"description":"source topic: MQTT topic of the device messages, e.g. devices/{{device}}/telemetry.","type":["string","null"]},"update":{"description":"source resource: interval (default, read every `interval` `magnitude`) | events (the device streams it when it changes).","type":["string","null"]}},"title":"Product profile data source","type":["object","null"]},"product_profile_target":{"description":"What an API resource request (`request.data`) or a flow (`sink`) does. `target` selects the fields used: topic \u2192 `topic` (+ `retain`): publish to the device over MQTT; resource \u2192 `resource`: call a device resource (IOTMP devices); resource_stream \u2192 `resource_stream`; property \u2192 `property`: set a device property; function \u2192 `function`: run a function of the product code; endpoint_call \u2192 `endpoint`: call an endpoint; plugin_endpoint \u2192 `plugin` + `path`; product_stream \u2192 `product_stream` (and optional `product`): publish to a product stream; none. The body sent is built from `payload` / `payload_type` / `payload_function`. A target needs a device: the one in the URL, the source device, or the one returned by the entry's `device_id_resolver`.","properties":{"endpoint":{"description":"target endpoint_call: endpoint id (may use placeholders).","type":["string","null"]},"function":{"type":["string","null"]},"path":{"description":"target plugin_endpoint: path inside the plugin, e.g. /api/process.","type":["string","null"]},"payload":{"description":"Template string (payload_type template_payload) or JSON value."},"payload_function":{"type":["string","null"]},"payload_type":{"anyOf":[{"$ref":"#/components/schemas/product_profile_payload_type"},{"type":"null"}]},"plugin":{"type":["string","null"]},"product":{"type":["string","null"]},"product_stream":{"type":["string","null"]},"property":{"type":["string","null"]},"resource":{"type":["string","null"]},"resource_stream":{"type":["string","null"]},"retain":{"description":"target topic: publish as a retained MQTT message.","type":["boolean","null"]},"target":{"description":"topic | resource | resource_stream | property | function | endpoint_call | plugin_endpoint | product_stream | none","type":["string","null"]},"topic":{"type":["string","null"]}},"title":"Product profile target","type":["object","null"]},"product_service":{"description":"A service the devices of the product expose, reached through the server: web (HTTP proxy) or vnc (remote desktop). The target is the address and port as seen from the device.","properties":{"description":{"type":["string","null"]},"enabled":{"type":["boolean","null"]},"name":{"type":["string","null"]},"security":{"properties":{"ip_filtering":{"type":["boolean","null"]},"timeout_minutes":{"type":["number","null"]}},"type":["object","null"]},"target":{"properties":{"address":{"description":"e.g. 127.0.0.1","type":["string","null"]},"port":{"description":"e.g. 8080","type":["integer","string","null"]},"secure":{"description":"The target uses TLS.","type":["boolean","null"]}},"type":["object","null"]},"type":{"description":"web (default) | vnc","type":["string","null"]},"vnc":{"properties":{"compression":{"type":["number","null"]},"quality":{"type":["number","null"]},"scale":{"type":["boolean","null"]},"shared":{"type":["boolean","null"]},"viewonly":{"type":["boolean","null"]}},"type":["object","null"]}},"title":"Product service","type":["object","null"]},"projects_ids":{"description":"A collection of unique project IDs, ensuring no duplicates within the array.","items":{"description":"An array of unique project identifiers, each following a 'username@project' format with each part limited to 32 alphanumeric characters, underscores or hyphens.","example":["project1@domain1","project2@domain2"],"pattern":"^[a-zA-Z0-9_-]{1,32}@[a-zA-Z0-9_-]{1,32}$","title":"Project IDs","type":"string"},"title":"Projects IDs Array","type":"array","uniqueItems":true},"property":{"description":"Schema for a property","properties":{"description":{"$ref":"#/components/schemas/resource_description"},"form":{"additionalProperties":false,"properties":{"fields":{}},"required":["fields"],"type":"object"},"name":{"$ref":"#/components/schemas/resource_name"},"perm":{"additionalProperties":false,"properties":{"hidden":{"items":{"enum":["owner","member"],"type":"string"},"type":"array","uniqueItems":true},"readOnly":{"items":{"enum":["owner","member"],"type":"string"},"type":"array","uniqueItems":true}},"type":"object"},"property":{"$ref":"#/components/schemas/resource_id"},"type":{"enum":["","configuration"],"type":"string"},"value":{}},"title":"Property","type":"object"},"property_create":{"allOf":[{"$ref":"#/components/schemas/property"},{"required":["property","value"],"type":"object"}],"description":"Schema for creating a property","title":"Property Create"},"property_update":{"allOf":[{"$ref":"#/components/schemas/property"},{"required":["value"],"type":"object"}],"description":"Schema for updating a property","title":"Property Update"},"resource_description":{"description":"A brief description of the resource, providing context or additional information, limited to 255 characters.","example":["Bucket storing all device measurements.","Dashbord for main floor."],"maxLength":255,"title":"Resource Description","type":"string"},"resource_id":{"description":"A unique identifier for resources, consisting of alphanumeric characters, underscores, or hyphens, and limited to 32 characters.","example":["resource_123","abcd-1234"],"pattern":"^[a-zA-Z0-9_-]{1,32}$","title":"Resource ID","type":"string"},"resource_name":{"description":"The name of the resource, limited to 255 characters. It can include any character.","example":["Raspberry Pi","Arduino MKR1000"],"maxLength":255,"title":"Resource Name","type":"string"},"sync_config":{"oneOf":[{"additionalProperties":false,"properties":{"available":{"minimum":0,"type":"integer"},"timeout":{"minimum":0,"type":"integer"}},"required":["available"],"type":"object"}],"title":"Sync Config"}},"securitySchemes":{"bearerAuth":{"bearerFormat":"JWT","scheme":"bearer","type":"http"},"oauth":{"flows":{"password":{"scopes":{"basic":"manage user account"},"tokenUrl":"https://perf.aws.thinger.io:443/oauth/token"}},"type":"oauth2"}}},"info":{"description":"Thinger.io Server API","title":"Thinger.io Server API","version":"1.0.0"},"openapi":"3.1.1","paths":{"/.well-known/acme-challenge/{token}":{"parameters":[{"in":"path","name":"token","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]+","type":"string"}}]},"/brand/{file}":{"parameters":[{"in":"path","name":"file","required":true,"schema":{"pattern":"^.*$","type":"string"}}]},"/oauth/authorize/{identity_provider}":{"parameters":[{"in":"path","name":"identity_provider","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/oauth/device/verification":{"post":{"operationId":"User_AuthorizeDeviceVerification","requestBody":{"content":{"application/json":{"schema":{"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"AuthorizeDevice","tags":["Users"]}},"/oauth/token":{"post":{"operationId":"Authentication_AuthenticateToken","requestBody":{"content":{"application/json":{"schema":{"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"}},"summary":"Authenticate","tags":["Authentication"]}},"/openapi.json":{"get":{"operationId":"Server_ReadApiOpenapi.json","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"}},"summary":"ReadServerApi","tags":["Server"]}},"/users/{user}/plugins/{plugin}{path}":{"delete":{"operationId":"Plugin_CallPluginEndpointDelete","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CallPluginEndpoint","tags":["Plugins"]},"get":{"operationId":"Plugin_CallPluginEndpointGet","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CallPluginEndpoint","tags":["Plugins"]},"head":{"operationId":"Plugin_CallPluginEndpointHead","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CallPluginEndpoint","tags":["Plugins"],"x-internal":true},"options":{"operationId":"Plugin_CallPluginEndpointOptions","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CallPluginEndpoint","tags":["Plugins"],"x-internal":true},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"plugin","required":true,"schema":{"pattern":"^[a-zA-Z0-9_\\-\\:]{1,32}","type":"string"}},{"in":"path","name":"path","required":true,"schema":{"pattern":"^.*$","type":"string"}}],"patch":{"operationId":"Plugin_CallPluginEndpointPatch","requestBody":{"content":{"application/json":{"schema":{"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CallPluginEndpoint","tags":["Plugins"]},"post":{"operationId":"Plugin_CallPluginEndpointPost","requestBody":{"content":{"application/json":{"schema":{"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CallPluginEndpoint","tags":["Plugins"]},"put":{"operationId":"Plugin_CallPluginEndpointPut","requestBody":{"content":{"application/json":{"schema":{"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CallPluginEndpoint","tags":["Plugins"]},"trace":{"operationId":"Plugin_CallPluginEndpointTrace","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CallPluginEndpoint","tags":["Plugins"],"x-internal":true}},"/v1/accounts/password":{"post":{"operationId":"User_CreatePassword","requestBody":{"content":{"application/json":{"schema":{"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"}},"summary":"CreateUserPassword","tags":["Users"]}},"/v1/accounts/password/reset":{"post":{"operationId":"User_CreatePasswordReset","requestBody":{"content":{"application/json":{"schema":{"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"}},"summary":"CreateUserPasswordReset","tags":["Users"]}},"/v1/brands":{"get":{"operationId":"Brand_List","responses":{"200":{"content":{"application/json":{"example":[{"brand":"iot.example.com","created":1791741478037,"description":"Console for Example customers","enabled":true,"modified":1791741478037,"name":"Example IoT"}],"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListBrands","tags":["Brands"]},"post":{"operationId":"Brand_Create","requestBody":{"content":{"application/json":{"examples":{"Brand for a domain":{"value":{"brand":"iot.example.com","config":{"accounts":{"allow_password":true,"public_sign_up":false},"copyright":"\u00a9 Example Inc.","email":"support@example.com","login":{"background_color":"#132533","box_class":"login-center"},"name":"Example","show_community":false,"style":{"topBar":{"background":"#132533","color":"#ffffff"}},"title":"Example IoT Console","url":"https://www.example.com"},"description":"Console for Example customers","enabled":true,"name":"Example IoT"}}},"schema":{"additionalProperties":false,"properties":{"brand":{"description":"The domain the brand applies to (e.g. iot.example.com): the console is branded for requests to that host. Point the domain to this server and register it in domains to get its certificate.","pattern":"^([a-zA-Z0-9-_]+\\.)*[a-zA-Z0-9][a-zA-Z0-9-_]+(?:\\.[a-zA-Z]{2,11})?$","type":"string"},"config":{"description":"Look and behaviour of the console when it is opened on the brand domain. With PUT it replaces the whole stored config (and images missing from it are deleted); PATCH merges it into the stored one.","properties":{"accounts":{"description":"Sign-up and login on this domain. Each key overrides the server setting of the same name (host settings, accounts.*).","properties":{"allow_password":{"description":"Password login (default true).","type":"boolean"},"allow_passwordless":{"description":"Passkey login.","type":"boolean"},"cross_sign_in":{"description":"false: only accounts created on this domain can sign in here (default true).","type":"boolean"},"federated_login":{"description":"Show the identity provider buttons.","type":"boolean"},"identity_providers":{"description":"Identity provider ids offered on this domain; empty offers every enabled one.","items":{},"type":"array"},"no_robot":{"description":"reCAPTCHA on sign-up. The secret is only returned to admins.","properties":{"enabled":{"type":"boolean"},"recaptcha":{"properties":{"secret":{"type":"string"}},"type":"object"}},"type":"object"},"public_sign_up":{"description":"Anyone can create an account.","type":"boolean"},"public_sign_up_member_owner":{"description":"Owner (admin or domain admin) of the project new members join.","type":"string"},"public_sign_up_member_role":{"description":"Role id given to the new members.","type":"string"},"public_sign_up_project":{"properties":{"limit_bucket_access":{"type":"boolean"}},"type":"object"},"public_sign_up_role":{"description":"Role of the new accounts: user or member.","type":"string"},"require_2fa":{"description":"Require a second factor.","type":"boolean"}},"type":"object"},"bright_logo":{"description":"Menu logo. data:image/png;base64,\u2026 or data:image/webp;base64,\u2026 to replace the image (stored under /brand/images/), the stored /brand/images/\u2026 URL to keep it, \"\" or null to remove it.","type":["string","null"]},"copyright":{"description":"Footer text.","type":"string"},"dark_logo":{"description":"Platform logo: login and public pages, exports. data:image/png;base64,\u2026 or data:image/webp;base64,\u2026 to replace the image (stored under /brand/images/), the stored /brand/images/\u2026 URL to keep it, \"\" or null to remove it.","type":["string","null"]},"description":{"description":"Meta description (also og:description).","type":"string"},"email":{"description":"Support address shown in the menu (mailto). Not the sender of emails: see the brand email.","type":"string"},"favicon":{"description":"Browser icon. data:image/png;base64,\u2026 or data:image/webp;base64,\u2026 to replace the image (stored under /brand/images/), the stored /brand/images/\u2026 URL to keep it, \"\" or null to remove it.","type":["string","null"]},"icon":{"description":"Menu icon when the menu is folded. data:image/png;base64,\u2026 or data:image/webp;base64,\u2026 to replace the image (stored under /brand/images/), the stored /brand/images/\u2026 URL to keep it, \"\" or null to remove it.","type":["string","null"]},"index_scripts":{"description":"Raw HTML/JS injected in the page head (analytics\u2026). Empty uses the default tag manager.","type":"string"},"keywords":{"description":"Meta keywords.","type":"string"},"login":{"description":"Login page.","properties":{"background_color":{"description":"CSS color.","type":"string"},"background_image":{"description":"Image URL.","type":"string"},"background_style":{"description":"Extra CSS as \"property:value;property:value\" (values cannot contain ':').","type":"string"},"box_class":{"description":"Position of the login box: login-center, login-left or login-right.","type":"string"},"box_style":{"description":"Inline CSS of the login box.","type":"string"}},"type":"object"},"name":{"description":"Company name, used as title prefix and logo alt text.","type":"string"},"product_types":{"description":"Options of the product type selector.","items":{"properties":{"label":{"type":"string"},"value":{"type":"string"}},"type":"object"},"type":"array"},"pwa":{"description":"Web app manifest (installable app). Served as is at /manifest.webmanifest.","properties":{"background_color":{"type":"string"},"display":{"description":"e.g. standalone.","type":"string"},"icons":{"description":"192x192 and 512x512 icons, each for purpose any and maskable.","items":{"properties":{"purpose":{"description":"any or maskable.","type":"string"},"sizes":{"description":"e.g. 192x192.","type":"string"},"src":{"description":"data:image/png;base64,\u2026 or data:image/webp;base64,\u2026 to replace the image (stored under /brand/images/), the stored /brand/images/\u2026 URL to keep it, \"\" or null to remove it.","type":["string","null"]},"type":{"description":"e.g. image/png.","type":"string"}},"type":"object"},"type":"array"},"name":{"type":"string"},"short_name":{"type":"string"},"start_url":{"type":"string"},"theme_color":{"description":"CSS color, also the browser theme color.","type":"string"}},"type":"object"},"share_image":{"description":"Image for link previews (og:image). data:image/png;base64,\u2026 or data:image/webp;base64,\u2026 to replace the image (stored under /brand/images/), the stored /brand/images/\u2026 URL to keep it, \"\" or null to remove it.","type":["string","null"]},"show_community":{"description":"Show the community links in the menu (default true).","type":"boolean"},"show_version":{"description":"Show the server version (default true).","type":"boolean"},"style":{"properties":{"topBar":{"description":"Console top bar.","properties":{"background":{"description":"CSS color.","type":"string"},"color":{"description":"CSS color of the text and icons.","type":"string"}},"type":"object"}},"type":"object"},"title":{"description":"Page title (also og:title).","type":"string"},"url":{"description":"Link of the logo on the login and public pages.","type":"string"}},"type":"object"},"description":{"type":"string"},"enabled":{"type":"boolean"},"name":{"type":"string"}},"required":["brand"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CreateBrand","tags":["Brands"]}},"/v1/brands/{brand}":{"delete":{"operationId":"Brand_Delete","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteBrand","tags":["Brands"]},"get":{"operationId":"Brand_ReadConfig","responses":{"200":{"content":{"application/json":{"examples":{"Brand for a domain":{"value":{"brand":"iot.example.com","config":{"accounts":{"allow_password":true,"public_sign_up":false},"copyright":"\u00a9 Example Inc.","email":"support@example.com","login":{"background_color":"#132533","box_class":"login-center"},"name":"Example","show_community":false,"style":{"topBar":{"background":"#132533","color":"#ffffff"}},"title":"Example IoT Console","url":"https://www.example.com"},"created":1791741478037,"description":"Console for Example customers","enabled":true,"modified":1791741478037,"name":"Example IoT"}}},"schema":{"type":"object"}}},"description":"ok"}},"summary":"ReadBrandConfig","tags":["Brands"]},"parameters":[{"in":"path","name":"brand","required":true,"schema":{"pattern":"^(?:[a-zA-Z0-9_-]+\\.*[a-zA-Z0-9][a-zA-Z0-9_-]+(?:\\.[a-zA-Z]{2,11})?)","type":"string"}}],"patch":{"operationId":"Brand_Patch","requestBody":{"content":{"application/json":{"examples":{"Change the SMTP password":{"value":{"email":{"settings":{"smtp":{"password":"new-app-password"}}}}},"Change the title only":{"value":{"config":{"title":"New Console Title"}}},"Disable public sign-up":{"value":{"config":{"accounts":{"public_sign_up":false}}}},"Remove a logo":{"value":{"config":{"icon":null}}},"Replace a logo":{"value":{"config":{"dark_logo":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg=="}}}},"schema":{"additionalProperties":false,"description":"Partial update: only the fields sent change; config and email are merged into the stored ones (RFC 7386 merge patch: a null value removes a key). Images left out are kept.","properties":{"config":{"description":"Look and behaviour of the console when it is opened on the brand domain. With PUT it replaces the whole stored config (and images missing from it are deleted); PATCH merges it into the stored one.","properties":{"accounts":{"description":"Sign-up and login on this domain. Each key overrides the server setting of the same name (host settings, accounts.*).","properties":{"allow_password":{"description":"Password login (default true).","type":["boolean","null"]},"allow_passwordless":{"description":"Passkey login.","type":["boolean","null"]},"cross_sign_in":{"description":"false: only accounts created on this domain can sign in here (default true).","type":["boolean","null"]},"federated_login":{"description":"Show the identity provider buttons.","type":["boolean","null"]},"identity_providers":{"description":"Identity provider ids offered on this domain; empty offers every enabled one.","items":{},"type":["array","null"]},"no_robot":{"description":"reCAPTCHA on sign-up. The secret is only returned to admins.","properties":{"enabled":{"type":["boolean","null"]},"recaptcha":{"properties":{"secret":{"type":["string","null"]}},"type":["object","null"]}},"type":["object","null"]},"public_sign_up":{"description":"Anyone can create an account.","type":["boolean","null"]},"public_sign_up_member_owner":{"description":"Owner (admin or domain admin) of the project new members join.","type":["string","null"]},"public_sign_up_member_role":{"description":"Role id given to the new members.","type":["string","null"]},"public_sign_up_project":{"properties":{"limit_bucket_access":{"type":["boolean","null"]}},"type":["object","null"]},"public_sign_up_role":{"description":"Role of the new accounts: user or member.","type":["string","null"]},"require_2fa":{"description":"Require a second factor.","type":["boolean","null"]}},"type":["object","null"]},"bright_logo":{"description":"Menu logo. data:image/png;base64,\u2026 or data:image/webp;base64,\u2026 to replace the image (stored under /brand/images/), the stored /brand/images/\u2026 URL to keep it, \"\" or null to remove it.","type":["string","null"]},"copyright":{"description":"Footer text.","type":["string","null"]},"dark_logo":{"description":"Platform logo: login and public pages, exports. data:image/png;base64,\u2026 or data:image/webp;base64,\u2026 to replace the image (stored under /brand/images/), the stored /brand/images/\u2026 URL to keep it, \"\" or null to remove it.","type":["string","null"]},"description":{"description":"Meta description (also og:description).","type":["string","null"]},"email":{"description":"Support address shown in the menu (mailto). Not the sender of emails: see the brand email.","type":["string","null"]},"favicon":{"description":"Browser icon. data:image/png;base64,\u2026 or data:image/webp;base64,\u2026 to replace the image (stored under /brand/images/), the stored /brand/images/\u2026 URL to keep it, \"\" or null to remove it.","type":["string","null"]},"icon":{"description":"Menu icon when the menu is folded. data:image/png;base64,\u2026 or data:image/webp;base64,\u2026 to replace the image (stored under /brand/images/), the stored /brand/images/\u2026 URL to keep it, \"\" or null to remove it.","type":["string","null"]},"index_scripts":{"description":"Raw HTML/JS injected in the page head (analytics\u2026). Empty uses the default tag manager.","type":["string","null"]},"keywords":{"description":"Meta keywords.","type":["string","null"]},"login":{"description":"Login page.","properties":{"background_color":{"description":"CSS color.","type":["string","null"]},"background_image":{"description":"Image URL.","type":["string","null"]},"background_style":{"description":"Extra CSS as \"property:value;property:value\" (values cannot contain ':').","type":["string","null"]},"box_class":{"description":"Position of the login box: login-center, login-left or login-right.","type":["string","null"]},"box_style":{"description":"Inline CSS of the login box.","type":["string","null"]}},"type":["object","null"]},"name":{"description":"Company name, used as title prefix and logo alt text.","type":["string","null"]},"product_types":{"description":"Options of the product type selector.","items":{"properties":{"label":{"type":["string","null"]},"value":{"type":["string","null"]}},"type":["object","null"]},"type":["array","null"]},"pwa":{"description":"Web app manifest (installable app). Served as is at /manifest.webmanifest.","properties":{"background_color":{"type":["string","null"]},"display":{"description":"e.g. standalone.","type":["string","null"]},"icons":{"description":"192x192 and 512x512 icons, each for purpose any and maskable.","items":{"properties":{"purpose":{"description":"any or maskable.","type":["string","null"]},"sizes":{"description":"e.g. 192x192.","type":["string","null"]},"src":{"description":"data:image/png;base64,\u2026 or data:image/webp;base64,\u2026 to replace the image (stored under /brand/images/), the stored /brand/images/\u2026 URL to keep it, \"\" or null to remove it.","type":["string","null"]},"type":{"description":"e.g. image/png.","type":["string","null"]}},"type":["object","null"]},"type":["array","null"]},"name":{"type":["string","null"]},"short_name":{"type":["string","null"]},"start_url":{"type":["string","null"]},"theme_color":{"description":"CSS color, also the browser theme color.","type":["string","null"]}},"type":["object","null"]},"share_image":{"description":"Image for link previews (og:image). data:image/png;base64,\u2026 or data:image/webp;base64,\u2026 to replace the image (stored under /brand/images/), the stored /brand/images/\u2026 URL to keep it, \"\" or null to remove it.","type":["string","null"]},"show_community":{"description":"Show the community links in the menu (default true).","type":["boolean","null"]},"show_version":{"description":"Show the server version (default true).","type":["boolean","null"]},"style":{"properties":{"topBar":{"description":"Console top bar.","properties":{"background":{"description":"CSS color.","type":["string","null"]},"color":{"description":"CSS color of the text and icons.","type":["string","null"]}},"type":["object","null"]}},"type":["object","null"]},"title":{"description":"Page title (also og:title).","type":["string","null"]},"url":{"description":"Link of the logo on the login and public pages.","type":["string","null"]}},"type":["object","null"]},"description":{"type":"string"},"email":{"description":"Emails sent to accounts of this domain (verification, password\u2026). With PUT it replaces the whole stored email config; PATCH merges it. Read it with GET /v1/brands/{brand}/email and try a template with POST /v1/brands/{brand}/email/test.","properties":{"custom":{"description":"true: send with `settings` instead of the server mail settings.","type":["boolean","null"]},"settings":{"properties":{"from":{"description":"Sender address.","type":["string","null"]},"from_name":{"description":"Sender name.","type":["string","null"]},"ses":{"properties":{"aws_access_key_id":{"type":["string","null"]},"aws_region":{"description":"e.g. eu-west-1.","type":["string","null"]},"aws_secret_access_key":{"type":["string","null"]}},"type":["object","null"]},"smtp":{"properties":{"host":{"type":["string","null"]},"password":{"type":["string","null"]},"port":{"description":"As a string, e.g. \"587\" (numbers are ignored by the server).","pattern":"^[0-9]{1,5}$","type":["string","integer","null"]},"secure":{"description":"true: implicit TLS (usually port 465); false: the server must offer STARTTLS (usually 587).","type":["boolean","null"]},"username":{"type":["string","null"]}},"type":["object","null"]},"type":{"description":"smtp or ses.","type":["string","null"]}},"type":["object","null"]},"templates":{"description":"Per template: email_verification, forgot_password, create_password, device_disabled. Missing fields use the defaults. Subject and body may use {{code}} (the token for the link), {{user}}, {{email}}, {{host}}, {{admin}}, {{host_url}} and, in device_disabled, {{device}}. Links: {{host_url}}/verify_email?code={{code}}, {{host_url}}/password?code={{code}} (forgot_password), {{host_url}}/create_password?code={{code}}. {{name}}, {{url}}, {{logo}} and {{description}} only exist in the built-in defaults: in a custom template write the brand name and the logo URL (e.g. https://<brand>/brand/images/dark_logo.png) directly. The 'enabled' flag is not enforced yet.","properties":{"create_password":{"properties":{"body":{"description":"HTML.","type":["string","null"]},"enabled":{"description":"The built-in defaults carry it as a string.","type":["boolean","string","null"]},"from":{"type":["string","null"]},"from_name":{"type":["string","null"]},"subject":{"type":["string","null"]}},"type":["object","null"]},"device_disabled":{"properties":{"body":{"description":"HTML.","type":["string","null"]},"enabled":{"description":"The built-in defaults carry it as a string.","type":["boolean","string","null"]},"from":{"type":["string","null"]},"from_name":{"type":["string","null"]},"subject":{"type":["string","null"]}},"type":["object","null"]},"email_verification":{"properties":{"body":{"description":"HTML.","type":["string","null"]},"enabled":{"description":"The built-in defaults carry it as a string.","type":["boolean","string","null"]},"from":{"type":["string","null"]},"from_name":{"type":["string","null"]},"subject":{"type":["string","null"]}},"type":["object","null"]},"forgot_password":{"properties":{"body":{"description":"HTML.","type":["string","null"]},"enabled":{"description":"The built-in defaults carry it as a string.","type":["boolean","string","null"]},"from":{"type":["string","null"]},"from_name":{"type":["string","null"]},"subject":{"type":["string","null"]}},"type":["object","null"]}},"type":["object","null"]}},"type":["object","null"]},"enabled":{"type":"boolean"},"name":{"type":"string"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateBrand","tags":["Brands"]},"put":{"operationId":"Brand_Update","requestBody":{"content":{"application/json":{"examples":{"Replace the whole config (logos missing from it are deleted)":{"value":{"config":{"bright_logo":"/brand/images/bright_logo.png","dark_logo":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==","name":"Example","style":{"topBar":{"background":"#132533","color":"#ffffff"}},"title":"Example IoT Console"}}},"Send emails with Amazon SES":{"value":{"email":{"custom":true,"settings":{"from":"noreply@example.com","from_name":"Example IoT","ses":{"aws_access_key_id":"AKIA\u2026","aws_region":"eu-west-1","aws_secret_access_key":"\u2026"},"type":"ses"}}}},"Send emails with SMTP":{"value":{"email":{"custom":true,"settings":{"from":"noreply@example.com","from_name":"Example IoT","smtp":{"host":"smtp.example.com","password":"app-password","port":"587","secure":false,"username":"noreply@example.com"},"type":"smtp"}}}}},"schema":{"additionalProperties":false,"properties":{"config":{"description":"Look and behaviour of the console when it is opened on the brand domain. With PUT it replaces the whole stored config (and images missing from it are deleted); PATCH merges it into the stored one.","properties":{"accounts":{"description":"Sign-up and login on this domain. Each key overrides the server setting of the same name (host settings, accounts.*).","properties":{"allow_password":{"description":"Password login (default true).","type":"boolean"},"allow_passwordless":{"description":"Passkey login.","type":"boolean"},"cross_sign_in":{"description":"false: only accounts created on this domain can sign in here (default true).","type":"boolean"},"federated_login":{"description":"Show the identity provider buttons.","type":"boolean"},"identity_providers":{"description":"Identity provider ids offered on this domain; empty offers every enabled one.","items":{},"type":"array"},"no_robot":{"description":"reCAPTCHA on sign-up. The secret is only returned to admins.","properties":{"enabled":{"type":"boolean"},"recaptcha":{"properties":{"secret":{"type":"string"}},"type":"object"}},"type":"object"},"public_sign_up":{"description":"Anyone can create an account.","type":"boolean"},"public_sign_up_member_owner":{"description":"Owner (admin or domain admin) of the project new members join.","type":"string"},"public_sign_up_member_role":{"description":"Role id given to the new members.","type":"string"},"public_sign_up_project":{"properties":{"limit_bucket_access":{"type":"boolean"}},"type":"object"},"public_sign_up_role":{"description":"Role of the new accounts: user or member.","type":"string"},"require_2fa":{"description":"Require a second factor.","type":"boolean"}},"type":"object"},"bright_logo":{"description":"Menu logo. data:image/png;base64,\u2026 or data:image/webp;base64,\u2026 to replace the image (stored under /brand/images/), the stored /brand/images/\u2026 URL to keep it, \"\" or null to remove it.","type":["string","null"]},"copyright":{"description":"Footer text.","type":"string"},"dark_logo":{"description":"Platform logo: login and public pages, exports. data:image/png;base64,\u2026 or data:image/webp;base64,\u2026 to replace the image (stored under /brand/images/), the stored /brand/images/\u2026 URL to keep it, \"\" or null to remove it.","type":["string","null"]},"description":{"description":"Meta description (also og:description).","type":"string"},"email":{"description":"Support address shown in the menu (mailto). Not the sender of emails: see the brand email.","type":"string"},"favicon":{"description":"Browser icon. data:image/png;base64,\u2026 or data:image/webp;base64,\u2026 to replace the image (stored under /brand/images/), the stored /brand/images/\u2026 URL to keep it, \"\" or null to remove it.","type":["string","null"]},"icon":{"description":"Menu icon when the menu is folded. data:image/png;base64,\u2026 or data:image/webp;base64,\u2026 to replace the image (stored under /brand/images/), the stored /brand/images/\u2026 URL to keep it, \"\" or null to remove it.","type":["string","null"]},"index_scripts":{"description":"Raw HTML/JS injected in the page head (analytics\u2026). Empty uses the default tag manager.","type":"string"},"keywords":{"description":"Meta keywords.","type":"string"},"login":{"description":"Login page.","properties":{"background_color":{"description":"CSS color.","type":"string"},"background_image":{"description":"Image URL.","type":"string"},"background_style":{"description":"Extra CSS as \"property:value;property:value\" (values cannot contain ':').","type":"string"},"box_class":{"description":"Position of the login box: login-center, login-left or login-right.","type":"string"},"box_style":{"description":"Inline CSS of the login box.","type":"string"}},"type":"object"},"name":{"description":"Company name, used as title prefix and logo alt text.","type":"string"},"product_types":{"description":"Options of the product type selector.","items":{"properties":{"label":{"type":"string"},"value":{"type":"string"}},"type":"object"},"type":"array"},"pwa":{"description":"Web app manifest (installable app). Served as is at /manifest.webmanifest.","properties":{"background_color":{"type":"string"},"display":{"description":"e.g. standalone.","type":"string"},"icons":{"description":"192x192 and 512x512 icons, each for purpose any and maskable.","items":{"properties":{"purpose":{"description":"any or maskable.","type":"string"},"sizes":{"description":"e.g. 192x192.","type":"string"},"src":{"description":"data:image/png;base64,\u2026 or data:image/webp;base64,\u2026 to replace the image (stored under /brand/images/), the stored /brand/images/\u2026 URL to keep it, \"\" or null to remove it.","type":["string","null"]},"type":{"description":"e.g. image/png.","type":"string"}},"type":"object"},"type":"array"},"name":{"type":"string"},"short_name":{"type":"string"},"start_url":{"type":"string"},"theme_color":{"description":"CSS color, also the browser theme color.","type":"string"}},"type":"object"},"share_image":{"description":"Image for link previews (og:image). data:image/png;base64,\u2026 or data:image/webp;base64,\u2026 to replace the image (stored under /brand/images/), the stored /brand/images/\u2026 URL to keep it, \"\" or null to remove it.","type":["string","null"]},"show_community":{"description":"Show the community links in the menu (default true).","type":"boolean"},"show_version":{"description":"Show the server version (default true).","type":"boolean"},"style":{"properties":{"topBar":{"description":"Console top bar.","properties":{"background":{"description":"CSS color.","type":"string"},"color":{"description":"CSS color of the text and icons.","type":"string"}},"type":"object"}},"type":"object"},"title":{"description":"Page title (also og:title).","type":"string"},"url":{"description":"Link of the logo on the login and public pages.","type":"string"}},"type":"object"},"description":{"type":"string"},"email":{"description":"Emails sent to accounts of this domain (verification, password\u2026). With PUT it replaces the whole stored email config; PATCH merges it. Read it with GET /v1/brands/{brand}/email and try a template with POST /v1/brands/{brand}/email/test.","properties":{"custom":{"description":"true: send with `settings` instead of the server mail settings.","type":"boolean"},"settings":{"properties":{"from":{"description":"Sender address.","type":"string"},"from_name":{"description":"Sender name.","type":"string"},"ses":{"properties":{"aws_access_key_id":{"type":"string"},"aws_region":{"description":"e.g. eu-west-1.","type":"string"},"aws_secret_access_key":{"type":"string"}},"type":"object"},"smtp":{"properties":{"host":{"type":"string"},"password":{"type":"string"},"port":{"description":"As a string, e.g. \"587\" (numbers are ignored by the server).","pattern":"^[0-9]{1,5}$","type":["string","integer"]},"secure":{"description":"true: implicit TLS (usually port 465); false: the server must offer STARTTLS (usually 587).","type":"boolean"},"username":{"type":"string"}},"type":"object"},"type":{"description":"smtp or ses.","type":"string"}},"type":"object"},"templates":{"description":"Per template: email_verification, forgot_password, create_password, device_disabled. Missing fields use the defaults. Subject and body may use {{code}} (the token for the link), {{user}}, {{email}}, {{host}}, {{admin}}, {{host_url}} and, in device_disabled, {{device}}. Links: {{host_url}}/verify_email?code={{code}}, {{host_url}}/password?code={{code}} (forgot_password), {{host_url}}/create_password?code={{code}}. {{name}}, {{url}}, {{logo}} and {{description}} only exist in the built-in defaults: in a custom template write the brand name and the logo URL (e.g. https://<brand>/brand/images/dark_logo.png) directly. The 'enabled' flag is not enforced yet.","properties":{"create_password":{"properties":{"body":{"description":"HTML.","type":"string"},"enabled":{"description":"The built-in defaults carry it as a string.","type":["boolean","string"]},"from":{"type":"string"},"from_name":{"type":"string"},"subject":{"type":"string"}},"type":"object"},"device_disabled":{"properties":{"body":{"description":"HTML.","type":"string"},"enabled":{"description":"The built-in defaults carry it as a string.","type":["boolean","string"]},"from":{"type":"string"},"from_name":{"type":"string"},"subject":{"type":"string"}},"type":"object"},"email_verification":{"properties":{"body":{"description":"HTML.","type":"string"},"enabled":{"description":"The built-in defaults carry it as a string.","type":["boolean","string"]},"from":{"type":"string"},"from_name":{"type":"string"},"subject":{"type":"string"}},"type":"object"},"forgot_password":{"properties":{"body":{"description":"HTML.","type":"string"},"enabled":{"description":"The built-in defaults carry it as a string.","type":["boolean","string"]},"from":{"type":"string"},"from_name":{"type":"string"},"subject":{"type":"string"}},"type":"object"}},"type":"object"}},"type":"object"},"enabled":{"type":"boolean"},"name":{"type":"string"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateBrand","tags":["Brands"]}},"/v1/brands/{brand}/email":{"parameters":[{"in":"path","name":"brand","required":true,"schema":{"pattern":"^(?:[a-zA-Z0-9_-]+\\.*[a-zA-Z0-9][a-zA-Z0-9_-]+(?:\\.[a-zA-Z]{2,11})?)","type":"string"}}]},"/v1/brands/{brand}/email/test":{"parameters":[{"in":"path","name":"brand","required":true,"schema":{"pattern":"^(?:[a-zA-Z0-9_-]+\\.*[a-zA-Z0-9][a-zA-Z0-9_-]+(?:\\.[a-zA-Z]{2,11})?)","type":"string"}}],"post":{"operationId":"Brand_TestEmail","requestBody":{"content":{"application/json":{"examples":{"Password reset email":{"description":"Sent to the calling admin's email address with the saved brand settings.","value":{"template":"forgot_password"}}},"schema":{"additionalProperties":false,"properties":{"template":{"$ref":"#/components/schemas/resource_id"}},"required":["template"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"TestBrandEmail","tags":["Brands"]}},"/v1/claims":{"post":{"operationId":"Claim_Request","requestBody":{"content":{"application/json":{"examples":{"Claim into a project":{"description":"Called by the account that claims; the project must be one shared with it by the claim owner.","value":{"code":"a1B2c3D4e5","project":"my_greenhouse"}}},"schema":{"additionalProperties":false,"properties":{"code":{"$ref":"#/components/schemas/resource_id"},"project":{"$ref":"#/components/schemas/resource_id"}},"required":["code","project"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"RequestClaim","tags":["Claims"]}},"/v1/claims/{code}":{"get":{"operationId":"Claim_Read","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadClaim","tags":["Claims"]},"parameters":[{"in":"path","name":"code","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v1/domains":{"get":{"operationId":"Domain_List","responses":{"200":{"content":{"application/json":{"example":[{"created":1791741478037,"description":"Console and API for Example customers","domain":"iot.example.com","modified":1791741478037}],"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListDomains","tags":["Domains"]},"post":{"operationId":"Domain_Create","requestBody":{"content":{"application/json":{"examples":{"Custom domain":{"value":{"description":"Console and API for Example customers","domain":"iot.example.com"}}},"schema":{"additionalProperties":false,"properties":{"description":{"type":"string"},"domain":{"description":"Hostname to serve with its own TLS certificate, e.g. iot.example.com. Before verifying, point it to this server (A/AAAA record to its IP, or CNAME to its hostname) and make sure port 80 is reachable from the internet: POST /v1/domains/{domain}/verify gets a Let's Encrypt certificate through an HTTP-01 challenge (a *.wildcard needs the DNS-01 challenge, only on Thinger-hosted servers). Certificates renew automatically while the DNS keeps pointing here. Brand the console on it by creating a brand with the same id.","pattern":"^([a-zA-Z0-9-_]+\\.)*[a-zA-Z0-9][a-zA-Z0-9-_]+\\.[a-zA-Z]{2,11}?$","type":"string"},"name":{"type":"string"}},"required":["domain"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CreateDomain","tags":["Domains"]}},"/v1/domains/{domain}":{"delete":{"operationId":"Domain_Delete","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteDomain","tags":["Domains"]},"get":{"operationId":"Domain_ReadConfig","responses":{"200":{"content":{"application/json":{"examples":{"Custom domain":{"value":{"created":1791741478037,"description":"Console and API for Example customers","domain":"iot.example.com","modified":1791741478037}}},"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadDomainConfig","tags":["Domains"]},"parameters":[{"in":"path","name":"domain","required":true,"schema":{"pattern":"^(?:[a-zA-Z0-9_-]+\\.*[a-zA-Z0-9][a-zA-Z0-9_-]+\\.[a-zA-Z]{2,11}?)","type":"string"}}],"put":{"operationId":"Domain_Update","requestBody":{"content":{"application/json":{"examples":{"Full Update":{"value":{"description":"Console and API for Example customers","domain":"iot.example.com"}},"Update 'description'":{"value":{"description":"Console and API for Example customers"}}},"schema":{"additionalProperties":false,"properties":{"description":{"type":"string"},"name":{"type":"string"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateDomain","tags":["Domains"]}},"/v1/domains/{domain}/verify":{"parameters":[{"in":"path","name":"domain","required":true,"schema":{"pattern":"^(?:[a-zA-Z0-9_-]+\\.*[a-zA-Z0-9][a-zA-Z0-9_-]+\\.[a-zA-Z]{2,11}?)","type":"string"}}],"post":{"operationId":"Domain_Verify","requestBody":{"content":{"application/json":{"schema":{"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"VerifyDomain","tags":["Domains"]}},"/v1/endpoints/templates":{"get":{"operationId":"Endpoint_ListTemplates","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListEndpointTemplates","tags":["Endpoints"]}},"/v1/endpoints/templates/{endpoint}":{"get":{"operationId":"Endpoint_ReadTemplateConfig","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadEndpointTemplateConfig","tags":["Endpoints"]},"parameters":[{"in":"path","name":"endpoint","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v1/hosts":{"get":{"operationId":"Host_List","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListHosts","tags":["Hosts"]},"post":{"operationId":"Host_Create","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":false,"properties":{"description":{"type":"string"},"host":{"description":"Hostname of the server. Hosts register themselves when they start.","pattern":"^([a-zA-Z0-9-_]+\\.)*[a-zA-Z0-9][a-zA-Z0-9-_]+(?:\\.[a-zA-Z]{2,11})?$","type":"string"}},"required":["host"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CreateHost","tags":["Hosts"]}},"/v1/hosts/{host}":{"delete":{"operationId":"Host_Delete","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteHost","tags":["Hosts"]},"get":{"operationId":"Host_ReadConfig","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadHostConfig","tags":["Hosts"]},"parameters":[{"in":"path","name":"host","required":true,"schema":{"pattern":"^(?:[a-zA-Z0-9_-]+\\.*[a-zA-Z0-9][a-zA-Z0-9_-]+(?:\\.[a-zA-Z]{2,11})?)","type":"string"}}],"put":{"operationId":"Host_Update","requestBody":{"content":{"application/json":{"examples":{"Describe the host":{"value":{"description":"Primary server, eu-west-1"}}},"schema":{"additionalProperties":false,"properties":{"description":{"type":"string"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateHost","tags":["Hosts"]}},"/v1/hosts/{host}/logs":{"get":{"description":"Server output (stdout and stderr) of the host. A websocket upgrade streams new lines live; a plain GET returns the last lines as text/plain. Reads the logs of the Docker container the server runs in (deployment.container_name, default \"thinger\"); other cluster hosts are proxied.","operationId":"Host_ReadLogs","parameters":[{"description":"Plain GET: number of last lines (1-5000, default 200).","in":"query","name":"lines","schema":{"default":200,"maximum":5000,"minimum":1,"type":"integer"}},{"description":"Plain GET: prefix each line with its timestamp.","in":"query","name":"timestamps","schema":{"type":"boolean"}},{"description":"Plain GET: only lines after this unix timestamp, or this many seconds ago when below 31536000.","in":"query","name":"since","schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadHostLogs","tags":["Hosts"]},"parameters":[{"in":"path","name":"host","required":true,"schema":{"pattern":"^(?:[a-zA-Z0-9_-]+\\.*[a-zA-Z0-9][a-zA-Z0-9_-]+(?:\\.[a-zA-Z]{2,11})?)","type":"string"}}]},"/v1/hosts/{host}/restart":{"parameters":[{"in":"path","name":"host","required":true,"schema":{"pattern":"^(?:[a-zA-Z0-9_-]+\\.*[a-zA-Z0-9][a-zA-Z0-9_-]+(?:\\.[a-zA-Z]{2,11})?)","type":"string"}}],"post":{"operationId":"Host_UpdateStateRestart","requestBody":{"content":{"application/json":{"schema":{"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateHostState","tags":["Hosts"]}},"/v1/hosts/{host}/settings":{"get":{"operationId":"Host_ReadSettings","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadHostSettings","tags":["Hosts"]},"parameters":[{"in":"path","name":"host","required":true,"schema":{"pattern":"^(?:[a-zA-Z0-9_-]+\\.*[a-zA-Z0-9][a-zA-Z0-9_-]+(?:\\.[a-zA-Z]{2,11})?)","type":"string"}}],"put":{"operationId":"Host_UpdateSettings","requestBody":{"content":{"application/json":{"examples":{"Change the MQTT ports":{"value":{"mqtt_server":{"port":"1884","ssl_port":"8884"}}},"Enable projects, members and identity providers":{"value":{"accounts":{"limits":{"identity_providers":{"max_count":5},"projects":{"max_count":-1},"projects_members":{"max_count":-1}}}}},"Remove a custom setting (back to the provider value)":{"value":{"deployment":{"x_frame_options":null}}},"Send server emails with SMTP":{"value":{"email":{"from":"noreply@example.com","from_name":"Example IoT","smtp":{"host":"smtp.example.com","password":"app-password","port":"587","secure":false,"username":"noreply@example.com"},"type":"smtp"}}}},"schema":{"description":"Merged (RFC 7386 merge patch: null removes a key) into the host custom settings, on top of the provider settings. Changes apply after POST /v1/hosts/{host}/restart. Ports are strings: numbers are ignored by the server. On cloud instances (configured by a subscription), database, plugins, rate_limiter, http_server.hosts and accounts.limits.{accounts,brands,domains,members} belong to the plan: sending them returns 403, and stored ones are ignored.","properties":{"accounts":{"description":"Accounts and limits. Brands can override the sign-up and login keys per domain.","properties":{"admin_emails":{"description":"Email addresses whose accounts become admins."},"allow_password":{"type":["boolean","null"]},"allow_passwordless":{"type":["boolean","null"]},"federated_login":{"type":["boolean","null"]},"identity_providers":{"description":"Identity provider ids offered on login; empty offers every enabled one."},"invalid_email_domains":{"description":"Email domains rejected on sign-up."},"invalid_usernames":{"description":"Usernames that cannot be registered."},"limits":{"description":"Per collection: {\"<collection>\": {\"max_count\": n}} with -1 = unlimited and 0 = disabled. Collections: access_tokens, buckets, dashboards, devices, endpoints, plugins, projects, projects_members, storages, alarms_rules, alarms_instances, syncs, types, groups, products, proxies, oauth_clients, identity_providers (default 0: set it to enable them). Also buckets.retention {period, unit} and buckets / endpoints min_interval. Accounts can override them with their own limits.","type":["object","null"]},"max_password_length":{"description":"Default 48.","type":["integer","string","null"]},"min_password_length":{"description":"Default 8.","type":["integer","string","null"]},"public_sign_up":{"type":["boolean","null"]},"public_sign_up_role":{"description":"user or member.","type":["string","null"]},"require_2fa":{"type":["boolean","null"]},"require_email_verification":{"type":["boolean","null"]},"required_email_domains":{"description":"Only these email domains can sign up."}},"type":["object","null"]},"buckets":{"properties":{"export":{"description":"Where bucket exports are written: type filesystem ({filesystem: {export_path}}) or s3 ({s3: {bucket_id, aws_access_key_id, aws_secret_access_key, aws_region}}).","properties":{"type":{"description":"filesystem or s3.","type":["string","null"]}},"type":["object","null"]},"storage":{"description":"Where bucket data is stored: default is mongodb, influxdb or dynamodb, each with its own connection settings (mongodb {connection_string, max_retention, default_retention}, influxdb {host, port, username, password}, dynamodb {table_name, aws_access_key_id, aws_secret_access_key, aws_region}).","properties":{"default":{"description":"mongodb, influxdb or dynamodb.","type":["string","null"]}},"type":["object","null"]}},"type":["object","null"]},"deployment":{"properties":{"contact_email":{"description":"The account registered with this email becomes admin; also {{admin}} in email templates.","type":["string","null"]},"content_security_policy":{"type":["string","null"]},"disable_swagger":{"type":["boolean","null"]},"x_frame_options":{"description":"Default SAMEORIGIN.","type":["string","null"]}},"type":["object","null"]},"email":{"description":"Server mail settings, used when a brand has no custom email.","properties":{"from":{"description":"Sender address.","type":["string","null"]},"from_name":{"type":["string","null"]},"ses":{"properties":{"aws_access_key_id":{"type":["string","null"]},"aws_region":{"type":["string","null"]},"aws_secret_access_key":{"type":["string","null"]}},"type":["object","null"]},"smtp":{"properties":{"host":{"type":["string","null"]},"password":{"type":["string","null"]},"port":{"description":"As a string, e.g. \"587\".","pattern":"^[0-9]{1,5}$","type":["string","integer","null"]},"secure":{"description":"true: implicit TLS (465); false: STARTTLS (587).","type":["boolean","null"]},"username":{"type":["string","null"]}},"type":["object","null"]},"type":{"description":"smtp or ses.","type":["string","null"]}},"type":["object","null"]},"http_server":{"description":"HTTP API and console.","properties":{"address":{"description":"Listening address, e.g. 0.0.0.0.","type":["string","null"]},"enabled":{"type":["boolean","null"]},"port":{"description":"e.g. \"80\".","pattern":"^[0-9]{1,5}$","type":["string","integer","null"]},"ssl_port":{"description":"e.g. \"443\".","pattern":"^[0-9]{1,5}$","type":["string","integer","null"]}},"type":["object","null"]},"mqtt_server":{"description":"MQTT broker for devices.","properties":{"address":{"type":["string","null"]},"enabled":{"type":["boolean","null"]},"port":{"description":"e.g. \"1883\".","pattern":"^[0-9]{1,5}$","type":["string","integer","null"]},"ssl_port":{"description":"e.g. \"8883\".","pattern":"^[0-9]{1,5}$","type":["string","integer","null"]}},"type":["object","null"]},"proxies":{"properties":{"dynamic_port_range_end":{"description":"Last one (default 51000).","type":["integer","null"]},"dynamic_port_range_start":{"description":"First port given to proxies without a fixed port (default 50000).","type":["integer","null"]}},"type":["object","null"]},"scripting_engine":{"description":"{\"nodejs\": {\"enabled\": true}}: JavaScript for product scripts.","type":["object","null"]},"ssl":{"properties":{"client_ca_certs":{"description":"PEM certificates to accept as client certificates.","type":["string","null"]},"ssl_ciphers":{"description":"OpenSSL cipher list.","type":["string","null"]},"ssl_enable_legacy_protocols":{"type":["boolean","null"]},"ssl_prefer_server_ciphers":{"type":["boolean","null"]}},"type":["object","null"]},"thing_server":{"description":"IOTMP server for devices.","properties":{"address":{"type":["string","null"]},"enabled":{"type":["boolean","null"]},"port":{"description":"e.g. \"25200\".","pattern":"^[0-9]{1,5}$","type":["string","integer","null"]},"port_v2":{"description":"IOTMP v2, default \"25204\".","pattern":"^[0-9]{1,5}$","type":["string","integer","null"]},"ssl_port":{"description":"e.g. \"25202\".","pattern":"^[0-9]{1,5}$","type":["string","integer","null"]},"ssl_port_v2":{"description":"IOTMP v2 over TLS, default \"25206\".","pattern":"^[0-9]{1,5}$","type":["string","integer","null"]}},"type":["object","null"]}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateHostSettings","tags":["Hosts"]}},"/v1/identity_providers":{"get":{"operationId":"IdentityProvider_List","responses":{"200":{"content":{"application/json":{"example":[{"created":1791741478041,"enabled":true,"identity_provider":"google","modified":1791741478041,"name":"Google","type":"oidc"},{"created":1791741478041,"enabled":true,"identity_provider":"entra","modified":1791741478041,"name":"Microsoft","type":"oidc"}],"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListIdentityProviders","tags":["IdentityProviders"]},"post":{"operationId":"IdentityProvider_Create","requestBody":{"content":{"application/json":{"examples":{"Google, existing accounts only":{"value":{"client_id":"<client-id>.apps.googleusercontent.com","client_secret":"<client-secret>","display":{"button_text":"Sign in with Google"},"domain":"accounts.google.com","enabled":true,"identity_provider":"google","name":"Google","provisioning":{"email_trust_mode":"verify_with_claim","mode":"match_only"},"type":"oidc"}},"Microsoft Entra ID":{"value":{"client_id":"<application-id>","client_secret":"<client-secret>","display":{"button_text":"Sign in with Microsoft"},"domain":"login.microsoftonline.com/<tenant-id>/v2.0","enabled":true,"identity_provider":"entra","name":"Microsoft","provisioning":{"allowed_domains":["example.com"],"email_trust_mode":"trust_idp","mode":"auto_provision"},"scopes":["openid","profile","email"],"type":"oidc"}}},"schema":{"additionalProperties":false,"description":"OpenID Connect provider for the console login. Disabled by default: set accounts.limits.identity_providers.max_count in the host settings (and restart). Register https://<brand domain>/oauth/callback as redirect URI in the provider, check it with POST /v1/identity_providers/{id}/test, and offer it on a domain with the brand config accounts.federated_login / accounts.identity_providers.","properties":{"attribute_mapping":{"properties":{"company":{"default":"organization","description":"Claim to use for company - not a standard OIDC claim","type":"string"},"email":{"default":"email","type":"string"},"location":{"default":"locale","description":"Claim to use for location","type":"string"},"name":{"default":"name","type":"string"},"picture":{"default":"picture","type":"string"},"username":{"default":"preferred_username","description":"Claim to use for username","type":"string"},"website":{"default":"website","description":"Claim to use for profile URL","type":"string"}},"type":"object"},"client_id":{"description":"OAuth2 client ID registered with the IdP","type":"string"},"client_secret":{"description":"OAuth2 client secret","type":"string"},"description":{"description":"Optional description","type":"string"},"display":{"properties":{"button_text":{"type":"string"},"logo":{"description":"Logo as base64 data URL","type":"string"}},"type":"object"},"domain":{"description":"Identity provider domain, e.g. your-tenant.us.auth0.com","type":"string"},"enabled":{"default":true,"type":"boolean"},"identity_provider":{"description":"Unique identifier for the identity provider","pattern":"^[a-zA-Z0-9-_]{1,32}$","type":"string"},"name":{"description":"Display name for the identity provider","type":"string"},"provisioning":{"properties":{"allowed_domains":{"description":"Allowed email domains. Leave empty to allow all.","items":{"type":"string"},"type":"array"},"email_trust_mode":{"default":"verify_with_claim","description":"Email verification mode","enum":["trust_idp","verify_with_claim","always_verify"],"type":"string"},"mode":{"default":"auto_provision","description":"User provisioning mode","enum":["auto_provision","match_only"],"type":"string"}},"type":"object"},"scopes":{"default":["openid","profile","email"],"description":"OAuth2 scopes to request","items":{"type":"string"},"type":"array"},"token_endpoint_auth_method":{"default":"client_secret_post","description":"Token endpoint authentication method","enum":["client_secret_post","client_secret_basic","none"],"type":"string"},"type":{"description":"Identity provider type - currently only OIDC supported","enum":["oidc"],"type":"string"}},"required":["identity_provider","name","type","domain","client_id","client_secret"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CreateIdentityProvider","tags":["IdentityProviders"]}},"/v1/identity_providers/{identity_provider}":{"delete":{"operationId":"IdentityProvider_Delete","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteIdentityProvider","tags":["IdentityProviders"]},"get":{"operationId":"IdentityProvider_ReadConfig","responses":{"200":{"content":{"application/json":{"examples":{"Google, existing accounts only":{"value":{"client_id":"<client-id>.apps.googleusercontent.com","client_secret":"<client-secret>","created":1791741478041,"display":{"button_text":"Sign in with Google"},"domain":"accounts.google.com","enabled":true,"identity_provider":"google","modified":1791741478041,"name":"Google","provisioning":{"email_trust_mode":"verify_with_claim","mode":"match_only"},"type":"oidc"}},"Microsoft Entra ID":{"value":{"client_id":"<application-id>","client_secret":"<client-secret>","created":1791741478041,"display":{"button_text":"Sign in with Microsoft"},"domain":"login.microsoftonline.com/<tenant-id>/v2.0","enabled":true,"identity_provider":"entra","modified":1791741478041,"name":"Microsoft","provisioning":{"allowed_domains":["example.com"],"email_trust_mode":"trust_idp","mode":"auto_provision"},"scopes":["openid","profile","email"],"type":"oidc"}}},"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadIdentityProviderConfig","tags":["IdentityProviders"]},"parameters":[{"in":"path","name":"identity_provider","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"operationId":"IdentityProvider_Update","requestBody":{"content":{"application/json":{"examples":{"Full Update":{"value":{"client_id":"<client-id>.apps.googleusercontent.com","client_secret":"<client-secret>","display":{"button_text":"Sign in with Google"},"domain":"accounts.google.com","enabled":true,"identity_provider":"google","name":"Google","provisioning":{"email_trust_mode":"verify_with_claim","mode":"match_only"},"type":"oidc"}},"Update 'client_id'":{"value":{"client_id":"<client-id>.apps.googleusercontent.com"}},"Update 'client_secret'":{"value":{"client_secret":"<client-secret>"}},"Update 'display'":{"value":{"display":{"button_text":"Sign in with Google"}}},"Update 'domain'":{"value":{"domain":"accounts.google.com"}},"Update 'enabled'":{"value":{"enabled":true}},"Update 'name'":{"value":{"name":"Google"}},"Update 'provisioning'":{"value":{"provisioning":{"email_trust_mode":"verify_with_claim","mode":"match_only"}}},"Update 'type'":{"value":{"type":"oidc"}}},"schema":{"additionalProperties":false,"properties":{"attribute_mapping":{"properties":{"company":{"type":"string"},"email":{"type":"string"},"location":{"type":"string"},"name":{"type":"string"},"picture":{"type":"string"},"username":{"type":"string"},"website":{"type":"string"}},"type":"object"},"client_id":{"type":"string"},"client_secret":{"type":"string"},"description":{"type":"string"},"display":{"properties":{"button_text":{"type":"string"},"logo":{"type":"string"}},"type":"object"},"domain":{"type":"string"},"enabled":{"type":"boolean"},"name":{"type":"string"},"provisioning":{"properties":{"allowed_domains":{"items":{"type":"string"},"type":"array"},"email_trust_mode":{"enum":["trust_idp","verify_with_claim","always_verify"],"type":"string"},"mode":{"enum":["auto_provision","match_only"],"type":"string"}},"type":"object"},"scopes":{"items":{"type":"string"},"type":"array"},"token_endpoint_auth_method":{"enum":["client_secret_post","client_secret_basic","none"],"type":"string"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateIdentityProvider","tags":["IdentityProviders"]}},"/v1/identity_providers/{identity_provider}/test":{"parameters":[{"in":"path","name":"identity_provider","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v1/oauth/providers/{identity_provider}":{"parameters":[{"in":"path","name":"identity_provider","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v1/oauth_clients":{"get":{"operationId":"OauthClient_List","responses":{"200":{"content":{"application/json":{"example":[{"created":1791741478040,"description":"Mobile and web app of Example","enabled":true,"modified":1791741478040,"name":"Example App","oauth_client":"example_app"}],"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListOauthClients","tags":["OauthClients"]},"post":{"operationId":"OauthClient_Create","requestBody":{"content":{"application/json":{"examples":{"Web application":{"value":{"description":"Mobile and web app of Example","enabled":true,"name":"Example App","oauth_client":"example_app","prompt":"Example App wants to read your devices","redirect_uri":"https://app.example.com/oauth/callback\nhttp://localhost:4200/oauth/callback","scope":{"Device":{"*":["ListDevices","ReadDevice"]}},"secret":"change-this-long-random-secret"}}},"schema":{"additionalProperties":false,"properties":{"description":{"type":"string"},"enabled":{"description":"Disabled clients cannot authorize nor get tokens.","type":"boolean"},"name":{"description":"Application name shown on the consent screen.","type":"string"},"oauth_client":{"description":"Client id used by the application in the OAuth2 flows (authorization code, device flow).","pattern":"^[a-zA-Z0-9-_]{1,32}$","type":"string"},"picture":{"description":"Logo shown on the consent screen, as a data URL.","type":"string"},"prompt":{"description":"Text of the consent screen.","type":"string"},"redirect_uri":{"description":"Allowed redirect URIs, one per line (newline separated). The redirect_uri of each request must match one of them exactly (case-insensitive).","type":"string"},"scope":{"description":"Permissions requested for the application, as a permission tree ({\"Device\": {\"*\": [\"ReadDevice\"]}}). Informational: the token scope comes from the authorize request.","type":"object"},"secret":{"description":"Client secret. Stored as is and returned to admins.","type":"string"}},"required":["oauth_client","name","secret","redirect_uri"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CreateOauthClient","tags":["OauthClients"]}},"/v1/oauth_clients/{oauth_client}":{"delete":{"operationId":"OauthClient_Delete","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteOauthClient","tags":["OauthClients"]},"get":{"operationId":"OauthClient_ReadConfig","responses":{"200":{"content":{"application/json":{"examples":{"Web application":{"value":{"created":1791741478040,"description":"Mobile and web app of Example","enabled":true,"modified":1791741478040,"name":"Example App","oauth_client":"example_app","prompt":"Example App wants to read your devices","redirect_uri":"https://app.example.com/oauth/callback\nhttp://localhost:4200/oauth/callback","scope":{"Device":{"*":["ListDevices","ReadDevice"]}},"secret":"change-this-long-random-secret"}}},"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadOauthClientConfig","tags":["OauthClients"]},"parameters":[{"in":"path","name":"oauth_client","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"operationId":"OauthClient_Update","requestBody":{"content":{"application/json":{"examples":{"Full Update":{"value":{"description":"Mobile and web app of Example","enabled":true,"name":"Example App","oauth_client":"example_app","prompt":"Example App wants to read your devices","redirect_uri":"https://app.example.com/oauth/callback\nhttp://localhost:4200/oauth/callback","scope":{"Device":{"*":["ListDevices","ReadDevice"]}},"secret":"change-this-long-random-secret"}},"Update 'description'":{"value":{"description":"Mobile and web app of Example"}},"Update 'enabled'":{"value":{"enabled":true}},"Update 'name'":{"value":{"name":"Example App"}},"Update 'prompt'":{"value":{"prompt":"Example App wants to read your devices"}},"Update 'redirect_uri'":{"value":{"redirect_uri":"https://app.example.com/oauth/callback\nhttp://localhost:4200/oauth/callback"}},"Update 'scope'":{"value":{"scope":{"Device":{"*":["ListDevices","ReadDevice"]}}}},"Update 'secret'":{"value":{"secret":"change-this-long-random-secret"}}},"schema":{"additionalProperties":false,"properties":{"description":{"type":"string"},"enabled":{"type":"boolean"},"name":{"type":"string"},"picture":{"type":"string"},"prompt":{"type":"string"},"redirect_uri":{"type":"string"},"scope":{"type":"object"},"secret":{"type":"string"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateOauthClient","tags":["OauthClients"]}},"/v1/oauth_clients/{oauth_client}/info":{"parameters":[{"in":"path","name":"oauth_client","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v1/proxies":{"get":{"operationId":"Proxy_ListProxies","responses":{"200":{"content":{"application/json":{"example":[{"created":1791741478102,"description":"Served at https://grafana.<server hostname>: the proxy id is the subdomain, and it needs a wildcard certificate","enabled":true,"modified":1791741478102,"name":"Grafana","proxy":"grafana"},{"created":1791741478102,"description":"TCP Proxy Description","enabled":true,"modified":1791741478102,"name":"TCP Proxy Name","proxy":"tcp_proxy_id"},{"created":1791741478102,"description":"TCP Proxy Description","enabled":true,"modified":1791741478102,"name":"TCP Proxy Name","proxy":"tcp_proxy_id"},{"created":1791741478102,"description":"UDP Proxy Description","enabled":true,"modified":1791741478102,"name":"UDP Proxy Name","proxy":"udp_proxy_id"},{"created":1791741478102,"description":"UDP Proxy Description","enabled":true,"modified":1791741478102,"name":"UDP Proxy Name","proxy":"udp_proxy_id"}],"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListProxies","tags":["Proxies"]},"post":{"operationId":"Proxy_Create","requestBody":{"content":{"application/json":{"examples":{"HTTPS Subdomain to Plugin":{"value":{"config":{"protocol":"tcp","source":{"routing":"subdomain","secure":true},"target":{"plugin":{"name":"grafana","user":"user_id"},"port":3000,"secure":false,"type":"plugin"}},"description":"Served at https://grafana.<server hostname>: the proxy id is the subdomain, and it needs a wildcard certificate","enabled":true,"name":"Grafana","proxy":"grafana"}},"TCP Proxy to Host":{"value":{"config":{"protocol":"tcp","source":{"port":8090,"secure":true},"target":{"address":"localhost","port":8086,"secure":false,"type":"address"}},"description":"TCP Proxy Description","enabled":true,"name":"TCP Proxy Name","proxy":"tcp_proxy_id"}},"TCP Proxy to Plugin":{"value":{"config":{"protocol":"tcp","source":{"port":8090,"secure":true},"target":{"plugin":{"name":"plugin_id","user":"user_id"},"port":8086,"secure":false,"type":"plugin"}},"description":"TCP Proxy Description","enabled":true,"name":"TCP Proxy Name","proxy":"tcp_proxy_id"}},"UDP Proxy to Host":{"value":{"config":{"protocol":"udp","source":{"port":9000},"target":{"address":"localhost","port":9000,"type":"address"}},"description":"UDP Proxy Description","enabled":true,"name":"UDP Proxy Name","proxy":"udp_proxy_id"}},"UDP Proxy to Plugin":{"value":{"config":{"protocol":"udp","source":{"port":9000},"target":{"plugin":{"name":"plugin_id","user":"user_id"},"port":9000,"type":"plugin"}},"description":"UDP Proxy Description","enabled":true,"name":"UDP Proxy Name","proxy":"udp_proxy_id"}}},"schema":{"additionalProperties":false,"properties":{"config":{"description":"protocol: tcp, udp, tcp_iotmp or http_iotmp. source: {port (number), secure (TLS), routing: port | subdomain (the proxy id becomes the subdomain of the server hostname), allowed_ips (IOTMP)}. target: {type: address | plugin, address, plugin: {user, name}, port (number), secure, timeout (seconds, default 10)}; IOTMP protocols also take target.user and target.device. options.timeout_minutes expires sessions. port_management (default true) opens ports on Thinger-hosted servers. Creating or updating starts the listener right away; an update with a partial config replaces the stored config.","type":"object"},"description":{"type":"string"},"enabled":{"type":"boolean"},"name":{"type":"string"},"proxy":{"pattern":"^[a-zA-Z0-9-_]{1,32}$","type":"string"}},"required":["proxy","name","config"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CreateProxy","tags":["Proxies"]}},"/v1/proxies/{proxy}":{"delete":{"operationId":"Proxy_Delete","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteProxy","tags":["Proxies"]},"get":{"operationId":"Proxy_ReadConfig","responses":{"200":{"content":{"application/json":{"examples":{"HTTPS Subdomain to Plugin":{"value":{"config":{"protocol":"tcp","source":{"routing":"subdomain","secure":true},"target":{"plugin":{"name":"grafana","user":"user_id"},"port":3000,"secure":false,"type":"plugin"}},"created":1791741478102,"description":"Served at https://grafana.<server hostname>: the proxy id is the subdomain, and it needs a wildcard certificate","enabled":true,"modified":1791741478102,"name":"Grafana","proxy":"grafana"}},"TCP Proxy to Host":{"value":{"config":{"protocol":"tcp","source":{"port":8090,"secure":true},"target":{"address":"localhost","port":8086,"secure":false,"type":"address"}},"created":1791741478102,"description":"TCP Proxy Description","enabled":true,"modified":1791741478102,"name":"TCP Proxy Name","proxy":"tcp_proxy_id"}},"TCP Proxy to Plugin":{"value":{"config":{"protocol":"tcp","source":{"port":8090,"secure":true},"target":{"plugin":{"name":"plugin_id","user":"user_id"},"port":8086,"secure":false,"type":"plugin"}},"created":1791741478102,"description":"TCP Proxy Description","enabled":true,"modified":1791741478102,"name":"TCP Proxy Name","proxy":"tcp_proxy_id"}},"UDP Proxy to Host":{"value":{"config":{"protocol":"udp","source":{"port":9000},"target":{"address":"localhost","port":9000,"type":"address"}},"created":1791741478102,"description":"UDP Proxy Description","enabled":true,"modified":1791741478102,"name":"UDP Proxy Name","proxy":"udp_proxy_id"}},"UDP Proxy to Plugin":{"value":{"config":{"protocol":"udp","source":{"port":9000},"target":{"plugin":{"name":"plugin_id","user":"user_id"},"port":9000,"type":"plugin"}},"created":1791741478102,"description":"UDP Proxy Description","enabled":true,"modified":1791741478102,"name":"UDP Proxy Name","proxy":"udp_proxy_id"}}},"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadProxyConfig","tags":["Proxies"]},"parameters":[{"in":"path","name":"proxy","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"operationId":"Proxy_Update","requestBody":{"content":{"application/json":{"examples":{"Full Update":{"value":{"config":{"protocol":"tcp","source":{"routing":"subdomain","secure":true},"target":{"plugin":{"name":"grafana","user":"user_id"},"port":3000,"secure":false,"type":"plugin"}},"description":"Served at https://grafana.<server hostname>: the proxy id is the subdomain, and it needs a wildcard certificate","enabled":true,"name":"Grafana","proxy":"grafana"}},"Update 'config'":{"value":{"config":{"protocol":"tcp","source":{"routing":"subdomain","secure":true},"target":{"plugin":{"name":"grafana","user":"user_id"},"port":3000,"secure":false,"type":"plugin"}}}},"Update 'description'":{"value":{"description":"Served at https://grafana.<server hostname>: the proxy id is the subdomain, and it needs a wildcard certificate"}},"Update 'enabled'":{"value":{"enabled":true}},"Update 'name'":{"value":{"name":"Grafana"}}},"schema":{"additionalProperties":false,"properties":{"config":{"type":"object"},"description":{"type":"string"},"enabled":{"type":"boolean"},"name":{"type":"string"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateProxy","tags":["Proxies"]}},"/v1/server/actions":{"get":{"operationId":"Server_ReadActions","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadServerActions","tags":["Server"]}},"/v1/server/assets":{"get":{"operationId":"Server_ReadAssets","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"}},"summary":"ReadServerAssets","tags":["Server"]}},"/v1/server/buckets/backends":{"get":{"operationId":"Server_ReadBucketsBackends","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"}},"summary":"ReadServerBucketsBackends","tags":["Server"]}},"/v1/server/events":{"get":{"operationId":"Server_ReadEvents","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"}},"summary":"ReadServerEvents","tags":["Server"]}},"/v1/server/healthcheck":{"get":{"operationId":"Server_ReadHealthcheck","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"}},"summary":"ReadServerHealthcheck","tags":["Server"]}},"/v1/server/settings":{"get":{"operationId":"Server_ReadSettings","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadServerSettings","tags":["Server"]}},"/v1/server/statistics":{"get":{"operationId":"Server_ReadStatistics","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadServerStatistics","tags":["Server"]}},"/v1/server/swagger.json":{"get":{"operationId":"Server_ReadApiSwagger.json","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"}},"summary":"ReadServerApi","tags":["Server"]}},"/v1/server/version":{"get":{"operationId":"Server_ReadVersion","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadServerVersion","tags":["Server"]}},"/v1/users":{"get":{"operationId":"User_List","responses":{"200":{"content":{"application/json":{"example":[{"created":1791741478035,"email":"jdoe@example.com","enabled":true,"modified":1791741478035,"role":"user","user":"jdoe","verified":true},{"created":1791741478035,"email":"operator1@example.com","enabled":true,"modified":1791741478035,"role":"member","user":"operator1","verified":true},{"created":1791741478035,"email":"jdoe@example.com","enabled":true,"modified":1791741478035,"role":"user","user":"jdoe","verified":true}],"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListUsers","tags":["Users"]},"post":{"operationId":"User_Create","requestBody":{"content":{"application/json":{"examples":{"Account that sets its own password":{"value":{"email":"jdoe@example.com","enabled":true,"password":"","role":"user","user":"jdoe","verified":true}},"Member of a project":{"value":{"email":"operator1@example.com","enabled":true,"options":{"project":{"default":"plant_madrid"}},"password":"a-strong-password","role":"member","user":"operator1","verified":true}},"Regular account":{"value":{"email":"jdoe@example.com","enabled":true,"password":"a-strong-password","role":"user","user":"jdoe","verified":true}}},"schema":{"additionalProperties":false,"properties":{"email":{"format":"email","type":"string"},"enabled":{"type":"boolean"},"options":{"additionalProperties":false,"properties":{"project":{"additionalProperties":false,"properties":{"default":{"$ref":"#/components/schemas/resource_id"}},"type":"object"}},"type":"object"},"password":{"description":"Empty, when an admin creates the account: the user receives an email to set it.","maxLength":72,"type":"string"},"recaptcha":{"type":"string"},"role":{"description":"user: a regular account. admin: server administrator (only admins create admins and domain admins). domain_admin: administers the accounts of its hosts. member: only works inside the projects it is invited to (needs options.project.default).","enum":["user","admin","member","domain_admin"],"type":"string"},"user":{"$ref":"#/components/schemas/resource_id"},"verified":{"description":"Email already verified (admins can skip the verification email).","type":"boolean"}},"required":["user","email","password"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CreateUser","tags":["Users"]}},"/v1/users/email/verify":{"post":{"operationId":"User_VerifyEmail","requestBody":{"content":{"application/json":{"schema":{"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"}},"summary":"VerifyUserEmail","tags":["Users"]}},"/v1/users/{user}":{"delete":{"operationId":"User_Delete","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteUser","tags":["Users"]},"get":{"operationId":"User_ReadConfig","responses":{"200":{"content":{"application/json":{"examples":{"Account that sets its own password":{"value":{"created":1791741478035,"email":"jdoe@example.com","enabled":true,"modified":1791741478035,"password":"","role":"user","user":"jdoe","verified":true}},"Member of a project":{"value":{"created":1791741478035,"email":"operator1@example.com","enabled":true,"modified":1791741478035,"options":{"project":{"default":"plant_madrid"}},"password":"a-strong-password","role":"member","user":"operator1","verified":true}},"Regular account":{"value":{"created":1791741478035,"email":"jdoe@example.com","enabled":true,"modified":1791741478035,"password":"a-strong-password","role":"user","user":"jdoe","verified":true}}},"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadUserConfig","tags":["Users"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"operationId":"User_Update","requestBody":{"content":{"application/json":{"examples":{"Disable an account":{"value":{"enabled":false}},"Make it a domain admin of a brand":{"value":{"host":["iot.example.com"],"role":"domain_admin"}},"Raise its limits":{"value":{"limits":{"buckets":{"max_count":50},"devices":{"max_count":500}}}},"Set a new password":{"value":{"password":"a-new-strong-password"}}},"schema":{"additionalProperties":false,"properties":{"email":{"type":"string"},"enabled":{"type":"boolean"},"host":{"description":"Domains the account belongs to (set on sign-up from the request host). Used for the brand emails, brand cross_sign_in and domain admins.","items":{"pattern":"^(?:[a-zA-Z0-9-_]+\\.)*[a-zA-Z0-9][a-zA-Z0-9-_]+(?:\\.[a-zA-Z]{2,11})?$","type":"string"},"maxItems":10,"type":"array"},"limits":{"description":"Per-account overrides of the server limits: {\"<collection>\": {\"max_count\": n}} (-1 = unlimited, 0 = disabled), and buckets.retention {period, unit}.","type":"object"},"options":{"additionalProperties":false,"properties":{"additionalProperties":false,"project":{"properties":{"default":{"$ref":"#/components/schemas/resource_id"}},"type":"object"}},"type":"object"},"password":{"maxLength":72,"minLength":6,"type":"string"},"role":{"enum":["user","admin","member","domain_admin"],"type":"string"},"verified":{"type":"boolean"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateUser","tags":["Users"]}},"/v1/users/{user}/account":{"get":{"operationId":"User_ReadAccount","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadUserAccount","tags":["Users"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v1/users/{user}/alarms/instances":{"get":{"operationId":"Alarm_ListInstances","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListAlarmInstances","tags":["Alarms"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Alarm_CreateInstance","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"properties":{"alarm":{"additionalProperties":false,"properties":{"rule":{"$ref":"#/components/schemas/resource_id"}},"type":"object"},"annotation":{"maxLength":512,"type":"string"},"asset_group":{"$ref":"#/components/schemas/resource_id"},"asset_type":{"$ref":"#/components/schemas/resource_id"},"description":{"$ref":"#/components/schemas/resource_description"},"evaluation":{"properties":{"last_completed":{"type":"number"},"last_values":{"type":"object"},"total_duration":{"type":"number"}},"type":"object"},"instance":{"$ref":"#/components/schemas/resource_id"},"name":{"$ref":"#/components/schemas/resource_name"},"origin":{"properties":{"id":{"$ref":"#/components/schemas/resource_id"},"name":{"$ref":"#/components/schemas/resource_name"},"source":{"enum":["device","user"],"type":"string"}},"required":["source","id","name"],"type":"object"},"reactivation":{"properties":{"timespan":{"properties":{"magnitude":{"enum":["second","minute","hour","day","week","month","year"],"type":"string"},"value":{"minimum":0,"type":"number"}},"type":"object"},"type":{"enum":["none","timespan"],"type":"string"}},"type":"object"},"severity":{"maximum":4,"minimum":0,"type":"number"},"state":{"maximum":4,"minimum":0,"type":"number"}},"required":["instance","alarm","name","state","severity","origin","evaluation"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CreateAlarmInstance","tags":["Alarms"]}},"/v1/users/{user}/alarms/instances/stats":{"get":{"operationId":"Alarm_ReadInstanceStats","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadAlarmInstanceStats","tags":["Alarms"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v1/users/{user}/alarms/instances/{instance}":{"delete":{"operationId":"Alarm_DeleteInstance","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteAlarmInstance","tags":["Alarms"]},"get":{"operationId":"Alarm_ReadInstanceConfig","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadAlarmInstanceConfig","tags":["Alarms"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"instance","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"operationId":"Alarm_UpdateInstance","requestBody":{"content":{"application/json":{"examples":{"Acknowledge":{"value":{"annotation":"Technician on the way","state":2}},"Clear":{"value":{"annotation":"Fan replaced","state":5}},"Shelve for 4 hours":{"value":{"annotation":"Planned maintenance","reactivation":{"timespan":{"magnitude":"hour","value":4},"type":"timespan"},"state":4}}},"schema":{"additionalProperties":false,"description":"Mostly used to change the state of an alarm instance: 0 none, 1 activated, 2 acknowledged, 3 latched, 4 shelved, 5 cleared (final). 'reactivation' sets when an acknowledged, shelved or latched alarm becomes active again if the condition persists.","properties":{"annotation":{"maxLength":512,"type":"string"},"description":{"$ref":"#/components/schemas/resource_description"},"name":{"$ref":"#/components/schemas/resource_name"},"reactivation":{"properties":{"timespan":{"properties":{"magnitude":{"enum":["second","minute","hour","day","week","month","year"],"type":"string"},"value":{"minimum":0,"type":"number"}},"type":"object"},"type":{"enum":["none","timespan"],"type":"string"}},"type":"object"},"state":{"maximum":6,"minimum":0,"type":"number"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateAlarmInstance","tags":["Alarms"]}},"/v1/users/{user}/alarms/instances/{instance}/projects":{"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"instance","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"operationId":"Alarm_UpdateInstanceProjects","requestBody":{"content":{"application/json":{"examples":{"No projects":{"value":[]},"One project":{"value":["alvarolb@greenhouse"]},"Two projects":{"value":["alvarolb@greenhouse","alvarolb@maintenance"]}},"schema":{"description":"Projects the resource belongs to, as <owner>@<project> ids. Replaces the whole list: read the current one first to add or remove a single project; [] removes it from every project.","items":{"pattern":"^[a-zA-Z0-9_]{1,32}@[a-zA-Z0-9_]{1,32}$","type":"string"},"type":"array"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateAlarmInstanceProjects","tags":["Alarms"]}},"/v1/users/{user}/alarms/rules":{"get":{"operationId":"Alarm_ListRules","responses":{"200":{"content":{"application/json":{"example":[{"created":1791741478114,"description":"Mean temperature above 30 for 3 checks in a row, per device","enabled":true,"modified":1791741478114,"name":"Greenhouse too hot","rule":"greenhouse_hot"},{"created":1791741478114,"description":"Any device of the smart_meter product disconnected","enabled":true,"modified":1791741478114,"name":"Meter offline","rule":"meter_offline"},{"created":1791741478114,"description":"Hourly max depth of each well above its own limit: the 'limits' property of the device, or of its asset type, asset group or product when the device has none","enabled":true,"modified":1791741478114,"name":"Water table too deep","rule":"well_too_deep"},{"created":1791741478114,"description":"Battery level reported in the 'battery' property below 15%, devices of the 'field_sensors' group","enabled":true,"modified":1791741478114,"name":"Low battery","rule":"low_battery"}],"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListAlarmRules","tags":["Alarms"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Alarm_CreateRule","requestBody":{"content":{"application/json":{"examples":{"Bucket threshold":{"value":{"config":{"activation":{"conditions":[{"comparison":"above","field":"climate.temperature","operator":"and","type":"value_check","value":"30"}],"confirmation":{"mode":"sequence","sequence":{"value":3}},"notifications":[{"id":"ops_email","type":"endpoint"}]},"check_interval":{"magnitude":"minute","value":5},"data":{"sources":[{"bucket":{"aggregation":{"period":"5m","type":"mean"},"group_by":["device"],"id":"greenhouse_climate","mapping":["temperature"]},"name":"climate","source":"bucket"}]},"normalization":{"conditions":[{"comparison":"below","field":"climate.temperature","operator":"and","type":"value_check","value":"28"}],"confirmation":{"mode":"timespan","timespan":{"magnitude":"minute","value":15}},"notifications":[{"id":"ops_email","type":"endpoint"}]},"reminder":{"interval":{"magnitude":"day","value":1},"notifications":[{"id":"ops_email","type":"endpoint"}],"type":"interval"},"severity":3},"description":"Mean temperature above 30 for 3 checks in a row, per device","enabled":true,"name":"Greenhouse too hot","rule":"greenhouse_hot"}},"Device offline":{"value":{"config":{"activation":{"conditions":[{"comparison":"equal","field":"status.connection.active","operator":"and","type":"value_check","value":"0"}],"confirmation":{"mode":"timespan","timespan":{"magnitude":"minute","value":10}},"notifications":[{"id":"support_webhook","type":"endpoint"}]},"check_interval":{"magnitude":"minute","value":1},"data":{"sources":[{"device_status":{"fields":["connection.active","connection.ts"],"product":"smart_meter"},"name":"status","source":"device_status"}]},"normalization":{"conditions":[{"comparison":"equal","field":"status.connection.active","operator":"and","type":"value_check","value":"1"}],"confirmation":{"mode":"immediate"},"notifications":[]},"reminder":{"notifications":[],"type":"none"},"severity":2},"description":"Any device of the smart_meter product disconnected","enabled":true,"name":"Meter offline","rule":"meter_offline"}},"Per-device threshold":{"value":{"config":{"activation":{"conditions":[{"comparison":"above","field":"well.depth_m","operator":"and","type":"value_check","value":"limits.value.max_depth_m"}],"confirmation":{"mode":"immediate"},"notifications":[{"id":"ops_email","type":"endpoint"}]},"check_interval":{"magnitude":"minute","value":15},"data":{"sources":[{"bucket":{"aggregation":{"period":"1h","type":"max"},"group_by":["device"],"id":"well_levels","mapping":["depth_m"]},"name":"well","source":"bucket"},{"device_property":{"fields":["value.max_depth_m"],"product":"piezometer","property":"limits"},"name":"limits","source":"device_property"}]},"normalization":{"conditions":[{"comparison":"below","field":"well.depth_m","operator":"and","type":"value_check","value":"limits.value.max_depth_m * 0.9"}],"confirmation":{"mode":"immediate"},"notifications":[]},"reminder":{"notifications":[],"type":"none"},"severity":2},"description":"Hourly max depth of each well above its own limit: the 'limits' property of the device, or of its asset type, asset group or product when the device has none","enabled":true,"name":"Water table too deep","rule":"well_too_deep"}},"Property condition":{"value":{"config":{"activation":{"conditions":[{"comparison":"below","field":"battery.value.level","operator":"and","type":"value_check","value":"15"}],"confirmation":{"mode":"immediate"},"notifications":[{"id":"ops_email","type":"endpoint"}]},"check_interval":{"magnitude":"hour","value":1},"data":{"sources":[{"device_property":{"asset_group":"field_sensors","fields":["value.level"],"property":"battery"},"name":"battery","source":"device_property"}]},"normalization":{"conditions":[{"comparison":"above","field":"battery.value.level","operator":"and","type":"value_check","value":"50"}],"confirmation":{"mode":"immediate"},"notifications":[]},"reminder":{"notifications":[],"type":"none"},"severity":1},"description":"Battery level reported in the 'battery' property below 15%, devices of the 'field_sensors' group","enabled":true,"name":"Low battery","rule":"low_battery"}}},"schema":{"additionalProperties":false,"description":"An alarm rule checks its data sources every check_interval and raises one alarm instance per device that meets the activation conditions. Sources: 'bucket' (bucket data, optionally aggregated and grouped by device), 'device_property' (a device property, resolved with type / group / product inheritance) and 'device_status' (connection.active, connection.ts). Sources can be narrowed with project, product, asset_type, asset_group or device. Conditions read '<source name>.<field>' and compare it with above, below, equal, not_equal (value), inside, outside (min, max), present or absent; a comparison on a field the device does not have is false (a bucket source with several mapping fields keeps a device that only has some of them), so 'a above 5 or b above 5' works on devices without b, and a device is skipped only when it has none of the fields the conditions read or misses a whole source (unless present / absent are used); values are strings, and can be expressions over other sources of the same device (e.g. 'limits.value.max_depth_m', a per-device threshold from a device_property source). device_property fields are paths in the property document: 'value.<field>'. Confirmation: immediate, sequence (N detections in a row) or timespan. Notifications call endpoints.","properties":{"config":{"$ref":"#/components/schemas/alarm_rule"},"description":{"$ref":"#/components/schemas/resource_description"},"enabled":{"type":"boolean"},"name":{"$ref":"#/components/schemas/resource_name"},"rule":{"$ref":"#/components/schemas/resource_id"}},"required":["rule","name","enabled"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CreateAlarmRule","tags":["Alarms"]}},"/v1/users/{user}/alarms/rules/{rule}":{"delete":{"operationId":"Alarm_DeleteRule","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteAlarmRule","tags":["Alarms"]},"get":{"operationId":"Alarm_ReadRuleConfig","responses":{"200":{"content":{"application/json":{"examples":{"Bucket threshold":{"value":{"config":{"activation":{"conditions":[{"comparison":"above","field":"climate.temperature","operator":"and","type":"value_check","value":"30"}],"confirmation":{"mode":"sequence","sequence":{"value":3}},"notifications":[{"id":"ops_email","type":"endpoint"}]},"check_interval":{"magnitude":"minute","value":5},"data":{"sources":[{"bucket":{"aggregation":{"period":"5m","type":"mean"},"group_by":["device"],"id":"greenhouse_climate","mapping":["temperature"]},"name":"climate","source":"bucket"}]},"normalization":{"conditions":[{"comparison":"below","field":"climate.temperature","operator":"and","type":"value_check","value":"28"}],"confirmation":{"mode":"timespan","timespan":{"magnitude":"minute","value":15}},"notifications":[{"id":"ops_email","type":"endpoint"}]},"reminder":{"interval":{"magnitude":"day","value":1},"notifications":[{"id":"ops_email","type":"endpoint"}],"type":"interval"},"severity":3},"created":1791741478114,"description":"Mean temperature above 30 for 3 checks in a row, per device","enabled":true,"modified":1791741478114,"name":"Greenhouse too hot","rule":"greenhouse_hot"}},"Device offline":{"value":{"config":{"activation":{"conditions":[{"comparison":"equal","field":"status.connection.active","operator":"and","type":"value_check","value":"0"}],"confirmation":{"mode":"timespan","timespan":{"magnitude":"minute","value":10}},"notifications":[{"id":"support_webhook","type":"endpoint"}]},"check_interval":{"magnitude":"minute","value":1},"data":{"sources":[{"device_status":{"fields":["connection.active","connection.ts"],"product":"smart_meter"},"name":"status","source":"device_status"}]},"normalization":{"conditions":[{"comparison":"equal","field":"status.connection.active","operator":"and","type":"value_check","value":"1"}],"confirmation":{"mode":"immediate"},"notifications":[]},"reminder":{"notifications":[],"type":"none"},"severity":2},"created":1791741478114,"description":"Any device of the smart_meter product disconnected","enabled":true,"modified":1791741478114,"name":"Meter offline","rule":"meter_offline"}},"Per-device threshold":{"value":{"config":{"activation":{"conditions":[{"comparison":"above","field":"well.depth_m","operator":"and","type":"value_check","value":"limits.value.max_depth_m"}],"confirmation":{"mode":"immediate"},"notifications":[{"id":"ops_email","type":"endpoint"}]},"check_interval":{"magnitude":"minute","value":15},"data":{"sources":[{"bucket":{"aggregation":{"period":"1h","type":"max"},"group_by":["device"],"id":"well_levels","mapping":["depth_m"]},"name":"well","source":"bucket"},{"device_property":{"fields":["value.max_depth_m"],"product":"piezometer","property":"limits"},"name":"limits","source":"device_property"}]},"normalization":{"conditions":[{"comparison":"below","field":"well.depth_m","operator":"and","type":"value_check","value":"limits.value.max_depth_m * 0.9"}],"confirmation":{"mode":"immediate"},"notifications":[]},"reminder":{"notifications":[],"type":"none"},"severity":2},"created":1791741478114,"description":"Hourly max depth of each well above its own limit: the 'limits' property of the device, or of its asset type, asset group or product when the device has none","enabled":true,"modified":1791741478114,"name":"Water table too deep","rule":"well_too_deep"}},"Property condition":{"value":{"config":{"activation":{"conditions":[{"comparison":"below","field":"battery.value.level","operator":"and","type":"value_check","value":"15"}],"confirmation":{"mode":"immediate"},"notifications":[{"id":"ops_email","type":"endpoint"}]},"check_interval":{"magnitude":"hour","value":1},"data":{"sources":[{"device_property":{"asset_group":"field_sensors","fields":["value.level"],"property":"battery"},"name":"battery","source":"device_property"}]},"normalization":{"conditions":[{"comparison":"above","field":"battery.value.level","operator":"and","type":"value_check","value":"50"}],"confirmation":{"mode":"immediate"},"notifications":[]},"reminder":{"notifications":[],"type":"none"},"severity":1},"created":1791741478114,"description":"Battery level reported in the 'battery' property below 15%, devices of the 'field_sensors' group","enabled":true,"modified":1791741478114,"name":"Low battery","rule":"low_battery"}}},"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadAlarmRuleConfig","tags":["Alarms"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"rule","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"operationId":"Alarm_UpdateRule","requestBody":{"content":{"application/json":{"examples":{"Disable the rule":{"value":{"enabled":false}},"Rename":{"value":{"description":"Zone A sensors only","name":"Greenhouse too hot - zone A"}}},"schema":{"additionalProperties":false,"description":"Fields sent replace the stored ones; config replaces the whole rule configuration (read it first to change part of it).","properties":{"config":{"$ref":"#/components/schemas/alarm_rule"},"description":{"$ref":"#/components/schemas/resource_description"},"enabled":{"type":"boolean"},"name":{"$ref":"#/components/schemas/resource_name"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateAlarmRule","tags":["Alarms"]}},"/v1/users/{user}/alarms/rules/{rule}/clone":{"get":{"operationId":"Alarm_CloneRuleConfig","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneAlarmRuleConfig","tags":["Alarms"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"rule","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Alarm_CloneRule","requestBody":{"content":{"application/json":{"examples":{"Copy with a new id":{"value":{"rule":"copy_of_rule"}},"Copy with name and description":{"value":{"description":"Same configuration as the original, for production line 2","name":"Line 2 copy","rule":"line_2_rule"}}},"schema":{"additionalProperties":false,"properties":{"description":{"$ref":"#/components/schemas/resource_description"},"enabled":{"type":"boolean"},"name":{"$ref":"#/components/schemas/resource_name"},"rule":{"$ref":"#/components/schemas/resource_id"}},"required":["rule"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneAlarmRule","tags":["Alarms"]}},"/v1/users/{user}/alarms/rules/{rule}/projects":{"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"rule","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"operationId":"Alarm_UpdateRuleProjects","requestBody":{"content":{"application/json":{"examples":{"No projects":{"value":[]},"One project":{"value":["alvarolb@greenhouse"]},"Two projects":{"value":["alvarolb@greenhouse","alvarolb@maintenance"]}},"schema":{"description":"Projects the resource belongs to, as <owner>@<project> ids. Replaces the whole list: read the current one first to add or remove a single project; [] removes it from every project.","items":{"pattern":"^[a-zA-Z0-9_]{1,32}@[a-zA-Z0-9_]{1,32}$","type":"string"},"type":"array"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateAlarmRuleProjects","tags":["Alarms"]}},"/v1/users/{user}/alarms/rules/{rule}/test-notification":{"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"rule","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Alarm_TestRuleNotificationTest-notification","requestBody":{"content":{"application/json":{"examples":{"Activation of a device":{"value":{"config":{"activation":{"notifications":[{"id":"ops_email","type":"endpoint"}]},"severity":3},"description":"Mean temperature above 30","event":{"origin":"greenhouse_01","type":"activation","values":{"climate":{"temperature":31.2}}},"name":"Greenhouse too hot"}}},"schema":{"description":"Simulates an alarm event of a device and SENDS the notifications configured for that event type (config.<type>.notifications) to their endpoints, so real emails or webhooks go out. Returns the notifications and the alarm payload they carried. Nothing is stored.","properties":{"config":{"$ref":"#/components/schemas/alarm_rule"},"description":{"type":["string","null"]},"event":{"properties":{"origin":{"description":"Device id.","type":["string","null"]},"type":{"enum":["activation","normalization","reminder"],"type":"string"},"values":{"description":"Source values that triggered the event, by source name."}},"required":["type"],"type":"object"},"name":{"type":["string","null"]}},"required":["event"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"TestRuleNotification","tags":["Alarms"]}},"/v1/users/{user}/alarms/rules/{rule}/test-rule":{"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"rule","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Alarm_TestRuleTest-rule","requestBody":{"content":{"application/json":{"examples":{"Bucket threshold":{"value":{"config":{"activation":{"conditions":[{"comparison":"above","field":"climate.temperature","operator":"and","type":"value_check","value":"30"}],"confirmation":{"mode":"sequence","sequence":{"value":3}},"notifications":[{"id":"ops_email","type":"endpoint"}]},"check_interval":{"magnitude":"minute","value":5},"data":{"sources":[{"bucket":{"aggregation":{"period":"5m","type":"mean"},"group_by":["device"],"id":"greenhouse_climate","mapping":["temperature"]},"name":"climate","source":"bucket"}]},"normalization":{"conditions":[{"comparison":"below","field":"climate.temperature","operator":"and","type":"value_check","value":"28"}],"confirmation":{"mode":"timespan","timespan":{"magnitude":"minute","value":15}},"notifications":[{"id":"ops_email","type":"endpoint"}]},"reminder":{"interval":{"magnitude":"day","value":1},"notifications":[{"id":"ops_email","type":"endpoint"}],"type":"interval"},"severity":3},"description":"Mean temperature above 30 for 3 checks in a row, per device","enabled":true,"name":"Greenhouse too hot"}},"Device offline":{"value":{"config":{"activation":{"conditions":[{"comparison":"equal","field":"status.connection.active","operator":"and","type":"value_check","value":"0"}],"confirmation":{"mode":"timespan","timespan":{"magnitude":"minute","value":10}},"notifications":[{"id":"support_webhook","type":"endpoint"}]},"check_interval":{"magnitude":"minute","value":1},"data":{"sources":[{"device_status":{"fields":["connection.active","connection.ts"],"product":"smart_meter"},"name":"status","source":"device_status"}]},"normalization":{"conditions":[{"comparison":"equal","field":"status.connection.active","operator":"and","type":"value_check","value":"1"}],"confirmation":{"mode":"immediate"},"notifications":[]},"reminder":{"notifications":[],"type":"none"},"severity":2},"description":"Any device of the smart_meter product disconnected","enabled":true,"name":"Meter offline"}},"Per-device threshold":{"value":{"config":{"activation":{"conditions":[{"comparison":"above","field":"well.depth_m","operator":"and","type":"value_check","value":"limits.value.max_depth_m"}],"confirmation":{"mode":"immediate"},"notifications":[{"id":"ops_email","type":"endpoint"}]},"check_interval":{"magnitude":"minute","value":15},"data":{"sources":[{"bucket":{"aggregation":{"period":"1h","type":"max"},"group_by":["device"],"id":"well_levels","mapping":["depth_m"]},"name":"well","source":"bucket"},{"device_property":{"fields":["value.max_depth_m"],"product":"piezometer","property":"limits"},"name":"limits","source":"device_property"}]},"normalization":{"conditions":[{"comparison":"below","field":"well.depth_m","operator":"and","type":"value_check","value":"limits.value.max_depth_m * 0.9"}],"confirmation":{"mode":"immediate"},"notifications":[]},"reminder":{"notifications":[],"type":"none"},"severity":2},"description":"Hourly max depth of each well above its own limit: the 'limits' property of the device, or of its asset type, asset group or product when the device has none","enabled":true,"name":"Water table too deep"}},"Property condition":{"value":{"config":{"activation":{"conditions":[{"comparison":"below","field":"battery.value.level","operator":"and","type":"value_check","value":"15"}],"confirmation":{"mode":"immediate"},"notifications":[{"id":"ops_email","type":"endpoint"}]},"check_interval":{"magnitude":"hour","value":1},"data":{"sources":[{"device_property":{"asset_group":"field_sensors","fields":["value.level"],"property":"battery"},"name":"battery","source":"device_property"}]},"normalization":{"conditions":[{"comparison":"above","field":"battery.value.level","operator":"and","type":"value_check","value":"50"}],"confirmation":{"mode":"immediate"},"notifications":[]},"reminder":{"notifications":[],"type":"none"},"severity":1},"description":"Battery level reported in the 'battery' property below 15%, devices of the 'field_sensors' group","enabled":true,"name":"Low battery"}}},"schema":{"additionalProperties":false,"description":"Fields sent replace the stored ones; config replaces the whole rule configuration (read it first to change part of it).","examples":{"Disable the rule":{"value":{"enabled":false}},"Rename":{"value":{"description":"Zone A sensors only","name":"Greenhouse too hot - zone A"}}},"properties":{"config":{"$ref":"#/components/schemas/alarm_rule"},"description":{"$ref":"#/components/schemas/resource_description"},"enabled":{"type":"boolean"},"name":{"$ref":"#/components/schemas/resource_name"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"TestRule","tags":["Alarms"]}},"/v1/users/{user}/alarms/rules/{rule}/test-source":{"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"rule","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Alarm_TestRuleSourceTest-source","requestBody":{"content":{"application/json":{"examples":{"Bucket source":{"value":{"bucket":{"aggregation":{"period":"5m","type":"mean"},"group_by":["device"],"id":"greenhouse_climate","mapping":["temperature"]},"name":"climate","source":"bucket"}},"Device property source":{"value":{"device_property":{"asset_group":"field_sensors","fields":["value.level"],"property":"battery"},"name":"battery","source":"device_property"}},"Device status source":{"value":{"device_status":{"fields":["connection.active","connection.ts"],"product":"smart_meter"},"name":"status","source":"device_status"}}},"schema":{"description":"One data source, as in config.data.sources: returns the data it produces now, per device. The rule id in the path does not need to exist yet.","properties":{"bucket":{"type":"object"},"check_interval":{"description":"Window read by a bucket source without aggregation, as in config.check_interval (default: the rule's, or 1 minute). The rule does not need to exist.","type":"object"},"device_property":{"type":"object"},"device_status":{"type":"object"},"name":{"type":["string","null"]},"source":{"enum":["bucket","device_property","device_status"],"type":"string"}},"required":["source"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"TestRuleSource","tags":["Alarms"]}},"/v1/users/{user}/assets/locations":{"get":{"operationId":"Asset_ReadLocations","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadAssetsLocations","tags":["Assets"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v1/users/{user}/buckets":{"get":{"operationId":"Bucket_List","responses":{"200":{"content":{"application/json":{"example":[{"bucket":"api_write","config":{"source":"api"},"created":1791741478101,"description":"Bucket for API write","enabled":true,"modified":1791741478101,"name":"API Write"},{"bucket":"mqtt_bucket","config":{"source":"mqtt","topic":"house/+/temperature"},"created":1791741478101,"description":"Bucket for MQTT topic","enabled":true,"modified":1791741478101,"name":"MQTT Bucket"},{"bucket":"device_bucket","config":{"device":"macbook","interval":300,"resource":"data","source":"device","update":"interval"},"created":1791741478101,"description":"Bucket for Thinger.io device","enabled":true,"modified":1791741478101,"name":"Device Bucket"},{"bucket":"device_write","config":{"source":"write"},"created":1791741478101,"description":"Bucket dor device write","enabled":true,"modified":1791741478101,"name":"Device Write"},{"backend":"influxdb","bucket":"vibration","config":{"device":"vibration_01","interval":10,"resource":"accel","source":"device","update":"interval"},"created":1791741478101,"description":"Accelerometer read every 10 seconds","enabled":true,"modified":1791741478101,"name":"Vibration"},{"bucket":"meter_readings","config":{"source":"write","tags":["device","site"]},"created":1791741478101,"description":"Readings written by every meter, tagged by device and site","enabled":true,"modified":1791741478101,"name":"Meter readings"}],"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListBuckets","tags":["Buckets"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Bucket_Create","requestBody":{"content":{"application/json":{"examples":{"From API Call":{"value":{"bucket":"api_write","config":{"source":"api"},"description":"Bucket for API write","enabled":true,"name":"API Write"}},"From MQTT Topic":{"value":{"bucket":"mqtt_bucket","config":{"source":"mqtt","topic":"house/+/temperature"},"description":"Bucket for MQTT topic","enabled":true,"name":"MQTT Bucket"}},"From Thinger Device":{"value":{"bucket":"device_bucket","config":{"device":"macbook","interval":300,"resource":"data","source":"device","update":"interval"},"description":"Bucket for Thinger.io device","enabled":true,"name":"Device Bucket"}},"From Thinger Device Write":{"value":{"bucket":"device_write","config":{"source":"write"},"description":"Bucket dor device write","enabled":true,"name":"Device Write"}},"High rate on InfluxDB":{"value":{"backend":"influxdb","bucket":"vibration","config":{"device":"vibration_01","interval":10,"resource":"accel","source":"device","update":"interval"},"description":"Accelerometer read every 10 seconds","enabled":true,"name":"Vibration","retention":{"period":30,"unit":"days"}}},"Tagged writes, kept 2 years":{"value":{"bucket":"meter_readings","config":{"source":"write","tags":["device","site"]},"description":"Readings written by every meter, tagged by device and site","enabled":true,"name":"Meter readings","retention":{"period":2,"unit":"years"}}}},"schema":{"additionalProperties":false,"properties":{"asset_group":{"$ref":"#/components/schemas/resource_id"},"asset_type":{"$ref":"#/components/schemas/resource_id"},"backend":{"$ref":"#/components/schemas/bucket_backend"},"bucket":{"$ref":"#/components/schemas/resource_id"},"config":{"$ref":"#/components/schemas/bucket_config"},"description":{"$ref":"#/components/schemas/resource_description"},"enabled":{"type":"boolean"},"name":{"$ref":"#/components/schemas/resource_name"},"product":{"$ref":"#/components/schemas/resource_id"},"retention":{"$ref":"#/components/schemas/bucket_retention"}},"required":["bucket","name","config","enabled"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CreateBucket","tags":["Buckets"]}},"/v1/users/{user}/buckets/{bucket}":{"delete":{"operationId":"Bucket_Delete","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteBucket","tags":["Buckets"]},"get":{"operationId":"Bucket_ReadConfig","responses":{"200":{"content":{"application/json":{"examples":{"From API Call":{"value":{"bucket":"api_write","config":{"source":"api"},"created":1791741478101,"description":"Bucket for API write","enabled":true,"modified":1791741478101,"name":"API Write"}},"From MQTT Topic":{"value":{"bucket":"mqtt_bucket","config":{"source":"mqtt","topic":"house/+/temperature"},"created":1791741478101,"description":"Bucket for MQTT topic","enabled":true,"modified":1791741478101,"name":"MQTT Bucket"}},"From Thinger Device":{"value":{"bucket":"device_bucket","config":{"device":"macbook","interval":300,"resource":"data","source":"device","update":"interval"},"created":1791741478101,"description":"Bucket for Thinger.io device","enabled":true,"modified":1791741478101,"name":"Device Bucket"}},"From Thinger Device Write":{"value":{"bucket":"device_write","config":{"source":"write"},"created":1791741478101,"description":"Bucket dor device write","enabled":true,"modified":1791741478101,"name":"Device Write"}},"High rate on InfluxDB":{"value":{"backend":"influxdb","bucket":"vibration","config":{"device":"vibration_01","interval":10,"resource":"accel","source":"device","update":"interval"},"created":1791741478101,"description":"Accelerometer read every 10 seconds","enabled":true,"modified":1791741478101,"name":"Vibration","retention":{"period":30,"unit":"days"}}},"Tagged writes, kept 2 years":{"value":{"bucket":"meter_readings","config":{"source":"write","tags":["device","site"]},"created":1791741478101,"description":"Readings written by every meter, tagged by device and site","enabled":true,"modified":1791741478101,"name":"Meter readings","retention":{"period":2,"unit":"years"}}}},"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadBucketConfig","tags":["Buckets"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"bucket","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"operationId":"Bucket_Update","requestBody":{"content":{"application/json":{"examples":{"Full Update":{"value":{"bucket":"api_write","config":{"source":"api"},"description":"Bucket for API write","enabled":true,"name":"API Write"}},"Update 'config'":{"value":{"config":{"source":"api"}}},"Update 'description'":{"value":{"description":"Bucket for API write"}},"Update 'enabled'":{"value":{"enabled":true}},"Update 'name'":{"value":{"name":"API Write"}}},"schema":{"additionalProperties":false,"properties":{"asset_group":{"oneOf":[{"$ref":"#/components/schemas/resource_id"},{"maxLength":0,"type":"string"}]},"asset_type":{"oneOf":[{"$ref":"#/components/schemas/resource_id"},{"maxLength":0,"type":"string"}]},"backend":{"$ref":"#/components/schemas/bucket_backend"},"config":{"$ref":"#/components/schemas/bucket_config"},"description":{"$ref":"#/components/schemas/resource_description"},"enabled":{"type":"boolean"},"name":{"$ref":"#/components/schemas/resource_name"},"product":{"oneOf":[{"$ref":"#/components/schemas/resource_id"},{"maxLength":0,"type":"string"}]},"retention":{"$ref":"#/components/schemas/bucket_retention"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateBucket","tags":["Buckets"]}},"/v1/users/{user}/buckets/{bucket}/clone":{"get":{"operationId":"Bucket_CloneConfig","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneBucketConfig","tags":["Buckets"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"bucket","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Bucket_Clone","requestBody":{"content":{"application/json":{"examples":{"Copy with a new id":{"value":{"bucket":"copy_of_bucket"}},"Copy with name and description":{"value":{"bucket":"line_2_bucket","description":"Same configuration as the original, for production line 2","name":"Line 2 copy"}}},"schema":{"additionalProperties":false,"properties":{"bucket":{"$ref":"#/components/schemas/resource_id"},"description":{"$ref":"#/components/schemas/resource_description"},"enabled":{"type":"boolean"},"name":{"$ref":"#/components/schemas/resource_name"}},"required":["bucket"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneBucket","tags":["Buckets"]}},"/v1/users/{user}/buckets/{bucket}/data":{"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"bucket","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Bucket_WriteData","requestBody":{"content":{"application/json":{"examples":{"One record":{"value":{"device":"greenhouse_01","humidity":51,"temperature":23.4}},"With its own timestamp":{"value":{"energy":1532.8,"power":2.1,"ts":1791650000000}}},"schema":{"description":"The JSON object becomes one record. ?ts=<epoch ms> sets its timestamp (MongoDB buckets also take a numeric 'ts' field). Fields listed in the bucket tags are indexed for filtering. The bucket must be enabled."}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"WriteBucket","tags":["Buckets"]}},"/v1/users/{user}/buckets/{bucket}/exports":{"get":{"operationId":"Bucket_ListExports","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListBucketExports","tags":["Buckets"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"bucket","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Bucket_CreateExport","requestBody":{"content":{"application/json":{"examples":{"Everything as JSON, call an endpoint":{"value":{"callback":"endpoint","data_type":"json","endpoint":"export_ready","timestamp_format":"milliseconds"}},"Last month as CSV, email when ready":{"value":{"callback":"email","data_type":"csv","max_ts":1791590400000,"min_ts":1788998400000,"timestamp_format":"iso"}}},"schema":{"additionalProperties":false,"description":"Generates a file with the bucket data between min_ts and max_ts (epoch ms; all data when missing), listed in GET .../exports when ready. callback: notify by email to the owner or call an endpoint when it finishes.","properties":{"callback":{"enum":["email","endpoint"],"type":"string"},"data_type":{"enum":["csv","arff","json"],"type":"string"},"endpoint":{"$ref":"#/components/schemas/resource_id"},"max_ts":{"minimum":0,"type":"number"},"min_ts":{"minimum":0,"type":"number"},"timestamp_format":{"enum":["iso","seconds","milliseconds"],"type":"string"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CreateBucketExport","tags":["Buckets"]}},"/v1/users/{user}/buckets/{bucket}/exports/{file}":{"delete":{"operationId":"Bucket_DeleteExport","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteBucketExport","tags":["Buckets"]},"get":{"operationId":"Bucket_ReadExport","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadBucketExport","tags":["Buckets"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"bucket","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"file","required":true,"schema":{"pattern":"^.*$","type":"string"}}]},"/v1/users/{user}/buckets/{bucket}/imports":{"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"bucket","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Bucket_CreateImport","requestBody":{"content":{"application/json":{"examples":{"CSV from a storage":{"value":{"file":"meter_readings_2025.csv","source":"storage","storage":"imports"}}},"schema":{"additionalProperties":false,"description":"Loads records into the bucket from a file already uploaded to a file storage (CSV with a header row, as produced by an export).","properties":{"file":{"type":"string"},"source":{"enum":["storage"],"type":"string"},"storage":{"$ref":"#/components/schemas/resource_id"}},"required":["source","storage","file"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CreateBucketImport","tags":["Buckets"]}},"/v1/users/{user}/buckets/{bucket}/projects":{"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"bucket","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"operationId":"Bucket_UpdateProjects","requestBody":{"content":{"application/json":{"examples":{"No projects":{"value":[]},"One project":{"value":["alvarolb@greenhouse"]},"Two projects":{"value":["alvarolb@greenhouse","alvarolb@maintenance"]}},"schema":{"description":"Projects the resource belongs to, as <owner>@<project> ids. Replaces the whole list: read the current one first to add or remove a single project; [] removes it from every project.","items":{"pattern":"^[a-zA-Z0-9_]{1,32}@[a-zA-Z0-9_]{1,32}$","type":"string"},"type":"array"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateBucketProjects","tags":["Buckets"]}},"/v1/users/{user}/buckets/{bucket}/tags":{"get":{"operationId":"Bucket_ListTags","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListBucketTags","tags":["Buckets"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"bucket","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v1/users/{user}/buckets/{bucket}/tags/{tag}":{"get":{"operationId":"Bucket_ReadTag","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadBucketTag","tags":["Buckets"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"bucket","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"tag","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v1/users/{user}/claims":{"get":{"operationId":"Claim_List","responses":{"200":{"content":{"application/json":{"example":[{"claim":"kit_0042","created":1791741478121,"description":"Gateway, sensor and dashboard shipped in box 0042","enabled":true,"modified":1791741478121,"name":"Starter kit 0042"}],"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListClaims","tags":["Claims"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Claim_Create","requestBody":{"content":{"application/json":{"examples":{"Starter kit":{"value":{"claim":"kit_0042","config":{"max_claims":1,"members":["support"],"members_roles":["viewer"],"resources":[{"identifiers":["kit_0042_gw","kit_0042_sensor"],"type":"device"},{"identifiers":["kit_dashboard"],"type":"dashboard"}]},"description":"Gateway, sensor and dashboard shipped in box 0042","enabled":true,"name":"Starter kit 0042"}}},"schema":{"additionalProperties":false,"description":"A claim lets another account take some of your resources into one of the projects you share with it: it opens the claim URL (or posts the code to /v1/claims), and the listed resources join that project; 'members' are added to it with 'members_roles' (global roles). 'max_claims' limits how many times the code works (0 = unlimited).","properties":{"claim":{"$ref":"#/components/schemas/resource_id"},"config":{"$ref":"#/components/schemas/claim_config"},"description":{"$ref":"#/components/schemas/resource_description"},"enabled":{"type":"boolean"},"name":{"$ref":"#/components/schemas/resource_name"}},"required":["claim","name","enabled","config"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CreateClaim","tags":["Claims"]}},"/v1/users/{user}/claims/{claim}":{"delete":{"operationId":"Claim_Delete","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteClaim","tags":["Claims"]},"get":{"operationId":"Claim_ReadConfig","responses":{"200":{"content":{"application/json":{"examples":{"Starter kit":{"value":{"claim":"kit_0042","config":{"max_claims":1,"members":["support"],"members_roles":["viewer"],"resources":[{"identifiers":["kit_0042_gw","kit_0042_sensor"],"type":"device"},{"identifiers":["kit_dashboard"],"type":"dashboard"}]},"created":1791741478121,"description":"Gateway, sensor and dashboard shipped in box 0042","enabled":true,"modified":1791741478121,"name":"Starter kit 0042"}}},"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadClaimConfig","tags":["Claims"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"claim","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"operationId":"Claim_Update","requestBody":{"content":{"application/json":{"examples":{"Disable the code":{"value":{"enabled":false}},"Rename":{"value":{"name":"Starter kit 0042 - returned"}}},"schema":{"additionalProperties":false,"description":"config replaces the whole claim configuration.","properties":{"config":{"$ref":"#/components/schemas/claim_config"},"description":{"$ref":"#/components/schemas/resource_description"},"enabled":{"type":"boolean"},"name":{"$ref":"#/components/schemas/resource_name"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateClaim","tags":["Claims"]}},"/v1/users/{user}/claims/{claim}/clone":{"get":{"operationId":"Claim_CloneConfig","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneClaimConfig","tags":["Claims"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"claim","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Claim_Clone","requestBody":{"content":{"application/json":{"examples":{"Copy with a new id":{"value":{"claim":"copy_of_claim"}},"Copy with name and description":{"value":{"claim":"line_2_claim","description":"Same configuration as the original, for production line 2","name":"Line 2 copy"}}},"schema":{"additionalProperties":false,"properties":{"claim":{"$ref":"#/components/schemas/resource_id"},"description":{"$ref":"#/components/schemas/resource_description"},"enabled":{"type":"boolean"},"name":{"$ref":"#/components/schemas/resource_name"}},"required":["claim"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneClaim","tags":["Claims"]}},"/v1/users/{user}/claims/{claim}/projects":{"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"claim","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"operationId":"Claim_UpdateProjects","requestBody":{"content":{"application/json":{"examples":{"No projects":{"value":[]},"One project":{"value":["alvarolb@greenhouse"]},"Two projects":{"value":["alvarolb@greenhouse","alvarolb@maintenance"]}},"schema":{"description":"Projects the resource belongs to, as <owner>@<project> ids. Replaces the whole list: read the current one first to add or remove a single project; [] removes it from every project.","items":{"pattern":"^[a-zA-Z0-9_]{1,32}@[a-zA-Z0-9_]{1,32}$","type":"string"},"type":"array"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateClaimProjects","tags":["Claims"]}},"/v1/users/{user}/dashboards":{"get":{"operationId":"Dashboard_List","responses":{"200":{"content":{"application/json":{"example":[{"created":1791741478033,"dashboard":"plant_overview","description":"Production KPIs","modified":1791741478033,"name":"Plant overview"},{"created":1791741478033,"dashboard":"fleet","description":"Device list and detail app","modified":1791741478033,"name":"Fleet","source":"url"}],"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListDashboards","tags":["Dashboards"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Dashboard_Create","requestBody":{"content":{"application/json":{"examples":{"Empty widget dashboard":{"value":{"dashboard":"plant_overview","description":"Production KPIs","name":"Plant overview","tabs":[{"icon":"fas fa-tachometer-alt","name":"Main","widgets":[]}]}},"Url dashboard (SDK app)":{"value":{"dashboard":"fleet","description":"Device list and detail app","name":"Fleet","source":"url","url":"/v1/users/alvarolb/storages/fleet_app/files/index.html?v=1"}}},"schema":{"additionalProperties":false,"allOf":[{"if":{"properties":{"source":{"const":"url"}},"required":["source"]},"then":{"required":["url"]}}],"description":"Widget dashboards are designed in the console editor (tabs with widgets). Url dashboards (source: url) render a web page, usually an app in a public file storage that uses the dashboard SDK (/sdk/thinger-dashboard.md). To show a dashboard on a device, product, asset type, group or project page, store the same object as its 'dashboard' property instead.","properties":{"controls":{},"dashboard":{"$ref":"#/components/schemas/resource_id"},"description":{"maxLength":255,"type":"string"},"functions":{},"name":{"maxLength":255,"minLength":1,"type":"string"},"placeholders":{},"properties":{},"source":{"enum":["widgets","url"],"type":"string"},"tabs":{"items":{},"type":"array"},"url":{"maxLength":1024,"pattern":"^(/[^/\\\\]|https://)","type":"string"},"widgets":{"items":{},"type":"array"}},"required":["dashboard","name"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CreateDashboard","tags":["Dashboards"]}},"/v1/users/{user}/dashboards/{dashboard}":{"delete":{"operationId":"Dashboard_Delete","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteDashboard","tags":["Dashboards"]},"get":{"operationId":"Dashboard_ReadConfig","responses":{"200":{"content":{"application/json":{"examples":{"Empty widget dashboard":{"value":{"created":1791741478033,"dashboard":"plant_overview","description":"Production KPIs","modified":1791741478033,"name":"Plant overview","tabs":[{"icon":"fas fa-tachometer-alt","name":"Main","widgets":[]}]}},"Url dashboard (SDK app)":{"value":{"created":1791741478033,"dashboard":"fleet","description":"Device list and detail app","modified":1791741478033,"name":"Fleet","source":"url","url":"/v1/users/alvarolb/storages/fleet_app/files/index.html?v=1"}}},"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadDashboardConfig","tags":["Dashboards"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"dashboard","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"operationId":"Dashboard_Update","requestBody":{"content":{"application/json":{"examples":{"Point to a new app version":{"value":{"source":"url","url":"/v1/users/alvarolb/storages/fleet_app/files/index.html?v=2"}},"Rename":{"value":{"description":"Production KPIs","name":"Plant overview (2026)"}}},"schema":{"additionalProperties":false,"allOf":[{"if":{"properties":{"source":{"const":"url"}},"required":["source"]},"then":{"required":["url"]}}],"properties":{"controls":{},"description":{"maxLength":255,"type":"string"},"functions":{},"name":{"maxLength":255,"minLength":1,"type":"string"},"placeholders":{},"properties":{},"source":{"enum":["widgets","url"],"type":"string"},"tabs":{"items":{},"type":"array"},"url":{"maxLength":1024,"pattern":"^(/[^/\\\\]|https://)","type":"string"},"widgets":{"items":{},"type":"array"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateDashboard","tags":["Dashboards"]}},"/v1/users/{user}/dashboards/{dashboard}/clone":{"get":{"operationId":"Dashboard_CloneConfig","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneDashboardConfig","tags":["Dashboards"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"dashboard","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Dashboard_Clone","requestBody":{"content":{"application/json":{"examples":{"Copy with a new id":{"value":{"dashboard":"copy_of_dashboard"}},"Copy with name and description":{"value":{"dashboard":"line_2_dashboard","description":"Same configuration as the original, for production line 2","name":"Line 2 copy"}}},"schema":{"additionalProperties":false,"properties":{"dashboard":{"$ref":"#/components/schemas/resource_id"},"description":{"$ref":"#/components/schemas/resource_description"},"enabled":{"type":"boolean"},"name":{"$ref":"#/components/schemas/resource_name"}},"required":["dashboard"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneDashboard","tags":["Dashboards"]}},"/v1/users/{user}/dashboards/{dashboard}/projects":{"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"dashboard","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"operationId":"Dashboard_UpdateProjects","requestBody":{"content":{"application/json":{"examples":{"No projects":{"value":[]},"One project":{"value":["alvarolb@greenhouse"]},"Two projects":{"value":["alvarolb@greenhouse","alvarolb@maintenance"]}},"schema":{"description":"Projects the resource belongs to, as <owner>@<project> ids. Replaces the whole list: read the current one first to add or remove a single project; [] removes it from every project.","items":{"pattern":"^[a-zA-Z0-9_]{1,32}@[a-zA-Z0-9_]{1,32}$","type":"string"},"type":"array"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateDashboardProjects","tags":["Dashboards"]}},"/v1/users/{user}/devices":{"get":{"operationId":"Device_List","responses":{"200":{"content":{"application/json":{"example":[{"asset_group":"AssetGroup","asset_type":"AssetType","created":1791741476395,"description":"HTTP Device","device":"http_device","enabled":true,"modified":1791741476395,"name":"SN0300301","type":"HTTP"},{"asset_group":"AssetGroup","asset_type":"AssetType","created":1791741476395,"description":"MQTT Device","device":"mqtt_device","enabled":true,"modified":1791741476395,"name":"SN0300301","type":"MQTT"},{"asset_group":"AssetGroup","asset_type":"AssetType","created":1791741476395,"description":"Thinger Device","device":"thinger_device","enabled":true,"modified":1791741476395,"name":"SN0300301","type":"Generic"}],"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListDevices","tags":["Devices"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Device_Create","requestBody":{"content":{"application/json":{"examples":{"HTTP Device":{"value":{"asset_group":"AssetGroup","asset_type":"AssetType","description":"HTTP Device","device":"http_device","enabled":true,"name":"SN0300301","type":"HTTP"}},"MQTT Device":{"value":{"asset_group":"AssetGroup","asset_type":"AssetType","credentials":"juvWgl9@y3CW","description":"MQTT Device","device":"mqtt_device","enabled":true,"name":"SN0300301","type":"MQTT"}},"Thinger Device":{"value":{"asset_group":"AssetGroup","asset_type":"AssetType","credentials":"juvWgl9@y3CW","description":"Thinger Device","device":"thinger_device","enabled":true,"name":"SN0300301","type":"Generic"}}},"schema":{"oneOf":[{"additionalProperties":false,"properties":{"asset_group":{"$ref":"#/components/schemas/resource_id"},"asset_type":{"$ref":"#/components/schemas/resource_id"},"connection":{"additionalProperties":false,"properties":{"timeouts":{"additionalProperties":false,"properties":{"disconnect":{"minimum":60,"type":"integer"},"sleep":{"minimum":0,"type":"integer"}},"type":"object"}},"type":"object"},"credentials":{"maxLength":255,"minLength":6,"type":"string"},"description":{"maxLength":255,"minLength":0,"type":"string"},"device":{"$ref":"#/components/schemas/resource_id"},"enabled":{"type":"boolean"},"labels":{"additionalProperties":{"maxLength":255,"type":"string"},"propertyNames":{"pattern":"^[A-Za-z0-9_][A-Za-z0-9_-]{0,62}$"},"type":"object"},"name":{"maxLength":255,"minLength":0,"type":"string"},"product":{"$ref":"#/components/schemas/resource_id"},"type":{"enum":["Generic","MQTT"],"type":"string"}},"required":["device","credentials"],"type":"object"},{"additionalProperties":false,"properties":{"asset_group":{"$ref":"#/components/schemas/resource_id"},"asset_type":{"$ref":"#/components/schemas/resource_id"},"description":{"maxLength":255,"minLength":1,"type":"string"},"device":{"$ref":"#/components/schemas/resource_id"},"enabled":{"type":"boolean"},"labels":{"additionalProperties":{"maxLength":255,"type":"string"},"propertyNames":{"pattern":"^[A-Za-z0-9_][A-Za-z0-9_-]{0,62}$"},"type":"object"},"name":{"maxLength":255,"minLength":0,"type":"string"},"parent":{"$ref":"#/components/schemas/resource_id"},"product":{"$ref":"#/components/schemas/resource_id"},"protocol":{"maxLength":50,"minLength":1,"type":"string"},"type":{"enum":["HTTP","Virtual","Subdevice"],"type":"string"}},"required":["device"],"type":"object"}]}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CreateDevice","tags":["Devices"]}},"/v1/users/{user}/devices/{device}":{"delete":{"operationId":"Device_Delete","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteDevice","tags":["Devices"]},"get":{"operationId":"Device_ReadStatus","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadDeviceStatus","tags":["Devices"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"device","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"operationId":"Device_Update","requestBody":{"content":{"application/json":{"examples":{"Update Asset Group":{"value":{"asset_group":"Farm 1"}},"Update Asset Type":{"value":{"asset_type":"Truck"}},"Update Credentials":{"value":{"credentials":"SJ?nROYpEzDn"}},"Update Description":{"value":{"description":"Updated Description"}},"Update Enabled":{"value":{"enabled":false}},"Update Labels":{"value":{"labels":{"region":"europe","type":"small"}}},"Update Name":{"value":{"name":"SN0300301"}}},"schema":{"additionalProperties":false,"properties":{"asset_group":{"oneOf":[{"$ref":"#/components/schemas/resource_id"},{"maxLength":0,"type":"string"}]},"asset_type":{"oneOf":[{"$ref":"#/components/schemas/resource_id"},{"maxLength":0,"type":"string"}]},"connection":{"additionalProperties":false,"properties":{"timeout":{"minimum":1,"type":"integer"},"timeouts":{"additionalProperties":false,"properties":{"disconnect":{"minimum":60,"type":"integer"},"sleep":{"minimum":0,"type":"integer"}},"type":"object"}},"type":"object"},"credentials":{"maxLength":255,"minLength":1,"type":"string"},"description":{"maxLength":255,"minLength":0,"type":"string"},"enabled":{"type":"boolean"},"labels":{"additionalProperties":{"maxLength":255,"type":"string"},"propertyNames":{"pattern":"^[A-Za-z0-9_][A-Za-z0-9_-]{0,62}$"},"type":"object"},"name":{"maxLength":255,"minLength":0,"type":"string"},"product":{"oneOf":[{"$ref":"#/components/schemas/resource_id"},{"maxLength":0,"type":"string"}]}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateDevice","tags":["Devices"]}},"/v1/users/{user}/devices/{device}/clone":{"get":{"operationId":"Device_CloneConfig","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneDeviceConfig","tags":["Devices"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"device","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Device_Clone","requestBody":{"content":{"application/json":{"examples":{"Copy with a new id":{"value":{"device":"copy_of_device"}},"Copy with name and description":{"value":{"description":"Same configuration as the original, for production line 2","device":"line_2_device","name":"Line 2 copy"}}},"schema":{"additionalProperties":false,"properties":{"description":{"$ref":"#/components/schemas/resource_description"},"device":{"$ref":"#/components/schemas/resource_id"},"enabled":{"type":"boolean"},"name":{"$ref":"#/components/schemas/resource_name"}},"required":["device"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneDevice","tags":["Devices"]}},"/v1/users/{user}/devices/{device}/projects":{"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"device","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"operationId":"Device_UpdateProjects","requestBody":{"content":{"application/json":{"examples":{"No projects":{"value":[]},"One project":{"value":["alvarolb@greenhouse"]},"Two projects":{"value":["alvarolb@greenhouse","alvarolb@maintenance"]}},"schema":{"description":"Projects the resource belongs to, as <owner>@<project> ids. Replaces the whole list: read the current one first to add or remove a single project; [] removes it from every project.","items":{"pattern":"^[a-zA-Z0-9_]{1,32}@[a-zA-Z0-9_]{1,32}$","type":"string"},"type":"array"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateDeviceProjects","tags":["Devices"]}},"/v1/users/{user}/devices/{device}/stats":{"get":{"deprecated":true,"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadDeviceStatistics","tags":["Devices"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"device","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v1/users/{user}/devices/{device}/tokens":{"get":{"operationId":"Device_ListTokens","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListDeviceTokens","tags":["Devices"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"device","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Device_CreateToken","requestBody":{"content":{"application/json":{"examples":{"All resources until a date":{"value":{"token_expiration":1798761600,"token_name":"Installer"}},"Read two resources":{"value":{"token_name":"Display panel","token_resources":["temperature","humidity"]}}},"schema":{"description":"A token limited to this device: it can only call the listed device resources (all of them when token_resources is missing). Useful to let a third party read or control one device.","properties":{"token_expiration":{"description":"Unix timestamp when the token stops working.","type":"number"},"token_name":{"type":"string"},"token_resources":{"description":"Resource names the token can call.","items":{"type":"string"},"type":"array"}},"required":["token_name"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CreateDeviceToken","tags":["Devices"]}},"/v1/users/{user}/devices/{device}/tokens/{token}":{"delete":{"operationId":"Device_DeleteToken","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteDeviceToken","tags":["Devices"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"device","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"token","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,50}","type":"string"}}]},"/v1/users/{user}/devices/{device}/{resource}":{"get":{"deprecated":true,"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"AccessDeviceResources","tags":["Devices"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"device","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"resource","required":true,"schema":{"pattern":"^(?:.{1,32}\\/?+)","type":"string"}}],"post":{"deprecated":true,"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"AccessDeviceResources","tags":["Devices"]}},"/v1/users/{user}/email":{"get":{"operationId":"User_ReadEmail","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadUserEmail","tags":["Users"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v1/users/{user}/endpoints":{"get":{"operationId":"Endpoint_List","responses":{"200":{"content":{"application/json":{"example":[{"created":1791741476398,"description":"Email Endpoint","enabled":true,"endpoint":"email_endpoint","modified":1791741476398,"name":"Email","type":"email"},{"created":1791741476398,"description":"HTTP Request","enabled":true,"endpoint":"http_request","modified":1791741476398,"name":"HTTP","type":"http_request"},{"created":1791741476398,"description":"HTTP request","enabled":true,"endpoint":"http_request","modified":1791741476398,"name":"HTTP","type":"http_request"}],"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListEndpoints","tags":["Endpoints"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Endpoint_Create","requestBody":{"content":{"application/json":{"examples":{"Email":{"description":"Creates an endpoint that sends an email when called. The calling data can be used in the body or the subject using placeholders like {{temperature}}.","value":{"config":{"body":"<p>The current temperature and humidity are: {{temperature}}, {{humidity}}</p>","body_type":"html","recipient":"alvarolb@thinger.io","reply_to":"alvarolb@thinger.io","subject":"Endpoint Testing"},"description":"Email Endpoint","enabled":true,"endpoint":"email_endpoint","name":"Email","type":"email"}},"HTTP Request":{"description":"Creates an endpoint that resend the call JSON data to the target endpoint, both from api or device calls. The calling data can be used in the url or headers using placeholders like {{temperature}}.","value":{"config":{"body":"","body_type":"json","headers":[{"key":"Authorization","value":"Bearer xyz"}],"method":"POST","url":"https://api.acme.com/sensor"},"description":"HTTP Request","enabled":true,"endpoint":"http_request","name":"HTTP","type":"http_request"}},"HTTP Request Custom Body":{"description":"Creates an endpoint that composes a new paylaod with the source variables passed to the call, both from api or device calls. The calling data can be used in the body, url, or headers using placeholders like {{temperature}}.","value":{"config":{"body":"{\n \"val1\" : {{temperature}},\n \"val2\": {{humidity}}\n}","body_type":"custom","headers":[{"key":"Content-Type","value":"application/json"}],"method":"POST","url":"https://api.acme.com/sensor"},"description":"HTTP request","enabled":true,"endpoint":"http_request","name":"HTTP","type":"http_request"}}},"schema":{"additionalProperties":false,"allOf":[{"if":{"properties":{"type":{"not":{"const":"virtual"}}},"required":["type"]},"then":{"required":["config"]}}],"description":"An endpoint is an outgoing action: type 'email', 'http_request' (webhooks, REST APIs), 'virtual' (no-op, for testing) or the id of an endpoint template (GET /v1/endpoints/templates lists them with their parameters; config is then {template, parameters}). Templates in config use {{payload}} (the data of the call) and its fields, e.g. {{payload.temperature}}. Called from the API (POST .../call), devices, product flows and alarm notifications.","properties":{"config":{"description":"Settings of the endpoint type; not needed for 'virtual'.","type":"object"},"description":{"maxLength":255,"type":"string"},"enabled":{"type":"boolean"},"endpoint":{"$ref":"#/components/schemas/resource_id"},"name":{"maxLength":255,"type":"string"},"type":{"maxLength":255,"minLength":1,"type":"string"}},"required":["endpoint","type"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CreateEndpoint","tags":["Endpoints"]}},"/v1/users/{user}/endpoints/{endpoint}":{"delete":{"operationId":"Endpoint_Delete","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteEndpoint","tags":["Endpoints"]},"get":{"operationId":"Endpoint_ReadConfig","responses":{"200":{"content":{"application/json":{"examples":{"Email":{"description":"Creates an endpoint that sends an email when called. The calling data can be used in the body or the subject using placeholders like {{temperature}}.","value":{"config":{"body":"<p>The current temperature and humidity are: {{temperature}}, {{humidity}}</p>","body_type":"html","recipient":"alvarolb@thinger.io","reply_to":"alvarolb@thinger.io","subject":"Endpoint Testing"},"created":1791741476398,"description":"Email Endpoint","enabled":true,"endpoint":"email_endpoint","modified":1791741476398,"name":"Email","type":"email"}},"HTTP Request":{"description":"Creates an endpoint that resend the call JSON data to the target endpoint, both from api or device calls. The calling data can be used in the url or headers using placeholders like {{temperature}}.","value":{"config":{"body":"","body_type":"json","headers":[{"key":"Authorization","value":"Bearer xyz"}],"method":"POST","url":"https://api.acme.com/sensor"},"created":1791741476398,"description":"HTTP Request","enabled":true,"endpoint":"http_request","modified":1791741476398,"name":"HTTP","type":"http_request"}},"HTTP Request Custom Body":{"description":"Creates an endpoint that composes a new paylaod with the source variables passed to the call, both from api or device calls. The calling data can be used in the body, url, or headers using placeholders like {{temperature}}.","value":{"config":{"body":"{\n \"val1\" : {{temperature}},\n \"val2\": {{humidity}}\n}","body_type":"custom","headers":[{"key":"Content-Type","value":"application/json"}],"method":"POST","url":"https://api.acme.com/sensor"},"created":1791741476398,"description":"HTTP request","enabled":true,"endpoint":"http_request","modified":1791741476398,"name":"HTTP","type":"http_request"}}},"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadEndpointConfig","tags":["Endpoints"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"endpoint","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"operationId":"Endpoint_Update","requestBody":{"content":{"application/json":{"examples":{"Full Update":{"value":{"config":{"body":"<p>The current temperature and humidity are: {{temperature}}, {{humidity}}</p>","body_type":"html","recipient":"alvarolb@thinger.io","reply_to":"alvarolb@thinger.io","subject":"Endpoint Testing"},"description":"Email Endpoint","enabled":true,"endpoint":"email_endpoint","name":"Email","type":"email"}},"Update 'config'":{"value":{"config":{"body":"<p>The current temperature and humidity are: {{temperature}}, {{humidity}}</p>","body_type":"html","recipient":"alvarolb@thinger.io","reply_to":"alvarolb@thinger.io","subject":"Endpoint Testing"}}},"Update 'description'":{"value":{"description":"Email Endpoint"}},"Update 'enabled'":{"value":{"enabled":true}},"Update 'name'":{"value":{"name":"Email"}},"Update 'type'":{"value":{"type":"email"}}},"schema":{"additionalProperties":false,"properties":{"config":{"type":"object"},"description":{"maxLength":255,"type":"string"},"enabled":{"type":"boolean"},"name":{"maxLength":255,"type":"string"},"type":{"maxLength":255,"minLength":1,"type":"string"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateEndpoint","tags":["Endpoints"]}},"/v1/users/{user}/endpoints/{endpoint}/call":{"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"endpoint","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Endpoint_Call","requestBody":{"content":{"application/json":{"examples":{"Alert payload":{"value":{"device":"greenhouse_01","message":"Temperature above 30","temperature":31.2}}},"schema":{"description":"Optional JSON payload, available to the endpoint templates as {{payload}} (e.g. the body of a webhook or the content of an email). The response is what the endpoint answered."}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CallEndpoint","tags":["Endpoints"]}},"/v1/users/{user}/endpoints/{endpoint}/clone":{"get":{"operationId":"Endpoint_CloneConfig","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneEndpointConfig","tags":["Endpoints"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"endpoint","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Endpoint_Clone","requestBody":{"content":{"application/json":{"examples":{"Copy with a new id":{"value":{"endpoint":"copy_of_endpoint"}},"Copy with name and description":{"value":{"description":"Same configuration as the original, for production line 2","endpoint":"line_2_endpoint","name":"Line 2 copy"}}},"schema":{"additionalProperties":false,"properties":{"description":{"$ref":"#/components/schemas/resource_description"},"enabled":{"type":"boolean"},"endpoint":{"$ref":"#/components/schemas/resource_id"},"name":{"$ref":"#/components/schemas/resource_name"}},"required":["endpoint"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneEndpoint","tags":["Endpoints"]}},"/v1/users/{user}/endpoints/{endpoint}/projects":{"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"endpoint","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"operationId":"Endpoint_UpdateProjects","requestBody":{"content":{"application/json":{"examples":{"No projects":{"value":[]},"One project":{"value":["alvarolb@greenhouse"]},"Two projects":{"value":["alvarolb@greenhouse","alvarolb@maintenance"]}},"schema":{"description":"Projects the resource belongs to, as <owner>@<project> ids. Replaces the whole list: read the current one first to add or remove a single project; [] removes it from every project.","items":{"pattern":"^[a-zA-Z0-9_]{1,32}@[a-zA-Z0-9_]{1,32}$","type":"string"},"type":"array"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateEndpointProjects","tags":["Endpoints"]}},"/v1/users/{user}/events":{"get":{"deprecated":true,"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"SubscribeUserEvents","tags":["Users"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v1/users/{user}/federated_identities/{identity_provider}":{"delete":{"operationId":"User_DeleteFederatedIdentity","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteUserFederatedIdentity","tags":["Users"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"identity_provider","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v1/users/{user}/groups":{"get":{"operationId":"Group_List","responses":{"200":{"content":{"application/json":{"example":[{"group":"madrid_line_2","name":"Line 2","parent":"madrid_plant"},{"description":"Devices installed in the Madrid plant","group":"madrid_plant","name":"Madrid plant"}],"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListGroups","tags":["Groups"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Group_Create","requestBody":{"content":{"application/json":{"examples":{"Area inside a site":{"value":{"group":"madrid_line_2","name":"Line 2","parent":"madrid_plant"}},"Site":{"value":{"description":"Devices installed in the Madrid plant","group":"madrid_plant","name":"Madrid plant"}}},"schema":{"additionalProperties":false,"description":"An asset group is where or whose a device is (a site, a customer, a building). Groups nest through 'parent'; devices join one with their asset_group field and inherit its properties. Project members can be limited to some groups.","properties":{"description":{"type":"string"},"group":{"$ref":"#/components/schemas/resource_id"},"name":{"type":"string"},"parent":{"$ref":"#/components/schemas/resource_id"}},"required":["group"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CreateGroup","tags":["Groups"]}},"/v1/users/{user}/groups/{group}":{"delete":{"operationId":"Group_Delete","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteGroup","tags":["Groups"]},"get":{"operationId":"Group_ReadConfig","responses":{"200":{"content":{"application/json":{"examples":{"Area inside a site":{"value":{"group":"madrid_line_2","name":"Line 2","parent":"madrid_plant"}},"Site":{"value":{"description":"Devices installed in the Madrid plant","group":"madrid_plant","name":"Madrid plant"}}},"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadGroupConfig","tags":["Groups"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"group","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"operationId":"Group_Update","requestBody":{"content":{"application/json":{"examples":{"Rename":{"value":{"description":"North building","name":"Madrid plant - north"}}},"schema":{"additionalProperties":false,"properties":{"description":{"type":"string"},"name":{"type":"string"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateGroup","tags":["Groups"]}},"/v1/users/{user}/groups/{group}/clone":{"get":{"operationId":"Group_CloneConfig","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneGroupConfig","tags":["Groups"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"group","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Group_Clone","requestBody":{"content":{"application/json":{"examples":{"Copy with a new id":{"value":{"group":"copy_of_group"}},"Copy with name and description":{"value":{"description":"Same configuration as the original, for production line 2","group":"line_2_group","name":"Line 2 copy"}}},"schema":{"additionalProperties":false,"properties":{"description":{"$ref":"#/components/schemas/resource_description"},"enabled":{"type":"boolean"},"group":{"$ref":"#/components/schemas/resource_id"},"name":{"$ref":"#/components/schemas/resource_name"}},"required":["group"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneGroup","tags":["Groups"]}},"/v1/users/{user}/groups/{group}/locations":{"get":{"operationId":"Group_ReadAssetsLocations","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadAssetsLocations","tags":["Groups"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"group","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v1/users/{user}/groups/{group}/projects":{"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"group","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"operationId":"Group_UpdateProjects","requestBody":{"content":{"application/json":{"examples":{"No projects":{"value":[]},"One project":{"value":["alvarolb@greenhouse"]},"Two projects":{"value":["alvarolb@greenhouse","alvarolb@maintenance"]}},"schema":{"description":"Projects the resource belongs to, as <owner>@<project> ids. Replaces the whole list: read the current one first to add or remove a single project; [] removes it from every project.","items":{"pattern":"^[a-zA-Z0-9_]{1,32}@[a-zA-Z0-9_]{1,32}$","type":"string"},"type":"array"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateGroupProjects","tags":["Groups"]}},"/v1/users/{user}/groups/{group}/properties":{"get":{"operationId":"Group_ListProperties","responses":{"200":{"content":{"application/json":{"example":[{"created":1791741476402,"description":"Sampling and alert thresholds","modified":1791741476402,"name":"Settings","property":"settings","type":"configuration","value":{"alerts":true,"interval":60,"max_temperature":28.5}},{"created":1791741476402,"modified":1791741476402,"name":"Location","property":"location","value":{"lat":40.4168,"lon":-3.7038}},{"created":1791741476402,"modified":1791741476402,"name":"Calibration","perm":{"readOnly":["member"]},"property":"calibration","value":{"gain":1.02,"offset":-0.4}},{"created":1791741476402,"modified":1791741476402,"name":"Dashboard","property":"dashboard","value":{"source":"url","url":"/v1/users/alvarolb/storages/fleet_app/files/index.html?v=1"}}],"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListGroupProperties","tags":["Groups"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"group","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Group_CreateProperty","requestBody":{"content":{"application/json":{"examples":{"Configuration value":{"value":{"description":"Sampling and alert thresholds","name":"Settings","property":"settings","type":"configuration","value":{"alerts":true,"interval":60,"max_temperature":28.5}}},"Location":{"value":{"name":"Location","property":"location","value":{"lat":40.4168,"lon":-3.7038}}},"Read-only for project members":{"value":{"name":"Calibration","perm":{"readOnly":["member"]},"property":"calibration","value":{"gain":1.02,"offset":-0.4}}},"Url dashboard of the resource":{"value":{"name":"Dashboard","property":"dashboard","value":{"source":"url","url":"/v1/users/alvarolb/storages/fleet_app/files/index.html?v=1"}}}},"schema":{"description":"A property is a JSON value stored on its resource (device, asset type, asset group, project, product, plugin or account). Devices inherit the properties of their asset type, asset group and product. 'type: configuration' marks values the device reads; 'perm' hides or locks a property for the account owner or project members. An array of these objects creates several at once.","oneOf":[{"items":{"$ref":"#/components/schemas/property_create"},"type":"array"},{"$ref":"#/components/schemas/property_create"}]}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CreateGroupProperty","tags":["Groups"]}},"/v1/users/{user}/groups/{group}/properties/{property}":{"delete":{"operationId":"Group_DeleteProperty","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteGroupProperty","tags":["Groups"]},"get":{"operationId":"Group_ReadProperty","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadGroupProperty","tags":["Groups"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"group","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"property","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"patch":{"operationId":"Group_PatchProperty","requestBody":{"content":{"application/json":{"examples":{"Change some fields of the value":{"value":{"value":{"interval":30}}},"Flattened fields":{"value":{"value.alerts":false,"value.max_temperature":27}}},"schema":{"oneOf":[{"additionalProperties":false,"properties":{"value":{}},"required":["value"]},{"additionalProperties":false,"minProperties":1,"patternProperties":{"^value(\\.[^.]+)+$":{}}}],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateGroupProperty","tags":["Groups"]},"put":{"operationId":"Group_UpdateProperty","requestBody":{"content":{"application/json":{"examples":{"Hide from project members":{"value":{"perm":{"hidden":["member"]},"value":"internal note"}},"Replace the value":{"value":{"value":{"alerts":true,"interval":30,"max_temperature":27}}},"Value, name and description":{"value":{"description":"Faster sampling during commissioning","name":"Settings","value":{"alerts":false,"interval":10,"max_temperature":28.5}}}},"schema":{"$ref":"#/components/schemas/property_update"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateGroupProperty","tags":["Groups"]}},"/v1/users/{user}/groups/{group}/properties/{property}/clone":{"get":{"operationId":"Group_ClonePropertyConfig","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneGroupPropertyConfig","tags":["Groups"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"group","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"property","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Group_CloneProperty","requestBody":{"content":{"application/json":{"examples":{"Copy with a new id":{"value":{"property":"copy_of_property"}},"Copy with name and description":{"value":{"description":"Same configuration as the original, for production line 2","name":"Line 2 copy","property":"line_2_property"}}},"schema":{"additionalProperties":false,"properties":{"description":{"$ref":"#/components/schemas/resource_description"},"enabled":{"type":"boolean"},"name":{"$ref":"#/components/schemas/resource_name"},"property":{"$ref":"#/components/schemas/resource_id"}},"required":["property"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneGroupProperty","tags":["Groups"]}},"/v1/users/{user}/info/device_locations":{"get":{"operationId":"User_ListDeviceLocationsDevice_location","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListDeviceLocations","tags":["Users"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v1/users/{user}/info/devices/locations":{"get":{"operationId":"User_ListDeviceLocations","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListDeviceLocations","tags":["Users"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v1/users/{user}/info/devices/stats":{"get":{"operationId":"Device_ReadDevicesStatistics","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadDeviceStatistics","tags":["Devices"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v1/users/{user}/limits":{"get":{"operationId":"User_ReadLimits","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadUserLimits","tags":["Users"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v1/users/{user}/limits/{resource}":{"get":{"operationId":"User_ReadResourceLimits","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadUserLimits","tags":["Users"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"resource","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v1/users/{user}/membership/{project_owner}/{project_id}/permissions":{"get":{"operationId":"User_ReadProjectPermissions","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadProjectPermissions","tags":["Users"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"project_owner","required":true,"schema":{"pattern":"^[a-zA-Z0-9_]{1,32}","type":"string"}},{"in":"path","name":"project_id","required":true,"schema":{"pattern":"^[a-zA-Z0-9_]{1,32}","type":"string"}}]},"/v1/users/{user}/mfa":{"get":{"operationId":"User_ReadMFAMfa","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadUserMFA","tags":["Users"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v1/users/{user}/mfa/totp":{"delete":{"operationId":"User_DeleteTOTPTotp","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteUserTOTP","tags":["Users"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v1/users/{user}/mfa/totp/backup-codes":{"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"User_CreateTOTPBackupCodesBackup-code","requestBody":{"content":{"application/json":{"schema":{"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CreateUserTOTPBackupCodes","tags":["Users"]}},"/v1/users/{user}/mfa/totp/setup":{"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"User_SetupTOTP","requestBody":{"content":{"application/json":{"schema":{"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"SetupUserTOTP","tags":["Users"]}},"/v1/users/{user}/mfa/totp/verify":{"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"User_VerifyTOTP","requestBody":{"content":{"application/json":{"schema":{"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"VerifyUserTOTP","tags":["Users"]}},"/v1/users/{user}/mfa/webauthn/credentials/{credential}":{"delete":{"operationId":"User_DeleteWebAuthnCredential","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteWebAuthnCredential","tags":["Users"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"credential","required":true,"schema":{"pattern":"^[a-zA-Z0-9_=-]{1,512}","type":"string"}}],"put":{"operationId":"User_UpdateWebAuthnCredential","requestBody":{"content":{"application/json":{"schema":{"properties":{"name":{"maxLength":255,"minLength":1,"type":"string"}},"required":["name"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateWebAuthnCredential","tags":["Users"]}},"/v1/users/{user}/mfa/webauthn/register/options":{"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"User_WebAuthnRegisterOptions","requestBody":{"content":{"application/json":{"schema":{"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"WebAuthnRegisterOptions","tags":["Users"]}},"/v1/users/{user}/mfa/webauthn/register/verify":{"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"User_WebAuthnRegisterVerify","requestBody":{"content":{"application/json":{"schema":{"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"WebAuthnRegisterVerify","tags":["Users"]}},"/v1/users/{user}/oauth/authorize":{"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"User_AuthorizeOauth","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":false,"properties":{"client_id":{"type":"string"},"login_hint":{"type":"string"},"nonce":{"type":"string"},"prompt":{"type":"string"},"redirect_uri":{"type":"string"},"response_mode":{"type":"string"},"response_type":{"enum":["code"]},"scope":{"type":"string"},"state":{"type":"string"},"ui_locales":{"type":"string"}},"required":["client_id","response_type"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"AuthorizeOauth","tags":["Users"]}},"/v1/users/{user}/passkeys":{"get":{"operationId":"User_ReadPasskeys","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadUserPasskeys","tags":["Users"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v1/users/{user}/passkeys/register/options":{"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"User_PasskeyRegisterOptions","requestBody":{"content":{"application/json":{"schema":{"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"PasskeyRegisterOptions","tags":["Users"]}},"/v1/users/{user}/passkeys/register/verify":{"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"User_PasskeyRegisterVerify","requestBody":{"content":{"application/json":{"schema":{"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"PasskeyRegisterVerify","tags":["Users"]}},"/v1/users/{user}/passkeys/{credential}":{"delete":{"operationId":"User_DeletePasskey","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteUserPasskey","tags":["Users"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"credential","required":true,"schema":{"pattern":"^[a-zA-Z0-9_=-]{1,512}","type":"string"}}],"put":{"operationId":"User_UpdatePasskey","requestBody":{"content":{"application/json":{"schema":{"properties":{"name":{"maxLength":255,"minLength":1,"type":"string"}},"required":["name"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateUserPasskey","tags":["Users"]}},"/v1/users/{user}/password":{"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"operationId":"User_UpdatePassword","requestBody":{"content":{"application/json":{"schema":{"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateUserPassword","tags":["Users"]}},"/v1/users/{user}/plugins":{"get":{"operationId":"Plugin_List","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListPlugins","tags":["Plugins"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v1/users/{user}/plugins/{plugin}":{"get":{"operationId":"Plugin_ReadInfo","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadPluginInfo","tags":["Plugins"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"plugin","required":true,"schema":{"pattern":"^[a-zA-Z0-9_\\-\\:]{1,32}","type":"string"}}],"post":{"operationId":"Plugin_ManageState","requestBody":{"content":{"application/json":{"schema":{"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ManagePluginState","tags":["Plugins"]}},"/v1/users/{user}/plugins/{plugin}/files/{file}":{"get":{"operationId":"Plugin_ReadFiles","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadPluginFiles","tags":["Plugins"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"plugin","required":true,"schema":{"pattern":"^[a-zA-Z0-9_\\-\\:]{1,32}","type":"string"}},{"in":"path","name":"file","required":true,"schema":{"pattern":"^.*$","type":"string"}}]},"/v1/users/{user}/plugins/{plugin}/properties":{"get":{"operationId":"Plugin_ListProperties","responses":{"200":{"content":{"application/json":{"example":[{"created":1791741478122,"description":"Sampling and alert thresholds","modified":1791741478122,"name":"Settings","property":"settings","type":"configuration","value":{"alerts":true,"interval":60,"max_temperature":28.5}},{"created":1791741478122,"modified":1791741478122,"name":"Location","property":"location","value":{"lat":40.4168,"lon":-3.7038}},{"created":1791741478122,"modified":1791741478122,"name":"Calibration","perm":{"readOnly":["member"]},"property":"calibration","value":{"gain":1.02,"offset":-0.4}},{"created":1791741478122,"modified":1791741478122,"name":"Dashboard","property":"dashboard","value":{"source":"url","url":"/v1/users/alvarolb/storages/fleet_app/files/index.html?v=1"}}],"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListPluginProperties","tags":["Plugins"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"plugin","required":true,"schema":{"pattern":"^[a-zA-Z0-9_\\-\\:]{1,32}","type":"string"}}],"post":{"operationId":"Plugin_CreateProperty","requestBody":{"content":{"application/json":{"examples":{"Configuration value":{"value":{"description":"Sampling and alert thresholds","name":"Settings","property":"settings","type":"configuration","value":{"alerts":true,"interval":60,"max_temperature":28.5}}},"Location":{"value":{"name":"Location","property":"location","value":{"lat":40.4168,"lon":-3.7038}}},"Read-only for project members":{"value":{"name":"Calibration","perm":{"readOnly":["member"]},"property":"calibration","value":{"gain":1.02,"offset":-0.4}}},"Url dashboard of the resource":{"value":{"name":"Dashboard","property":"dashboard","value":{"source":"url","url":"/v1/users/alvarolb/storages/fleet_app/files/index.html?v=1"}}}},"schema":{"description":"A property is a JSON value stored on its resource (device, asset type, asset group, project, product, plugin or account). Devices inherit the properties of their asset type, asset group and product. 'type: configuration' marks values the device reads; 'perm' hides or locks a property for the account owner or project members. An array of these objects creates several at once.","oneOf":[{"items":{"$ref":"#/components/schemas/property_create"},"type":"array"},{"$ref":"#/components/schemas/property_create"}]}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CreatePluginProperty","tags":["Plugins"]}},"/v1/users/{user}/plugins/{plugin}/properties/{property}":{"delete":{"operationId":"Plugin_DeleteProperty","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeletePluginProperty","tags":["Plugins"]},"get":{"operationId":"Plugin_ReadProperty","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadPluginProperty","tags":["Plugins"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"plugin","required":true,"schema":{"pattern":"^[a-zA-Z0-9_\\-\\:]{1,32}","type":"string"}},{"in":"path","name":"property","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"patch":{"operationId":"Plugin_PatchProperty","requestBody":{"content":{"application/json":{"examples":{"Change some fields of the value":{"value":{"value":{"interval":30}}},"Flattened fields":{"value":{"value.alerts":false,"value.max_temperature":27}}},"schema":{"oneOf":[{"additionalProperties":false,"properties":{"value":{}},"required":["value"]},{"additionalProperties":false,"minProperties":1,"patternProperties":{"^value(\\.[^.]+)+$":{}}}],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdatePluginProperty","tags":["Plugins"]},"put":{"operationId":"Plugin_UpdateProperty","requestBody":{"content":{"application/json":{"examples":{"Hide from project members":{"value":{"perm":{"hidden":["member"]},"value":"internal note"}},"Replace the value":{"value":{"value":{"alerts":true,"interval":30,"max_temperature":27}}},"Value, name and description":{"value":{"description":"Faster sampling during commissioning","name":"Settings","value":{"alerts":false,"interval":10,"max_temperature":28.5}}}},"schema":{"$ref":"#/components/schemas/property_update"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdatePluginProperty","tags":["Plugins"]}},"/v1/users/{user}/plugins/{plugin}/properties/{property}/clone":{"get":{"operationId":"Plugin_ClonePropertyConfig","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ClonePluginPropertyConfig","tags":["Plugins"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"plugin","required":true,"schema":{"pattern":"^[a-zA-Z0-9_\\-\\:]{1,32}","type":"string"}},{"in":"path","name":"property","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Plugin_CloneProperty","requestBody":{"content":{"application/json":{"examples":{"Copy with a new id":{"value":{"property":"copy_of_property"}},"Copy with name and description":{"value":{"description":"Same configuration as the original, for production line 2","name":"Line 2 copy","property":"line_2_property"}}},"schema":{"additionalProperties":false,"properties":{"description":{"$ref":"#/components/schemas/resource_description"},"enabled":{"type":"boolean"},"name":{"$ref":"#/components/schemas/resource_name"},"property":{"$ref":"#/components/schemas/resource_id"}},"required":["property"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ClonePluginProperty","tags":["Plugins"]}},"/v1/users/{user}/plugins/{plugin}/terminal":{"get":{"operationId":"Plugin_RunCommandTerminal","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"RunPluginCommand","tags":["Plugins"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"plugin","required":true,"schema":{"pattern":"^[a-zA-Z0-9_\\-\\:]{1,32}","type":"string"}}]},"/v1/users/{user}/plugins/{plugin}/terminal/logs":{"get":{"operationId":"Plugin_ReadLogs","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadPluginLogs","tags":["Plugins"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"plugin","required":true,"schema":{"pattern":"^[a-zA-Z0-9_\\-\\:]{1,32}","type":"string"}}]},"/v1/users/{user}/plugins/{plugin}/terminal/shell":{"get":{"operationId":"Plugin_RunShell","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"RunPluginShell","tags":["Plugins"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"plugin","required":true,"schema":{"pattern":"^[a-zA-Z0-9_\\-\\:]{1,32}","type":"string"}}]},"/v1/users/{user}/products":{"get":{"operationId":"Product_List","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListProducts","tags":["Products"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Product_Create","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":false,"properties":{"config":{"$ref":"#/components/schemas/product_config"},"description":{"$ref":"#/components/schemas/resource_description"},"enabled":{"type":"boolean"},"name":{"$ref":"#/components/schemas/resource_name"},"product":{"$ref":"#/components/schemas/resource_id"},"profile":{"type":"object"},"services":{"type":"object"}},"required":["product","name"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CreateProduct","tags":["Products"]}},"/v1/users/{user}/products/{product}":{"delete":{"operationId":"Product_Delete","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteProduct","tags":["Products"]},"get":{"operationId":"Product_ReadConfig","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadProductConfig","tags":["Products"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"product","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"operationId":"Product_Update","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":false,"properties":{"config":{"$ref":"#/components/schemas/product_config"},"description":{"$ref":"#/components/schemas/resource_description"},"enabled":{"type":"boolean"},"name":{"$ref":"#/components/schemas/resource_name"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateProduct","tags":["Products"]}},"/v1/users/{user}/products/{product}/clone":{"get":{"operationId":"Product_CloneConfig","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneProductConfig","tags":["Products"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"product","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Product_Clone","requestBody":{"content":{"application/json":{"examples":{"Copy with a new id":{"value":{"product":"copy_of_product"}},"Copy with name and description":{"value":{"description":"Same configuration as the original, for production line 2","name":"Line 2 copy","product":"line_2_product"}}},"schema":{"additionalProperties":false,"properties":{"description":{"$ref":"#/components/schemas/resource_description"},"enabled":{"type":"boolean"},"name":{"$ref":"#/components/schemas/resource_name"},"product":{"$ref":"#/components/schemas/resource_id"}},"required":["product"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneProduct","tags":["Products"]}},"/v1/users/{user}/products/{product}/export":{"get":{"operationId":"Product_Export","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ExportProduct","tags":["Products"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"product","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v1/users/{user}/products/{product}/firmwares":{"get":{"operationId":"Product_ListFirmwares","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListProductFirmwares","tags":["Products"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"product","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Product_CreateFirmware","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":false,"properties":{"firmware":{"pattern":"^[a-zA-Z0-9_]{1,25}$","type":"string"},"name":{"maxLength":255,"type":"string"},"version":{"pattern":"(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)(?:-[\\da-z-]+(?:\\.[\\da-z-]+)*)?(?:\\+[\\da-z-]+(?:\\.[\\da-z-]+)*)?","type":"string"}},"required":["firmware","version"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CreateProductFirmware","tags":["Products"]}},"/v1/users/{user}/products/{product}/firmwares/{firmware}/{firmware_version}":{"delete":{"operationId":"Product_DeleteFirmware","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteProductFirmware","tags":["Products"]},"get":{"operationId":"Product_ReadFirmwareConfig","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadProductFirmwareConfig","tags":["Products"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"product","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"firmware","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"firmware_version","required":true,"schema":{"pattern":"^(?:0|[1-9]\\d*\\.(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)(?:-[\\da-z-]+(?:\\.[\\da-z-]+)*)?(?:\\+[\\da-z-]+(?:\\.[\\da-z-]+)*)?)","type":"string"}}],"put":{"operationId":"Product_UpdateFirmware","requestBody":{"content":{"application/json":{"schema":{"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateProductFirmware","tags":["Products"],"x-internal":true}},"/v1/users/{user}/products/{product}/firmwares/{firmware}/{firmware_version}/flash":{"get":{"operationId":"Product_FlashFirmware","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"FlashProductFirmware","tags":["Products"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"product","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"firmware","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"firmware_version","required":true,"schema":{"pattern":"^(?:0|[1-9]\\d*\\.(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)(?:-[\\da-z-]+(?:\\.[\\da-z-]+)*)?(?:\\+[\\da-z-]+(?:\\.[\\da-z-]+)*)?)","type":"string"}}]},"/v1/users/{user}/products/{product}/firmwares/{firmware}/{firmware_version}/stream":{"get":{"operationId":"Product_UpdateFirmwareStream","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateProductFirmware","tags":["Products"],"x-internal":true},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"product","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"firmware","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"firmware_version","required":true,"schema":{"pattern":"^(?:0|[1-9]\\d*\\.(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)(?:-[\\da-z-]+(?:\\.[\\da-z-]+)*)?(?:\\+[\\da-z-]+(?:\\.[\\da-z-]+)*)?)","type":"string"}}]},"/v1/users/{user}/products/{product}/firmwares/{firmware}/{firmware_version}/toolchain":{"get":{"operationId":"Product_UpdateFirmwareToolchain","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateProductFirmware","tags":["Products"],"x-internal":true},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"product","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"firmware","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"firmware_version","required":true,"schema":{"pattern":"^(?:0|[1-9]\\d*\\.(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)(?:-[\\da-z-]+(?:\\.[\\da-z-]+)*)?(?:\\+[\\da-z-]+(?:\\.[\\da-z-]+)*)?)","type":"string"}}]},"/v1/users/{user}/products/{product}/profile/code":{"get":{"operationId":"Product_ReadProfileCode","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadProductProfile","tags":["Products"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"product","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"operationId":"Product_UpdateProfileCode","requestBody":{"content":{"application/json":{"examples":{"Code from a file storage":{"value":{"storage":"meter_product_code"}},"Code from a folder of an application storage":{"value":{"path":"code/meter","storage":"fleet_app"}},"Inline code":{"value":{"code":"function resolveDevice(payload) {\n // device id from the serial sent by the caller\n return 'meter_' + payload.serial;\n}\n\nfunction toCelsius(payload) {\n return { temperature: (payload.temperature_f - 32) * 5 / 9 };\n}\n"}}},"schema":{"$ref":"#/components/schemas/product_profile_code"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateProductProfile","tags":["Products"]}},"/v1/users/{user}/products/{product}/profile/console":{"get":{"operationId":"Product_ReadProfileConsole","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadProductProfile","tags":["Products"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"product","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v1/users/{user}/products/{product}/profile/{category}":{"get":{"operationId":"Product_ReadProfile","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadProductProfile","tags":["Products"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"product","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"category","required":true,"schema":{"pattern":"^properties|buckets|flows|endpoints|api|autoprovisions","type":"string"}}],"put":{"description":"Replace every entry of a profile category. Entries missing from the body are removed; to change one entry use PUT .../profile/{category}/{resource}.","operationId":"Product_UpdateProfile","requestBody":{"content":{"application/json":{"examples":{"All buckets of the product, one of them per device (PUT \u2026/profile/buckets)":{"value":{"telemetry":{"data":{"interval":60,"magnitude":"second","payload_type":"source_payload","resource":"telemetry","source":"resource","update":"interval"},"description":"One shared bucket, tagged with each device","enabled":true,"name":"Telemetry","retention":{"period":6,"unit":"months"}},"{{device}}_readings":{"data":{"payload_type":"source_payload","source":"topic","topic":"plant/{{line}}/{{device}}/{{field}}"},"enabled":true,"name":"Readings","tags":["line"]}}},"Remove every flow (PUT \u2026/profile/flows)":{"value":{}}},"schema":{"$ref":"#/components/schemas/product_profile_category"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateProductProfile","tags":["Products"]}},"/v1/users/{user}/products/{product}/profile/{category}/{resource}":{"delete":{"operationId":"Product_DeleteProductProfileResource","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateProductProfile","tags":["Products"]},"get":{"operationId":"Product_ReadProductProfileResource","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadProductProfile","tags":["Products"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"product","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"category","required":true,"schema":{"pattern":"^properties|buckets|flows|endpoints|api|autoprovisions","type":"string"}},{"in":"path","name":"resource","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"description":"Create or replace one entry of a profile category (properties, buckets, flows, api, autoprovisions; endpoints is deprecated). The product is reinitialized, so the change applies at once to its devices.","operationId":"Product_UpdateProductProfileResource","requestBody":{"content":{"application/json":{"examples":{"API resource that calls an endpoint (PUT \u2026/profile/api/notify)":{"value":{"description":"Sends a notification from the device","enabled":true,"name":"Notify","request":{"data":{"endpoint":"notify_email","payload":"{\"device\": \"{{device}}\", \"message\": \"{{payload.message}}\"}","payload_type":"template_payload","target":"endpoint_call"}},"response":{"data":{"source":"request_response"}}}},"API resource to configure a device by serial, with device_id_resolver (PUT \u2026/profile/api/configure)":{"value":{"device_id_resolver":"resolveDevice","enabled":true,"name":"Configure","request":{"data":{"payload":"{{payload.settings}}","property":"settings","target":"property"}},"response":{"data":{"source":"request_response"}}}},"Autoprovision devices by id pattern (PUT \u2026/profile/autoprovisions/meters)":{"value":{"config":{"group":"plant_a","mode":"pattern","pattern":"^meter_[0-9]{6}$","type":"meter"},"description":"Creates meter_XXXXXX devices on their first connection","enabled":true,"name":"Meters"}},"Bucket fed from a device resource every 60 s (PUT \u2026/profile/buckets/telemetry)":{"value":{"data":{"interval":60,"magnitude":"second","payload_type":"source_payload","resource":"telemetry","source":"resource","update":"interval"},"description":"One shared bucket, tagged with each device","enabled":true,"name":"Telemetry","retention":{"period":6,"unit":"months"}}},"Bucket from MQTT topics with tags (PUT \u2026/profile/buckets/readings)":{"value":{"data":{"payload_type":"source_payload","source":"topic","topic":"plant/{{line}}/{{device}}/{{field}}"},"enabled":true,"name":"Readings","tags":["line"]}},"Configuration property with a default (PUT \u2026/profile/properties/settings)":{"value":{"default":{"value":{"report_interval":60,"threshold":25.5}},"enabled":true,"name":"Settings","perm":{"hidden":false,"readOnly":"member"},"type":"configuration"}},"Flow: email when a device disconnects (PUT \u2026/profile/flows/offline_alert)":{"value":{"data":{"event":"device_state_change","filter":{"state":"disconnected"},"payload_type":"source_event","source":"event"},"enabled":true,"name":"Offline alert","sink":{"endpoint":"notify_email","payload":"{\"text\": \"{{device}} is offline\"}","target":"endpoint_call"}}},"Property set from an MQTT topic (PUT \u2026/profile/properties/status)":{"value":{"data":{"payload_type":"source_payload","source":"topic","topic":"devices/{{device}}/status"},"default":{"value":{"state":"unknown"}},"description":"Last status message","enabled":true,"name":"Status"}}},"schema":{"$ref":"#/components/schemas/product_profile_entry"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateProductProfile","tags":["Products"]}},"/v1/users/{user}/products/{product}/projects":{"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"product","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"operationId":"Product_UpdateProjects","requestBody":{"content":{"application/json":{"examples":{"No projects":{"value":[]},"One project":{"value":["alvarolb@greenhouse"]},"Two projects":{"value":["alvarolb@greenhouse","alvarolb@maintenance"]}},"schema":{"description":"Projects the resource belongs to, as <owner>@<project> ids. Replaces the whole list: read the current one first to add or remove a single project; [] removes it from every project.","items":{"pattern":"^[a-zA-Z0-9_]{1,32}@[a-zA-Z0-9_]{1,32}$","type":"string"},"type":"array"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateProductProjects","tags":["Products"]}},"/v1/users/{user}/products/{product}/properties":{"get":{"operationId":"Product_ListProperties","responses":{"200":{"content":{"application/json":{"example":[{"created":1791741478028,"description":"Sampling and alert thresholds","modified":1791741478028,"name":"Settings","property":"settings","type":"configuration","value":{"alerts":true,"interval":60,"max_temperature":28.5}},{"created":1791741478028,"modified":1791741478028,"name":"Location","property":"location","value":{"lat":40.4168,"lon":-3.7038}},{"created":1791741478028,"modified":1791741478028,"name":"Calibration","perm":{"readOnly":["member"]},"property":"calibration","value":{"gain":1.02,"offset":-0.4}},{"created":1791741478028,"modified":1791741478028,"name":"Dashboard","property":"dashboard","value":{"source":"url","url":"/v1/users/alvarolb/storages/fleet_app/files/index.html?v=1"}}],"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListProductProperties","tags":["Products"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"product","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Product_CreateProperty","requestBody":{"content":{"application/json":{"examples":{"Configuration value":{"value":{"description":"Sampling and alert thresholds","name":"Settings","property":"settings","type":"configuration","value":{"alerts":true,"interval":60,"max_temperature":28.5}}},"Location":{"value":{"name":"Location","property":"location","value":{"lat":40.4168,"lon":-3.7038}}},"Read-only for project members":{"value":{"name":"Calibration","perm":{"readOnly":["member"]},"property":"calibration","value":{"gain":1.02,"offset":-0.4}}},"Url dashboard of the resource":{"value":{"name":"Dashboard","property":"dashboard","value":{"source":"url","url":"/v1/users/alvarolb/storages/fleet_app/files/index.html?v=1"}}}},"schema":{"description":"A property is a JSON value stored on its resource (device, asset type, asset group, project, product, plugin or account). Devices inherit the properties of their asset type, asset group and product. 'type: configuration' marks values the device reads; 'perm' hides or locks a property for the account owner or project members. An array of these objects creates several at once.","oneOf":[{"items":{"$ref":"#/components/schemas/property_create"},"type":"array"},{"$ref":"#/components/schemas/property_create"}]}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CreateProductProperty","tags":["Products"]}},"/v1/users/{user}/products/{product}/properties/{property}":{"delete":{"operationId":"Product_DeleteProperty","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteProductProperty","tags":["Products"]},"get":{"operationId":"Product_ReadProperty","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadProductProperty","tags":["Products"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"product","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"property","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"patch":{"operationId":"Product_PatchProperty","requestBody":{"content":{"application/json":{"examples":{"Change some fields of the value":{"value":{"value":{"interval":30}}},"Flattened fields":{"value":{"value.alerts":false,"value.max_temperature":27}}},"schema":{"oneOf":[{"additionalProperties":false,"properties":{"value":{}},"required":["value"]},{"additionalProperties":false,"minProperties":1,"patternProperties":{"^value(\\.[^.]+)+$":{}}}],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateProductProperty","tags":["Products"]},"put":{"operationId":"Product_UpdateProperty","requestBody":{"content":{"application/json":{"examples":{"Hide from project members":{"value":{"perm":{"hidden":["member"]},"value":"internal note"}},"Replace the value":{"value":{"value":{"alerts":true,"interval":30,"max_temperature":27}}},"Value, name and description":{"value":{"description":"Faster sampling during commissioning","name":"Settings","value":{"alerts":false,"interval":10,"max_temperature":28.5}}}},"schema":{"$ref":"#/components/schemas/property_update"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateProductProperty","tags":["Products"]}},"/v1/users/{user}/products/{product}/properties/{property}/clone":{"get":{"operationId":"Product_ClonePropertyConfig","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneProductPropertyConfig","tags":["Products"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"product","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"property","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Product_CloneProperty","requestBody":{"content":{"application/json":{"examples":{"Copy with a new id":{"value":{"property":"copy_of_property"}},"Copy with name and description":{"value":{"description":"Same configuration as the original, for production line 2","name":"Line 2 copy","property":"line_2_property"}}},"schema":{"additionalProperties":false,"properties":{"description":{"$ref":"#/components/schemas/resource_description"},"enabled":{"type":"boolean"},"name":{"$ref":"#/components/schemas/resource_name"},"property":{"$ref":"#/components/schemas/resource_id"}},"required":["property"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneProductProperty","tags":["Products"]}},"/v1/users/{user}/products/{product}/resources/{resource}":{"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"product","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"resource","required":true,"schema":{"pattern":"^(?:.{1,32}\\/?+)","type":"string"}}],"post":{"description":"Call an API resource of the product (profile api) without naming a device. The body is free (any JSON, or an array to call it once per element) and is the {{payload}} of the resource. A device is only reached when the resource defines device_id_resolver, a product code function that returns the device id from the payload.","operationId":"Product_AccessResources","requestBody":{"content":{"application/json":{"schema":{"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"AccessProductResources","tags":["Products"]}},"/v1/users/{user}/products/{product}/services":{"get":{"operationId":"Product_ReadServices","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadProductServices","tags":["Products"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"product","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v1/users/{user}/products/{product}/services/{service}":{"delete":{"operationId":"Product_DeleteServices","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteProductServices","tags":["Products"]},"get":{"operationId":"Product_ReadServices","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadProductServices","tags":["Products"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"product","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"service","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"operationId":"Product_UpdateServices","requestBody":{"content":{"application/json":{"examples":{"Remote desktop (PUT \u2026/services/desktop)":{"value":{"enabled":true,"name":"Desktop","target":{"address":"127.0.0.1","port":5900},"type":"vnc","vnc":{"compression":2,"quality":6,"scale":true,"shared":true,"viewonly":false}}},"Web interface of the device (PUT \u2026/services/web_ui)":{"value":{"description":"Device configuration page","enabled":true,"name":"Web UI","security":{"ip_filtering":false,"timeout_minutes":60},"target":{"address":"127.0.0.1","port":8080,"secure":false},"type":"web"}}},"schema":{"$ref":"#/components/schemas/product_service"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateProductServices","tags":["Products"]}},"/v1/users/{user}/profile":{"get":{"operationId":"User_ReadProfile","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadUserProfile","tags":["Users"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"operationId":"User_UpdateProfile","requestBody":{"content":{"application/json":{"examples":{"Public profile":{"value":{"company":"Acme Farms","location":"Madrid, Spain","name":"Jane Doe","url":"https://acme.example"}}},"schema":{"additionalProperties":false,"properties":{"company":{"maxLength":255,"minLength":0,"type":"string"},"location":{"maxLength":255,"minLength":0,"type":"string"},"name":{"maxLength":255,"minLength":0,"type":"string"},"picture":{"maxLength":50000,"pattern":"^$|^data:image/(?:png|jpeg|webp);base64,(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$","type":"string"},"url":{"maxLength":255,"minLength":0,"type":"string"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateUserProfile","tags":["Users"]}},"/v1/users/{user}/projects":{"get":{"operationId":"Project_List","responses":{"200":{"content":{"application/json":{"example":[{"created":1791741476399,"description":"Description","modified":1791741476399,"name":"Project","project":"project"}],"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListProjects","tags":["Projects"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Project_Create","requestBody":{"content":{"application/json":{"examples":{"Create Project":{"description":"Creates a new project.","value":{"description":"Description","name":"Project","project":"project"}}},"schema":{"additionalProperties":false,"properties":{"config":{"properties":{"limit_bucket_access":{"type":"boolean"}},"type":"object"},"description":{"$ref":"#/components/schemas/resource_description"},"name":{"$ref":"#/components/schemas/resource_name"},"project":{"$ref":"#/components/schemas/resource_id"}},"required":["project","name"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CreateProject","tags":["Projects"]}},"/v1/users/{user}/projects/{project}":{"delete":{"operationId":"Project_Delete","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteProject","tags":["Projects"]},"get":{"operationId":"Project_ReadConfig","responses":{"200":{"content":{"application/json":{"examples":{"Create Project":{"description":"Creates a new project.","value":{"created":1791741476399,"description":"Description","modified":1791741476399,"name":"Project","project":"project"}}},"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadProjectConfig","tags":["Projects"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"project","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"operationId":"Project_Update","requestBody":{"content":{"application/json":{"examples":{"Full Update":{"value":{"description":"Description","name":"Project","project":"project"}},"Update 'description'":{"value":{"description":"Description"}},"Update 'name'":{"value":{"name":"Project"}}},"schema":{"additionalProperties":false,"properties":{"config":{"properties":{"limit_bucket_access":{"type":"boolean"}},"type":"object"},"description":{"$ref":"#/components/schemas/resource_description"},"name":{"$ref":"#/components/schemas/resource_name"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateProject","tags":["Projects"]}},"/v1/users/{user}/projects/{project}/clone":{"get":{"operationId":"Project_CloneConfig","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneProjectConfig","tags":["Projects"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"project","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Project_Clone","requestBody":{"content":{"application/json":{"examples":{"Copy with a new id":{"value":{"project":"copy_of_project"}},"Copy with name and description":{"value":{"description":"Same configuration as the original, for production line 2","name":"Line 2 copy","project":"line_2_project"}}},"schema":{"additionalProperties":false,"properties":{"description":{"$ref":"#/components/schemas/resource_description"},"enabled":{"type":"boolean"},"name":{"$ref":"#/components/schemas/resource_name"},"project":{"$ref":"#/components/schemas/resource_id"}},"required":["project"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneProject","tags":["Projects"]}},"/v1/users/{user}/projects/{project}/members":{"get":{"operationId":"Project_ListMembers","responses":{"200":{"content":{"application/json":{"example":[{"created":1791741476400,"enabled":true,"member":"jane","modified":1791741476400},{"created":1791741476400,"enabled":true,"member":"tech_madrid","modified":1791741476400},{"created":1791741476400,"enabled":true,"member":"acme_viewer","modified":1791741476400}],"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListProjectMembers","tags":["Projects"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"project","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Project_CreateMember","requestBody":{"content":{"application/json":{"examples":{"Existing account with a role":{"value":{"enabled":true,"member":"jane","roles":["operator"]}},"Limited to a site":{"value":{"enabled":true,"groups":["madrid_plant"],"hide_menu":true,"member":"tech_madrid","roles":["operator"]}},"New account":{"value":{"account":{"email":"viewer@acme.example","password":"a-long-random-password"},"enabled":true,"member":"acme_viewer","roles":["viewer"]}}},"schema":{"additionalProperties":false,"description":"Shares the project with an account (member = its username). Effective permissions: its own allow / deny plus its project roles and global roles. 'groups' limits it to devices of those asset groups. With 'account' the server first creates that account (verified, role member, this project as default).","properties":{"account":{"properties":{"email":{"format":"email","type":"string"},"password":{"type":"string"}},"type":"object"},"allow":{"$ref":"#/components/schemas/permission"},"deny":{"$ref":"#/components/schemas/permission"},"enabled":{"type":"boolean"},"global_roles":{"items":{"$ref":"#/components/schemas/resource_id"},"maxItems":10,"type":"array"},"groups":{"items":{"$ref":"#/components/schemas/resource_id"},"maxItems":10,"type":"array"},"hide_menu":{"type":"boolean"},"member":{"$ref":"#/components/schemas/resource_id"},"roles":{"items":{"$ref":"#/components/schemas/resource_id"},"maxItems":10,"type":"array"}},"required":["member","enabled"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CreateProjectMember","tags":["Projects"]}},"/v1/users/{user}/projects/{project}/members/{member}":{"delete":{"operationId":"Project_DeleteMember","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteProjectMember","tags":["Projects"]},"get":{"operationId":"Project_ReadMemberConfig","responses":{"200":{"content":{"application/json":{"examples":{"Existing account with a role":{"value":{"created":1791741476400,"enabled":true,"member":"jane","modified":1791741476400,"roles":["operator"]}},"Limited to a site":{"value":{"created":1791741476400,"enabled":true,"groups":["madrid_plant"],"hide_menu":true,"member":"tech_madrid","modified":1791741476400,"roles":["operator"]}},"New account":{"value":{"account":{"email":"viewer@acme.example","password":"a-long-random-password"},"created":1791741476400,"enabled":true,"member":"acme_viewer","modified":1791741476400,"roles":["viewer"]}}},"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadProjectMemberConfig","tags":["Projects"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"project","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"member","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"operationId":"Project_UpdateMember","requestBody":{"content":{"application/json":{"examples":{"Change roles":{"value":{"roles":["viewer"]}},"Suspend":{"value":{"enabled":false}}},"schema":{"additionalProperties":false,"properties":{"allow":{"$ref":"#/components/schemas/permission"},"deny":{"$ref":"#/components/schemas/permission"},"enabled":{"type":"boolean"},"global_roles":{"items":{"$ref":"#/components/schemas/resource_id"},"maxItems":10,"type":"array"},"groups":{"items":{"$ref":"#/components/schemas/resource_id"},"maxItems":10,"type":"array"},"hide_menu":{"type":"boolean"},"roles":{"items":{"$ref":"#/components/schemas/resource_id"},"maxItems":10,"type":"array"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateProjectMember","tags":["Projects"]}},"/v1/users/{user}/projects/{project}/properties":{"get":{"operationId":"Project_ListProperties","responses":{"200":{"content":{"application/json":{"example":[{"created":1791741476399,"description":"Sampling and alert thresholds","modified":1791741476399,"name":"Settings","property":"settings","type":"configuration","value":{"alerts":true,"interval":60,"max_temperature":28.5}},{"created":1791741476399,"modified":1791741476399,"name":"Location","property":"location","value":{"lat":40.4168,"lon":-3.7038}},{"created":1791741476399,"modified":1791741476399,"name":"Calibration","perm":{"readOnly":["member"]},"property":"calibration","value":{"gain":1.02,"offset":-0.4}},{"created":1791741476399,"modified":1791741476399,"name":"Dashboard","property":"dashboard","value":{"source":"url","url":"/v1/users/alvarolb/storages/fleet_app/files/index.html?v=1"}}],"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListProjectProperties","tags":["Projects"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"project","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Project_CreateProperty","requestBody":{"content":{"application/json":{"examples":{"Configuration value":{"value":{"description":"Sampling and alert thresholds","name":"Settings","property":"settings","type":"configuration","value":{"alerts":true,"interval":60,"max_temperature":28.5}}},"Location":{"value":{"name":"Location","property":"location","value":{"lat":40.4168,"lon":-3.7038}}},"Read-only for project members":{"value":{"name":"Calibration","perm":{"readOnly":["member"]},"property":"calibration","value":{"gain":1.02,"offset":-0.4}}},"Url dashboard of the resource":{"value":{"name":"Dashboard","property":"dashboard","value":{"source":"url","url":"/v1/users/alvarolb/storages/fleet_app/files/index.html?v=1"}}}},"schema":{"description":"A property is a JSON value stored on its resource (device, asset type, asset group, project, product, plugin or account). Devices inherit the properties of their asset type, asset group and product. 'type: configuration' marks values the device reads; 'perm' hides or locks a property for the account owner or project members. An array of these objects creates several at once.","oneOf":[{"items":{"$ref":"#/components/schemas/property_create"},"type":"array"},{"$ref":"#/components/schemas/property_create"}]}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CreateProjectProperty","tags":["Projects"]}},"/v1/users/{user}/projects/{project}/properties/{property}":{"delete":{"operationId":"Project_DeleteProperty","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteProjectProperty","tags":["Projects"]},"get":{"operationId":"Project_ReadProperty","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadProjectProperty","tags":["Projects"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"project","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"property","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"patch":{"operationId":"Project_PatchProperty","requestBody":{"content":{"application/json":{"examples":{"Change some fields of the value":{"value":{"value":{"interval":30}}},"Flattened fields":{"value":{"value.alerts":false,"value.max_temperature":27}}},"schema":{"oneOf":[{"additionalProperties":false,"properties":{"value":{}},"required":["value"]},{"additionalProperties":false,"minProperties":1,"patternProperties":{"^value(\\.[^.]+)+$":{}}}],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateProjectProperty","tags":["Projects"]},"put":{"operationId":"Project_UpdateProperty","requestBody":{"content":{"application/json":{"examples":{"Hide from project members":{"value":{"perm":{"hidden":["member"]},"value":"internal note"}},"Replace the value":{"value":{"value":{"alerts":true,"interval":30,"max_temperature":27}}},"Value, name and description":{"value":{"description":"Faster sampling during commissioning","name":"Settings","value":{"alerts":false,"interval":10,"max_temperature":28.5}}}},"schema":{"$ref":"#/components/schemas/property_update"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateProjectProperty","tags":["Projects"]}},"/v1/users/{user}/projects/{project}/properties/{property}/clone":{"get":{"operationId":"Project_ClonePropertyConfig","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneProjectPropertyConfig","tags":["Projects"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"project","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"property","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Project_CloneProperty","requestBody":{"content":{"application/json":{"examples":{"Copy with a new id":{"value":{"property":"copy_of_property"}},"Copy with name and description":{"value":{"description":"Same configuration as the original, for production line 2","name":"Line 2 copy","property":"line_2_property"}}},"schema":{"additionalProperties":false,"properties":{"description":{"$ref":"#/components/schemas/resource_description"},"enabled":{"type":"boolean"},"name":{"$ref":"#/components/schemas/resource_name"},"property":{"$ref":"#/components/schemas/resource_id"}},"required":["property"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneProjectProperty","tags":["Projects"]}},"/v1/users/{user}/projects/{project}/roles":{"get":{"operationId":"Project_ListRoles","responses":{"200":{"content":{"application/json":{"example":[{"allow":{"Alarm":{"*":["List*","Read*","UpdateAlarmInstance"]},"Bucket":{"*":["List*","Read*"]},"Dashboard":{"*":["List*","Read*"]},"Device":{"*":["List*","Read*","AccessDeviceResources"]}},"created":1791741476400,"enabled":true,"modified":1791741476400,"role":"operator"},{"allow":{"Bucket":{"*":["List*","Read*"]},"Dashboard":{"*":["List*","Read*"]},"Device":{"*":["List*","Read*"]}},"created":1791741476400,"enabled":true,"modified":1791741476400,"role":"viewer"}],"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListProjectRoles","tags":["Projects"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"project","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Project_CreateRole","requestBody":{"content":{"application/json":{"examples":{"Operator":{"value":{"allow":{"Alarm":{"*":["List*","Read*","UpdateAlarmInstance"]},"Bucket":{"*":["List*","Read*"]},"Dashboard":{"*":["List*","Read*"]},"Device":{"*":["List*","Read*","AccessDeviceResources"]}},"enabled":true,"role":"operator"}},"Viewer":{"value":{"allow":{"Bucket":{"*":["List*","Read*"]},"Dashboard":{"*":["List*","Read*"]},"Device":{"*":["List*","Read*"]}},"enabled":true,"role":"viewer"}}},"schema":{"additionalProperties":false,"description":"A project role is a named set of permissions for members of this project (members.roles). Permissions: {<resource type>: {<resource id or *>: action | [actions]}}; actions accept a trailing * (Read*, List*).","properties":{"allow":{"$ref":"#/components/schemas/permission"},"deny":{"$ref":"#/components/schemas/permission"},"enabled":{"type":"boolean"},"role":{"$ref":"#/components/schemas/resource_id"}},"required":["role","enabled"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CreateProjectRole","tags":["Projects"]}},"/v1/users/{user}/projects/{project}/roles/{role}":{"delete":{"operationId":"Project_DeleteRole","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteProjectRole","tags":["Projects"]},"get":{"operationId":"Project_ReadRoleConfig","responses":{"200":{"content":{"application/json":{"examples":{"Operator":{"value":{"allow":{"Alarm":{"*":["List*","Read*","UpdateAlarmInstance"]},"Bucket":{"*":["List*","Read*"]},"Dashboard":{"*":["List*","Read*"]},"Device":{"*":["List*","Read*","AccessDeviceResources"]}},"created":1791741476400,"enabled":true,"modified":1791741476400,"role":"operator"}},"Viewer":{"value":{"allow":{"Bucket":{"*":["List*","Read*"]},"Dashboard":{"*":["List*","Read*"]},"Device":{"*":["List*","Read*"]}},"created":1791741476400,"enabled":true,"modified":1791741476400,"role":"viewer"}}},"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadProjectRoleConfig","tags":["Projects"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"project","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"role","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"operationId":"Project_UpdateRole","requestBody":{"content":{"application/json":{"examples":{"Disable the role":{"value":{"enabled":false}},"Replace its permissions":{"value":{"allow":{"Dashboard":{"*":["List*","Read*"]},"Device":{"*":["List*","Read*"]}}}}},"schema":{"additionalProperties":false,"properties":{"allow":{"$ref":"#/components/schemas/permission"},"deny":{"$ref":"#/components/schemas/permission"},"enabled":{"type":"boolean"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateProjectRole","tags":["Projects"]}},"/v1/users/{user}/projects/{project}/roles/{role}/clone":{"get":{"operationId":"Project_CloneRoleConfig","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneProjectRoleConfig","tags":["Projects"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"project","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"role","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Project_CloneRole","requestBody":{"content":{"application/json":{"examples":{"Copy with a new id":{"value":{"role":"copy_of_role"}},"Copy with name and description":{"value":{"description":"Same configuration as the original, for production line 2","name":"Line 2 copy","role":"line_2_role"}}},"schema":{"additionalProperties":false,"properties":{"description":{"$ref":"#/components/schemas/resource_description"},"enabled":{"type":"boolean"},"name":{"$ref":"#/components/schemas/resource_name"},"role":{"$ref":"#/components/schemas/resource_id"}},"required":["role"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneProjectRole","tags":["Projects"]}},"/v1/users/{user}/properties":{"get":{"operationId":"Property_ListProperties","responses":{"200":{"content":{"application/json":{"example":[{"created":1791741478035,"description":"Sampling and alert thresholds","modified":1791741478035,"name":"Settings","property":"settings","type":"configuration","value":{"alerts":true,"interval":60,"max_temperature":28.5}},{"created":1791741478035,"modified":1791741478035,"name":"Location","property":"location","value":{"lat":40.4168,"lon":-3.7038}},{"created":1791741478035,"modified":1791741478035,"name":"Calibration","perm":{"readOnly":["member"]},"property":"calibration","value":{"gain":1.02,"offset":-0.4}},{"created":1791741478035,"modified":1791741478035,"name":"Dashboard","property":"dashboard","value":{"source":"url","url":"/v1/users/alvarolb/storages/fleet_app/files/index.html?v=1"}}],"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListProperties","tags":["Properties"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Property_Create","requestBody":{"content":{"application/json":{"examples":{"Configuration value":{"value":{"description":"Sampling and alert thresholds","name":"Settings","property":"settings","type":"configuration","value":{"alerts":true,"interval":60,"max_temperature":28.5}}},"Location":{"value":{"name":"Location","property":"location","value":{"lat":40.4168,"lon":-3.7038}}},"Read-only for project members":{"value":{"name":"Calibration","perm":{"readOnly":["member"]},"property":"calibration","value":{"gain":1.02,"offset":-0.4}}},"Url dashboard of the resource":{"value":{"name":"Dashboard","property":"dashboard","value":{"source":"url","url":"/v1/users/alvarolb/storages/fleet_app/files/index.html?v=1"}}}},"schema":{"description":"A property is a JSON value stored on its resource (device, asset type, asset group, project, product, plugin or account). Devices inherit the properties of their asset type, asset group and product. 'type: configuration' marks values the device reads; 'perm' hides or locks a property for the account owner or project members. An array of these objects creates several at once.","oneOf":[{"items":{"$ref":"#/components/schemas/property_create"},"type":"array"},{"$ref":"#/components/schemas/property_create"}]}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CreateProperty","tags":["Properties"]}},"/v1/users/{user}/properties/{property}":{"delete":{"operationId":"Property_Delete","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteProperty","tags":["Properties"]},"get":{"operationId":"Property_Read","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadProperty","tags":["Properties"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"property","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"patch":{"operationId":"Property_Patch","requestBody":{"content":{"application/json":{"examples":{"Change some fields of the value":{"value":{"value":{"interval":30}}},"Flattened fields":{"value":{"value.alerts":false,"value.max_temperature":27}}},"schema":{"oneOf":[{"additionalProperties":false,"properties":{"value":{}},"required":["value"]},{"additionalProperties":false,"minProperties":1,"patternProperties":{"^value(\\.[^.]+)+$":{}}}],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateProperty","tags":["Properties"]},"put":{"operationId":"Property_Update","requestBody":{"content":{"application/json":{"examples":{"Hide from project members":{"value":{"perm":{"hidden":["member"]},"value":"internal note"}},"Replace the value":{"value":{"value":{"alerts":true,"interval":30,"max_temperature":27}}},"Value, name and description":{"value":{"description":"Faster sampling during commissioning","name":"Settings","value":{"alerts":false,"interval":10,"max_temperature":28.5}}}},"schema":{"$ref":"#/components/schemas/property_update"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateProperty","tags":["Properties"]}},"/v1/users/{user}/properties/{property}/clone":{"get":{"operationId":"Property_CloneConfig","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ClonePropertyConfig","tags":["Properties"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"property","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Property_Clone","requestBody":{"content":{"application/json":{"examples":{"Copy with a new id":{"value":{"property":"copy_of_property"}},"Copy with name and description":{"value":{"description":"Same configuration as the original, for production line 2","name":"Line 2 copy","property":"line_2_property"}}},"schema":{"additionalProperties":false,"properties":{"description":{"$ref":"#/components/schemas/resource_description"},"enabled":{"type":"boolean"},"name":{"$ref":"#/components/schemas/resource_name"},"property":{"$ref":"#/components/schemas/resource_id"}},"required":["property"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneProperty","tags":["Properties"]}},"/v1/users/{user}/roles":{"get":{"operationId":"Role_List","responses":{"200":{"content":{"application/json":{"example":[{"allow":{"Alarm":{"*":["List*","Read*","UpdateAlarmInstance"]},"Bucket":{"*":["List*","Read*"]},"Dashboard":{"*":["List*","Read*"]},"Device":{"*":["List*","Read*","AccessDeviceResources"]}},"created":1791741476401,"enabled":true,"modified":1791741476401,"role":"operator"},{"allow":{"Bucket":{"*":["List*","Read*"]},"Dashboard":{"*":["List*","Read*"]},"Device":{"*":["List*","Read*"]}},"created":1791741476401,"enabled":true,"modified":1791741476401,"role":"viewer"}],"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListRoles","tags":["Roles"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Role_Create","requestBody":{"content":{"application/json":{"examples":{"Operator":{"value":{"allow":{"Alarm":{"*":["List*","Read*","UpdateAlarmInstance"]},"Bucket":{"*":["List*","Read*"]},"Dashboard":{"*":["List*","Read*"]},"Device":{"*":["List*","Read*","AccessDeviceResources"]}},"enabled":true,"role":"operator"}},"Viewer":{"value":{"allow":{"Bucket":{"*":["List*","Read*"]},"Dashboard":{"*":["List*","Read*"]},"Device":{"*":["List*","Read*"]}},"enabled":true,"role":"viewer"}}},"schema":{"additionalProperties":false,"description":"A global role is a named set of permissions of the account, reusable by members of any of its projects (members.global_roles). Permissions: {<resource type>: {<resource id or *>: action | [actions]}}; actions accept a trailing * (Read*, List*).","properties":{"allow":{"$ref":"#/components/schemas/permission"},"deny":{"$ref":"#/components/schemas/permission"},"enabled":{"type":"boolean"},"role":{"$ref":"#/components/schemas/resource_id"}},"required":["role","enabled"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CreateRole","tags":["Roles"]}},"/v1/users/{user}/roles/{role}":{"delete":{"operationId":"Role_Delete","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteRole","tags":["Roles"]},"get":{"operationId":"Role_ReadConfig","responses":{"200":{"content":{"application/json":{"examples":{"Operator":{"value":{"allow":{"Alarm":{"*":["List*","Read*","UpdateAlarmInstance"]},"Bucket":{"*":["List*","Read*"]},"Dashboard":{"*":["List*","Read*"]},"Device":{"*":["List*","Read*","AccessDeviceResources"]}},"created":1791741476401,"enabled":true,"modified":1791741476401,"role":"operator"}},"Viewer":{"value":{"allow":{"Bucket":{"*":["List*","Read*"]},"Dashboard":{"*":["List*","Read*"]},"Device":{"*":["List*","Read*"]}},"created":1791741476401,"enabled":true,"modified":1791741476401,"role":"viewer"}}},"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadRoleConfig","tags":["Roles"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"role","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"operationId":"Role_Update","requestBody":{"content":{"application/json":{"examples":{"Disable the role":{"value":{"enabled":false}},"Replace its permissions":{"value":{"allow":{"Dashboard":{"*":["List*","Read*"]},"Device":{"*":["List*","Read*"]}}}}},"schema":{"additionalProperties":false,"properties":{"allow":{"$ref":"#/components/schemas/permission"},"deny":{"$ref":"#/components/schemas/permission"},"enabled":{"type":"boolean"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateRole","tags":["Roles"]}},"/v1/users/{user}/roles/{role}/clone":{"get":{"operationId":"Role_CloneConfig","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneRoleConfig","tags":["Roles"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"role","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Role_Clone","requestBody":{"content":{"application/json":{"examples":{"Copy with a new id":{"value":{"role":"copy_of_role"}},"Copy with name and description":{"value":{"description":"Same configuration as the original, for production line 2","name":"Line 2 copy","role":"line_2_role"}}},"schema":{"additionalProperties":false,"properties":{"description":{"$ref":"#/components/schemas/resource_description"},"enabled":{"type":"boolean"},"name":{"$ref":"#/components/schemas/resource_name"},"role":{"$ref":"#/components/schemas/resource_id"}},"required":["role"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneRole","tags":["Roles"]}},"/v1/users/{user}/stats":{"get":{"operationId":"User_ReadStatistics","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadUserStatistics","tags":["Users"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v1/users/{user}/storages":{"get":{"operationId":"Storage_List","responses":{"200":{"content":{"application/json":{"example":[{"created":1791741478032,"description":"Storages","index":"index.html","modified":1791741478032,"name":"File Storage","public":true,"storage":"file_storage"},{"created":1791741478032,"description":"Manuals and reports; only readable with a token","modified":1791741478032,"name":"Documents","public":false,"storage":"documents"}],"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListStorages","tags":["Storages"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Storage_Create","requestBody":{"content":{"application/json":{"examples":{"Create Storage":{"description":"Creates a new file storage with public access. It can act as a web server and it is possible to serve a default file, i.e., index.html","value":{"description":"Storages","index":"index.html","name":"File Storage","public":true,"storage":"file_storage"}},"Private storage":{"value":{"description":"Manuals and reports; only readable with a token","name":"Documents","public":false,"storage":"documents"}}},"schema":{"additionalProperties":false,"properties":{"description":{"$ref":"#/components/schemas/resource_description"},"index":{"maxLength":255,"type":"string"},"name":{"$ref":"#/components/schemas/resource_name"},"public":{"type":"boolean"},"storage":{"$ref":"#/components/schemas/resource_id"},"terminal_image":{"maxLength":255,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9._/-]*:[a-zA-Z0-9._-]+$","type":"string"}},"required":["storage","name"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CreateStorage","tags":["Storages"]}},"/v1/users/{user}/storages/{storage}":{"delete":{"operationId":"Storage_Delete","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteStorage","tags":["Storages"]},"get":{"operationId":"Storage_ReadConfig","responses":{"200":{"content":{"application/json":{"examples":{"Create Storage":{"description":"Creates a new file storage with public access. It can act as a web server and it is possible to serve a default file, i.e., index.html","value":{"created":1791741478032,"description":"Storages","index":"index.html","modified":1791741478032,"name":"File Storage","public":true,"storage":"file_storage"}},"Private storage":{"value":{"created":1791741478032,"description":"Manuals and reports; only readable with a token","modified":1791741478032,"name":"Documents","public":false,"storage":"documents"}}},"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadStorageConfig","tags":["Storages"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"storage","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"operationId":"Storage_Update","requestBody":{"content":{"application/json":{"examples":{"Full Update":{"value":{"description":"Storages","index":"index.html","name":"File Storage","public":true,"storage":"file_storage"}},"Update 'description'":{"value":{"description":"Storages"}},"Update 'index'":{"value":{"index":"index.html"}},"Update 'name'":{"value":{"name":"File Storage"}},"Update 'public'":{"value":{"public":true}}},"schema":{"additionalProperties":false,"properties":{"description":{"$ref":"#/components/schemas/resource_description"},"index":{"maxLength":255,"type":"string"},"name":{"$ref":"#/components/schemas/resource_name"},"public":{"type":"boolean"},"terminal_image":{"maxLength":255,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9._/-]*:[a-zA-Z0-9._-]+$","type":"string"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateStorage","tags":["Storages"]}},"/v1/users/{user}/storages/{storage}/clone":{"get":{"operationId":"Storage_CloneConfig","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneStorageConfig","tags":["Storages"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"storage","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Storage_Clone","requestBody":{"content":{"application/json":{"examples":{"Copy with a new id":{"value":{"storage":"copy_of_storage"}},"Copy with name and description":{"value":{"description":"Same configuration as the original, for production line 2","name":"Line 2 copy","storage":"line_2_storage"}}},"schema":{"additionalProperties":false,"properties":{"description":{"$ref":"#/components/schemas/resource_description"},"enabled":{"type":"boolean"},"name":{"$ref":"#/components/schemas/resource_name"},"storage":{"$ref":"#/components/schemas/resource_id"}},"required":["storage"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneStorage","tags":["Storages"]}},"/v1/users/{user}/storages/{storage}/files":{"get":{"operationId":"Storage_ListFiles","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListStorageFiles","tags":["Storages"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"storage","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v1/users/{user}/storages/{storage}/files/{file}":{"delete":{"operationId":"Storage_DeleteFiles","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteStorageFiles","tags":["Storages"]},"get":{"operationId":"Storage_ReadFiles","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadStorageFiles","tags":["Storages"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"storage","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"file","required":true,"schema":{"pattern":"^.*$","type":"string"}}],"put":{"description":"Creates or overwrites the file with the raw request body (any content type); folders on the path are created. For large or binary files prefer PUT /v2/users/{user}/storages/{storage}/files/{path}, which streams the upload.","operationId":"Storage_UpdateFiles","requestBody":{"content":{"application/json":{"schema":{"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateStorageFiles","tags":["Storages"]}},"/v1/users/{user}/storages/{storage}/files{path}":{"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"storage","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"path","required":true,"schema":{"pattern":"^(?:\\/.+?)","type":"string"}}],"patch":{"operationId":"Storage_RenameFiles.+)?)","requestBody":{"content":{"application/json":{"examples":{"Move into a folder":{"value":{"path":"archive/2025/report.csv"}},"Rename a file":{"value":{"path":"docs/manual-v2.pdf"}}},"schema":{"additionalProperties":false,"description":"Moves or renames the file or folder of the URL to 'path', inside the same storage.","properties":{"path":{"maxLength":255,"type":"string"}},"required":["path"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"RenameStorageFiles","tags":["Storages"]},"post":{"description":"Uploads files into the folder of the path: multipart/form-data with one or more files, or JSON {\"files\": [names], \"folders\": [names]} to create empty files and folders.","operationId":"Storage_CreateFiles.+)?)","requestBody":{"content":{"application/json":{"schema":{"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CreateStorageFiles","tags":["Storages"]}},"/v1/users/{user}/storages/{storage}/projects":{"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"storage","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"operationId":"Storage_UpdateProjects","requestBody":{"content":{"application/json":{"examples":{"No projects":{"value":[]},"One project":{"value":["alvarolb@greenhouse"]},"Two projects":{"value":["alvarolb@greenhouse","alvarolb@maintenance"]}},"schema":{"description":"Projects the resource belongs to, as <owner>@<project> ids. Replaces the whole list: read the current one first to add or remove a single project; [] removes it from every project.","items":{"pattern":"^[a-zA-Z0-9_]{1,32}@[a-zA-Z0-9_]{1,32}$","type":"string"},"type":"array"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateStorageProjects","tags":["Storages"]}},"/v1/users/{user}/syncs":{"get":{"operationId":"Sync_List","responses":{"200":{"content":{"application/json":{"example":[{"created":1791741478031,"enabled":true,"modified":1791741478031,"name":"Firmware uploads","sync":"firmware_uploads"},{"created":1791741478031,"description":"Only one controller can dose at a time","enabled":true,"modified":1791741478031,"name":"Dosing pump","sync":"dosing_pump"}],"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListSyncs","tags":["Syncs"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Sync_Create","requestBody":{"content":{"application/json":{"examples":{"Limit concurrent uploads":{"value":{"config":{"available":5,"timeout":600},"enabled":true,"name":"Firmware uploads","sync":"firmware_uploads"}},"One device at a time":{"value":{"config":{"available":1,"timeout":120},"description":"Only one controller can dose at a time","enabled":true,"name":"Dosing pump","sync":"dosing_pump"}}},"schema":{"additionalProperties":false,"description":"A sync is a shared semaphore: 'available' slots that devices or scripts take with locks (POST .../syncs/{sync}/locks) and release, e.g. to let only N devices use a resource at the same time. 'timeout' (seconds) is the default lock lifetime; 0 = until released.","properties":{"config":{"$ref":"#/components/schemas/sync_config"},"description":{"$ref":"#/components/schemas/resource_description"},"enabled":{"type":"boolean"},"name":{"$ref":"#/components/schemas/resource_name"},"sync":{"$ref":"#/components/schemas/resource_id"}},"required":["sync","name","enabled","config"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CreateSync","tags":["Syncs"]}},"/v1/users/{user}/syncs/{sync}":{"delete":{"operationId":"Sync_Delete","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteSync","tags":["Syncs"]},"get":{"operationId":"Sync_ReadConfig","responses":{"200":{"content":{"application/json":{"examples":{"Limit concurrent uploads":{"value":{"config":{"available":5,"timeout":600},"created":1791741478031,"enabled":true,"modified":1791741478031,"name":"Firmware uploads","sync":"firmware_uploads"}},"One device at a time":{"value":{"config":{"available":1,"timeout":120},"created":1791741478031,"description":"Only one controller can dose at a time","enabled":true,"modified":1791741478031,"name":"Dosing pump","sync":"dosing_pump"}}},"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadSyncConfig","tags":["Syncs"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"sync","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"operationId":"Sync_Update","requestBody":{"content":{"application/json":{"examples":{"Disable":{"value":{"enabled":false}},"More slots":{"value":{"config":{"available":10,"timeout":600}}}},"schema":{"additionalProperties":false,"properties":{"config":{"$ref":"#/components/schemas/sync_config"},"description":{"$ref":"#/components/schemas/resource_description"},"enabled":{"type":"boolean"},"name":{"$ref":"#/components/schemas/resource_name"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateSync","tags":["Syncs"]}},"/v1/users/{user}/syncs/{sync}/clone":{"get":{"operationId":"Sync_CloneConfig","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneSyncConfig","tags":["Syncs"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"sync","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Sync_Clone","requestBody":{"content":{"application/json":{"examples":{"Copy with a new id":{"value":{"sync":"copy_of_sync"}},"Copy with name and description":{"value":{"description":"Same configuration as the original, for production line 2","name":"Line 2 copy","sync":"line_2_sync"}}},"schema":{"additionalProperties":false,"properties":{"description":{"$ref":"#/components/schemas/resource_description"},"enabled":{"type":"boolean"},"name":{"$ref":"#/components/schemas/resource_name"},"sync":{"$ref":"#/components/schemas/resource_id"}},"required":["sync"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneSync","tags":["Syncs"]}},"/v1/users/{user}/syncs/{sync}/locks":{"get":{"operationId":"Sync_ListLocks","responses":{"200":{"content":{"application/json":{"example":[{"created":1791741478031,"lock":"pump_controller_1","modified":1791741478031,"name":"Controller 1"},{"created":1791741478031,"lock":"bulk_job","modified":1791741478031,"slots":2}],"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListSyncLocks","tags":["Syncs"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"sync","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Sync_CreateLock","requestBody":{"content":{"application/json":{"examples":{"Take one slot":{"value":{"lock":"pump_controller_1","name":"Controller 1"}},"Two slots for 60 seconds":{"value":{"lock":"bulk_job","slots":2,"timeout":60}}},"schema":{"additionalProperties":false,"description":"Takes 'slots' (default 1) of the sync. Fails when not enough slots are free. 'timeout' (seconds) overrides the sync default; without lock id a random one is assigned. Delete the lock to release it.","properties":{"description":{"$ref":"#/components/schemas/resource_description"},"lock":{"$ref":"#/components/schemas/resource_id"},"name":{"$ref":"#/components/schemas/resource_name"},"slots":{"type":"number"},"timeout":{"type":"number"}},"required":[],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CreateSyncLock","tags":["Syncs"]}},"/v1/users/{user}/syncs/{sync}/locks/{lock}":{"delete":{"operationId":"Sync_DeleteLock","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteSyncLock","tags":["Syncs"]},"get":{"operationId":"Sync_ReadLockConfig","responses":{"200":{"content":{"application/json":{"examples":{"Take one slot":{"value":{"created":1791741478031,"lock":"pump_controller_1","modified":1791741478031,"name":"Controller 1"}},"Two slots for 60 seconds":{"value":{"created":1791741478031,"lock":"bulk_job","modified":1791741478031,"slots":2,"timeout":60}}},"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadSyncLockConfig","tags":["Syncs"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"sync","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"lock","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"operationId":"Sync_UpdateLock","requestBody":{"content":{"application/json":{"examples":{"Rename":{"value":{"name":"Controller 1 - night shift"}}},"schema":{"additionalProperties":false,"properties":{"description":{"$ref":"#/components/schemas/resource_description"},"name":{"$ref":"#/components/schemas/resource_name"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateSyncLock","tags":["Syncs"]}},"/v1/users/{user}/syncs/{sync}/projects":{"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"sync","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"operationId":"Sync_UpdateProjects","requestBody":{"content":{"application/json":{"examples":{"No projects":{"value":[]},"One project":{"value":["alvarolb@greenhouse"]},"Two projects":{"value":["alvarolb@greenhouse","alvarolb@maintenance"]}},"schema":{"description":"Projects the resource belongs to, as <owner>@<project> ids. Replaces the whole list: read the current one first to add or remove a single project; [] removes it from every project.","items":{"pattern":"^[a-zA-Z0-9_]{1,32}@[a-zA-Z0-9_]{1,32}$","type":"string"},"type":"array"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateSyncProjects","tags":["Syncs"]}},"/v1/users/{user}/timezone":{"get":{"operationId":"User_ReadTimezone","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadUserTimezone","tags":["Users"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"operationId":"User_UpdateTimezone","requestBody":{"content":{"application/json":{"examples":{"Madrid":{"value":{"timezone":"Europe/Madrid"}}},"schema":{"additionalProperties":false,"properties":{"timezone":{"maxLength":255,"minLength":1,"type":"string"}},"required":["timezone"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateUserTimezone","tags":["Users"]}},"/v1/users/{user}/tokens":{"get":{"operationId":"Token_List","responses":{"200":{"content":{"application/json":{"example":[{"created":1791741478034,"enabled":true,"modified":1791741478034,"name":"Admin Access","token":"admin_access"},{"created":1791741478034,"enabled":true,"modified":1791741478034,"name":"Shared Access","token":"shared_access"},{"created":1791741478034,"enabled":true,"modified":1791741478034,"name":"Greenhouse 01","token":"greenhouse_01_access"},{"created":1791741478034,"enabled":true,"modified":1791741478034,"name":"Read-only dashboard","token":"readonly_dashboard"}],"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListTokens","tags":["Tokens"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Token_Create","requestBody":{"content":{"application/json":{"examples":{"Admin Access":{"description":"Creates a token with admin access. (For every resource, with any name, execute any action).","value":{"allow":{"*":{"*":"*"}},"enabled":true,"name":"Admin Access","token":"admin_access"}},"Custom Access":{"description":"Creates a token with permissions for reading an specific bucket 'mqtt_bucket', and to access any device resource.","value":{"allow":{"Bucket":{"mqtt_bucket":["ReadBucket"]},"Device":{"*":["AccessDeviceResources"]}},"enabled":true,"name":"Shared Access","token":"shared_access"}},"One device":{"description":"Access to a single device and its data bucket. To scope a token to a project instead, create it with ?project=<project>: it then only works with that project.","value":{"allow":{"Bucket":{"greenhouse_climate":["ReadBucket"]},"Device":{"greenhouse_01":["Read*","AccessDeviceResources"]}},"enabled":true,"name":"Greenhouse 01","token":"greenhouse_01_access"}},"Read-only devices and buckets":{"description":"Lists and reads devices and bucket data, without changing anything (e.g. for an external dashboard).","value":{"allow":{"Bucket":{"*":["List*","Read*"]},"Device":{"*":["List*","Read*"]}},"enabled":true,"name":"Read-only dashboard","token":"readonly_dashboard"}}},"schema":{"additionalProperties":false,"properties":{"allow":{"$ref":"#/components/schemas/permission"},"deny":{"$ref":"#/components/schemas/permission"},"description":{"$ref":"#/components/schemas/resource_description"},"enabled":{"type":"boolean"},"expire":{"description":"Expiration as a unix timestamp in milliseconds: the token stops working then, and is deleted shortly after. Without it the token does not expire. Set when the token is created; it cannot be changed later.","type":"number"},"name":{"$ref":"#/components/schemas/resource_name"},"token":{"pattern":"^[a-zA-Z0-9_]{1,50}$","type":"string"}},"required":["token","name","enabled"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CreateToken","tags":["Tokens"]}},"/v1/users/{user}/tokens/{token}":{"delete":{"operationId":"Token_Delete","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteToken","tags":["Tokens"]},"get":{"operationId":"Token_ReadConfig","responses":{"200":{"content":{"application/json":{"examples":{"Admin Access":{"description":"Creates a token with admin access. (For every resource, with any name, execute any action).","value":{"allow":{"*":{"*":"*"}},"created":1791741478034,"enabled":true,"modified":1791741478034,"name":"Admin Access","token":"admin_access"}},"Custom Access":{"description":"Creates a token with permissions for reading an specific bucket 'mqtt_bucket', and to access any device resource.","value":{"allow":{"Bucket":{"mqtt_bucket":["ReadBucket"]},"Device":{"*":["AccessDeviceResources"]}},"created":1791741478034,"enabled":true,"modified":1791741478034,"name":"Shared Access","token":"shared_access"}},"One device":{"description":"Access to a single device and its data bucket. To scope a token to a project instead, create it with ?project=<project>: it then only works with that project.","value":{"allow":{"Bucket":{"greenhouse_climate":["ReadBucket"]},"Device":{"greenhouse_01":["Read*","AccessDeviceResources"]}},"created":1791741478034,"enabled":true,"modified":1791741478034,"name":"Greenhouse 01","token":"greenhouse_01_access"}},"Read-only devices and buckets":{"description":"Lists and reads devices and bucket data, without changing anything (e.g. for an external dashboard).","value":{"allow":{"Bucket":{"*":["List*","Read*"]},"Device":{"*":["List*","Read*"]}},"created":1791741478034,"enabled":true,"modified":1791741478034,"name":"Read-only dashboard","token":"readonly_dashboard"}}},"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadTokenConfig","tags":["Tokens"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"token","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,50}","type":"string"}}],"put":{"operationId":"Token_Update","requestBody":{"content":{"application/json":{"examples":{"Full Update":{"value":{"allow":{"*":{"*":"*"}},"enabled":true,"name":"Admin Access","token":"admin_access"}},"Update 'allow'":{"value":{"allow":{"*":{"*":"*"}}}},"Update 'enabled'":{"value":{"enabled":true}},"Update 'name'":{"value":{"name":"Admin Access"}}},"schema":{"additionalProperties":false,"properties":{"allow":{"$ref":"#/components/schemas/permission"},"deny":{"$ref":"#/components/schemas/permission"},"description":{"$ref":"#/components/schemas/resource_description"},"enabled":{"type":"boolean"},"expire":{"description":"Cannot be changed: the expiration is signed into the token when it is created. Create a new token instead.","type":"number"},"name":{"$ref":"#/components/schemas/resource_name"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateToken","tags":["Tokens"]}},"/v1/users/{user}/tokens/{token}/clone":{"get":{"operationId":"Token_CloneConfig","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneTokenConfig","tags":["Tokens"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"token","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,50}","type":"string"}}],"post":{"operationId":"Token_Clone","requestBody":{"content":{"application/json":{"examples":{"Copy with a new id":{"value":{"token":"copy_of_token"}},"Copy with name and description":{"value":{"description":"Same configuration as the original, for production line 2","name":"Line 2 copy","token":"line_2_token"}}},"schema":{"additionalProperties":false,"properties":{"description":{"$ref":"#/components/schemas/resource_description"},"enabled":{"type":"boolean"},"name":{"$ref":"#/components/schemas/resource_name"},"token":{"$ref":"#/components/schemas/resource_id"}},"required":["token"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneToken","tags":["Tokens"]}},"/v1/users/{user}/tokens/{token}/projects":{"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"token","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,50}","type":"string"}}],"put":{"operationId":"Token_UpdateProjects","requestBody":{"content":{"application/json":{"examples":{"No projects":{"value":[]},"One project":{"value":["alvarolb@greenhouse"]},"Two projects":{"value":["alvarolb@greenhouse","alvarolb@maintenance"]}},"schema":{"description":"Projects the resource belongs to, as <owner>@<project> ids. Replaces the whole list: read the current one first to add or remove a single project; [] removes it from every project.","items":{"pattern":"^[a-zA-Z0-9_]{1,32}@[a-zA-Z0-9_]{1,32}$","type":"string"},"type":"array"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateTokenProjects","tags":["Tokens"]}},"/v1/users/{user}/types":{"get":{"operationId":"Type_List","responses":{"200":{"content":{"application/json":{"example":[{"description":"Gas boilers with remote control","name":"Boiler","type":"boiler"}],"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListTypes","tags":["Types"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Type_Create","requestBody":{"content":{"application/json":{"examples":{"Boiler":{"value":{"description":"Gas boilers with remote control","name":"Boiler","type":"boiler"}}},"schema":{"additionalProperties":false,"description":"An asset type is what a device is (boiler, meter, gateway). Devices join one with their asset_type field and inherit its properties.","properties":{"description":{"type":"string"},"name":{"type":"string"},"type":{"$ref":"#/components/schemas/resource_id"}},"required":["type"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CreateType","tags":["Types"]}},"/v1/users/{user}/types/{type}":{"delete":{"operationId":"Type_Delete","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteType","tags":["Types"]},"get":{"operationId":"Type_ReadConfig","responses":{"200":{"content":{"application/json":{"examples":{"Boiler":{"value":{"description":"Gas boilers with remote control","name":"Boiler","type":"boiler"}}},"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadTypeConfig","tags":["Types"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"type","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"operationId":"Type_Update","requestBody":{"content":{"application/json":{"examples":{"Rename":{"value":{"description":"Condensing gas boilers","name":"Gas boiler"}}},"schema":{"additionalProperties":false,"properties":{"description":{"type":"string"},"name":{"type":"string"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateType","tags":["Types"]}},"/v1/users/{user}/types/{type}/clone":{"get":{"operationId":"Type_CloneConfig","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneTypeConfig","tags":["Types"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"type","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Type_Clone","requestBody":{"content":{"application/json":{"examples":{"Copy with a new id":{"value":{"type":"copy_of_type"}},"Copy with name and description":{"value":{"description":"Same configuration as the original, for production line 2","name":"Line 2 copy","type":"line_2_type"}}},"schema":{"additionalProperties":false,"properties":{"description":{"$ref":"#/components/schemas/resource_description"},"enabled":{"type":"boolean"},"name":{"$ref":"#/components/schemas/resource_name"},"type":{"$ref":"#/components/schemas/resource_id"}},"required":["type"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneType","tags":["Types"]}},"/v1/users/{user}/types/{type}/locations":{"get":{"operationId":"Type_ReadAssetsLocations","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadAssetsLocations","tags":["Types"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"type","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v1/users/{user}/types/{type}/projects":{"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"type","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"operationId":"Type_UpdateProjects","requestBody":{"content":{"application/json":{"examples":{"No projects":{"value":[]},"One project":{"value":["alvarolb@greenhouse"]},"Two projects":{"value":["alvarolb@greenhouse","alvarolb@maintenance"]}},"schema":{"description":"Projects the resource belongs to, as <owner>@<project> ids. Replaces the whole list: read the current one first to add or remove a single project; [] removes it from every project.","items":{"pattern":"^[a-zA-Z0-9_]{1,32}@[a-zA-Z0-9_]{1,32}$","type":"string"},"type":"array"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateTypeProjects","tags":["Types"]}},"/v1/users/{user}/types/{type}/properties":{"get":{"operationId":"Type_ListProperties","responses":{"200":{"content":{"application/json":{"example":[{"created":1791741476404,"description":"Sampling and alert thresholds","modified":1791741476404,"name":"Settings","property":"settings","type":"configuration","value":{"alerts":true,"interval":60,"max_temperature":28.5}},{"created":1791741476404,"modified":1791741476404,"name":"Location","property":"location","value":{"lat":40.4168,"lon":-3.7038}},{"created":1791741476404,"modified":1791741476404,"name":"Calibration","perm":{"readOnly":["member"]},"property":"calibration","value":{"gain":1.02,"offset":-0.4}},{"created":1791741476404,"modified":1791741476404,"name":"Dashboard","property":"dashboard","value":{"source":"url","url":"/v1/users/alvarolb/storages/fleet_app/files/index.html?v=1"}}],"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListTypeProperties","tags":["Types"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"type","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Type_CreateProperty","requestBody":{"content":{"application/json":{"examples":{"Configuration value":{"value":{"description":"Sampling and alert thresholds","name":"Settings","property":"settings","type":"configuration","value":{"alerts":true,"interval":60,"max_temperature":28.5}}},"Location":{"value":{"name":"Location","property":"location","value":{"lat":40.4168,"lon":-3.7038}}},"Read-only for project members":{"value":{"name":"Calibration","perm":{"readOnly":["member"]},"property":"calibration","value":{"gain":1.02,"offset":-0.4}}},"Url dashboard of the resource":{"value":{"name":"Dashboard","property":"dashboard","value":{"source":"url","url":"/v1/users/alvarolb/storages/fleet_app/files/index.html?v=1"}}}},"schema":{"description":"A property is a JSON value stored on its resource (device, asset type, asset group, project, product, plugin or account). Devices inherit the properties of their asset type, asset group and product. 'type: configuration' marks values the device reads; 'perm' hides or locks a property for the account owner or project members. An array of these objects creates several at once.","oneOf":[{"items":{"$ref":"#/components/schemas/property_create"},"type":"array"},{"$ref":"#/components/schemas/property_create"}]}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CreateTypeProperty","tags":["Types"]}},"/v1/users/{user}/types/{type}/properties/{property}":{"delete":{"operationId":"Type_DeleteProperty","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteTypeProperty","tags":["Types"]},"get":{"operationId":"Type_ReadProperty","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadTypeProperty","tags":["Types"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"type","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"property","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"patch":{"operationId":"Type_PatchProperty","requestBody":{"content":{"application/json":{"examples":{"Change some fields of the value":{"value":{"value":{"interval":30}}},"Flattened fields":{"value":{"value.alerts":false,"value.max_temperature":27}}},"schema":{"oneOf":[{"additionalProperties":false,"properties":{"value":{}},"required":["value"]},{"additionalProperties":false,"minProperties":1,"patternProperties":{"^value(\\.[^.]+)+$":{}}}],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateTypeProperty","tags":["Types"]},"put":{"operationId":"Type_UpdateProperty","requestBody":{"content":{"application/json":{"examples":{"Hide from project members":{"value":{"perm":{"hidden":["member"]},"value":"internal note"}},"Replace the value":{"value":{"value":{"alerts":true,"interval":30,"max_temperature":27}}},"Value, name and description":{"value":{"description":"Faster sampling during commissioning","name":"Settings","value":{"alerts":false,"interval":10,"max_temperature":28.5}}}},"schema":{"$ref":"#/components/schemas/property_update"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateTypeProperty","tags":["Types"]}},"/v1/users/{user}/types/{type}/properties/{property}/clone":{"get":{"operationId":"Type_ClonePropertyConfig","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneTypePropertyConfig","tags":["Types"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"type","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"property","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Type_CloneProperty","requestBody":{"content":{"application/json":{"examples":{"Copy with a new id":{"value":{"property":"copy_of_property"}},"Copy with name and description":{"value":{"description":"Same configuration as the original, for production line 2","name":"Line 2 copy","property":"line_2_property"}}},"schema":{"additionalProperties":false,"properties":{"description":{"$ref":"#/components/schemas/resource_description"},"enabled":{"type":"boolean"},"name":{"$ref":"#/components/schemas/resource_name"},"property":{"$ref":"#/components/schemas/resource_id"}},"required":["property"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneTypeProperty","tags":["Types"]}},"/v2/users/{user}/devices/{device}/{resource}":{"get":{"deprecated":true,"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"AccessDeviceResources","tags":["Devices"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"device","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"resource","required":true,"schema":{"pattern":"^(?:.{1,32}\\/?+)","type":"string"}}],"post":{"deprecated":true,"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"AccessDeviceResources","tags":["Devices"]}},"/v2/users/{user}/events":{"get":{"operationId":"User_SubscribeEvents","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"SubscribeUserEvents","tags":["Users"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v2/users/{user}/storages/{storage}/files{file}":{"delete":{"operationId":"Storage_DeleteFilesFiles(?<file>.*$)","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteStorageFiles","tags":["Storages"]},"get":{"operationId":"Storage_ReadFilesFiles(?<file>.*$)","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadStorageFiles","tags":["Storages"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"storage","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"file","required":true,"schema":{"pattern":"^.*$","type":"string"}}],"patch":{"operationId":"Storage_RenameFilesFiles(?<file>.*$)","requestBody":{"content":{"application/json":{"examples":{"Rename a file":{"value":{"path":"/docs/manual-v2.pdf"}}},"schema":{"description":"Moves or renames the file or folder of the URL to 'path', inside the same storage.","properties":{"path":{"type":"string"}},"required":["path"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"RenameStorageFiles","tags":["Storages"]},"put":{"description":"Streams the raw request body (any content type, e.g. application/octet-stream) into the file; folders are created. A path ending in / creates a folder (empty body). ?overwrite=false fails if it exists.","operationId":"Storage_UpdateFilesFiles(?<file>.*$)","requestBody":{"content":{"application/json":{"schema":{"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateStorageFiles","tags":["Storages"]}},"/v2/users/{user}/storages/{storage}/terminal":{"get":{"operationId":"Storage_AccessTerminal","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"AccessStorageTerminal","tags":["Storages"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"storage","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v3/users/{user}/devices/{device}/buckets":{"get":{"operationId":"Device_ListBuckets","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListDeviceBuckets","tags":["Devices"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"device","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v3/users/{user}/devices/{device}/buckets/{bucket}/tags":{"get":{"operationId":"Device_ListBucketTags","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListDeviceBucketTags","tags":["Devices"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"device","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"bucket","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v3/users/{user}/devices/{device}/buckets/{bucket}/tags/{tag}":{"get":{"operationId":"Device_ReadBucketTag","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadDeviceBucketTag","tags":["Devices"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"device","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"bucket","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"tag","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v3/users/{user}/devices/{device}/callback":{"get":{"operationId":"Device_ReadCallbackConfig","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadDeviceCallbackConfig","tags":["Devices"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"device","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"put":{"operationId":"Device_UpdateCallback","requestBody":{"content":{"application/json":{"examples":{"Store the data in a bucket":{"value":{"actions":{"write_bucket":"meter_readings"},"properties":{"timeout":10}}},"Store, notify and reply with a property":{"value":{"actions":{"call_endpoint":"readings_webhook","send_property":"settings","write_bucket":"meter_readings"}}}},"schema":{"additionalProperties":false,"description":"What the server does with the JSON an HTTP device posts to its callback (POST /v3/users/{user}/devices/{device}/callback/data): write_bucket stores it in a bucket, call_endpoint forwards it to an endpoint, set_property saves it as a device property, send_property returns a property as the response (e.g. its configuration). properties.timeout: minutes without data before the device is shown as disconnected.","properties":{"actions":{"additionalProperties":false,"properties":{"call_endpoint":{"$ref":"#/components/schemas/resource_id"},"send_property":{"$ref":"#/components/schemas/resource_id"},"set_property":{"$ref":"#/components/schemas/resource_id"},"write_bucket":{"$ref":"#/components/schemas/resource_id"}},"type":"object"},"properties":{"additionalProperties":false,"properties":{"timeout":{"type":"integer"}},"type":"object"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateDeviceCallback","tags":["Devices"]}},"/v3/users/{user}/devices/{device}/callback/data":{"get":{"operationId":"Device_ReadCallbackResponseData","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadDeviceCallbackResponse","tags":["Devices"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"device","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Device_CallCallbackData","requestBody":{"content":{"application/json":{"examples":{"Meter reading":{"value":{"energy":1532.8,"power":2.1,"voltage":229.7}}},"schema":{"description":"Data an HTTP device sends: any JSON. The device callback settings (PUT .../callback) decide what happens with it (bucket, endpoint, property, response). ?ts=<epoch ms> sets the timestamp."}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CallDeviceCallback","tags":["Devices"]}},"/v3/users/{user}/devices/{device}/files{file}":{"delete":{"operationId":"Device_DeleteFilesFiles(?<file>.*$)","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteDeviceFiles","tags":["Devices"]},"get":{"operationId":"Device_ReadFilesFiles(?<file>.*$)","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadDeviceFiles","tags":["Devices"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"device","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"file","required":true,"schema":{"pattern":"^.*$","type":"string"}}],"patch":{"operationId":"Device_RenameFilesFiles(?<file>.*$)","requestBody":{"content":{"application/json":{"schema":{"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"RenameDeviceFiles","tags":["Devices"]},"put":{"operationId":"Device_UpdateFilesFiles(?<file>.*$)","requestBody":{"content":{"application/json":{"schema":{"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateDeviceFiles","tags":["Devices"]}},"/v3/users/{user}/devices/{device}/properties":{"get":{"operationId":"Device_ListProperties","responses":{"200":{"content":{"application/json":{"example":[{"created":1791741476395,"description":"Sampling and alert thresholds","modified":1791741476395,"name":"Settings","property":"settings","type":"configuration","value":{"alerts":true,"interval":60,"max_temperature":28.5}},{"created":1791741476395,"modified":1791741476395,"name":"Location","property":"location","value":{"lat":40.4168,"lon":-3.7038}},{"created":1791741476395,"modified":1791741476395,"name":"Calibration","perm":{"readOnly":["member"]},"property":"calibration","value":{"gain":1.02,"offset":-0.4}},{"created":1791741476395,"modified":1791741476395,"name":"Dashboard","property":"dashboard","value":{"source":"url","url":"/v1/users/alvarolb/storages/fleet_app/files/index.html?v=1"}}],"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListDeviceProperties","tags":["Devices"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"device","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Device_CreateProperty","requestBody":{"content":{"application/json":{"examples":{"Configuration value":{"value":{"description":"Sampling and alert thresholds","name":"Settings","property":"settings","type":"configuration","value":{"alerts":true,"interval":60,"max_temperature":28.5}}},"Location":{"value":{"name":"Location","property":"location","value":{"lat":40.4168,"lon":-3.7038}}},"Read-only for project members":{"value":{"name":"Calibration","perm":{"readOnly":["member"]},"property":"calibration","value":{"gain":1.02,"offset":-0.4}}},"Url dashboard of the resource":{"value":{"name":"Dashboard","property":"dashboard","value":{"source":"url","url":"/v1/users/alvarolb/storages/fleet_app/files/index.html?v=1"}}}},"schema":{"description":"A property is a JSON value stored on its resource (device, asset type, asset group, project, product, plugin or account). Devices inherit the properties of their asset type, asset group and product. 'type: configuration' marks values the device reads; 'perm' hides or locks a property for the account owner or project members. An array of these objects creates several at once.","oneOf":[{"items":{"$ref":"#/components/schemas/property_create"},"type":"array"},{"$ref":"#/components/schemas/property_create"}]}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CreateDeviceProperty","tags":["Devices"]}},"/v3/users/{user}/devices/{device}/properties/{property}":{"delete":{"operationId":"Device_DeleteProperty","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"DeleteDeviceProperty","tags":["Devices"]},"get":{"operationId":"Device_ReadProperty","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadDeviceProperty","tags":["Devices"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"device","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"property","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"patch":{"operationId":"Device_PatchProperty","requestBody":{"content":{"application/json":{"examples":{"Change some fields of the value":{"value":{"value":{"interval":30}}},"Flattened fields":{"value":{"value.alerts":false,"value.max_temperature":27}}},"schema":{"oneOf":[{"additionalProperties":false,"properties":{"value":{}},"required":["value"]},{"additionalProperties":false,"minProperties":1,"patternProperties":{"^value(\\.[^.]+)+$":{}}}],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateDeviceProperty","tags":["Devices"]},"put":{"operationId":"Device_UpdateProperty","requestBody":{"content":{"application/json":{"examples":{"Hide from project members":{"value":{"perm":{"hidden":["member"]},"value":"internal note"}},"Replace the value":{"value":{"value":{"alerts":true,"interval":30,"max_temperature":27}}},"Value, name and description":{"value":{"description":"Faster sampling during commissioning","name":"Settings","value":{"alerts":false,"interval":10,"max_temperature":28.5}}}},"schema":{"$ref":"#/components/schemas/property_update"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"UpdateDeviceProperty","tags":["Devices"]}},"/v3/users/{user}/devices/{device}/properties/{property}/clone":{"get":{"operationId":"Device_ClonePropertyConfig","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneDevicePropertyConfig","tags":["Devices"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"device","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"property","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}],"post":{"operationId":"Device_CloneProperty","requestBody":{"content":{"application/json":{"examples":{"Copy with a new id":{"value":{"property":"copy_of_property"}},"Copy with name and description":{"value":{"description":"Same configuration as the original, for production line 2","name":"Line 2 copy","property":"line_2_property"}}},"schema":{"additionalProperties":false,"properties":{"description":{"$ref":"#/components/schemas/resource_description"},"enabled":{"type":"boolean"},"name":{"$ref":"#/components/schemas/resource_name"},"property":{"$ref":"#/components/schemas/resource_id"}},"required":["property"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"CloneDeviceProperty","tags":["Devices"]}},"/v3/users/{user}/devices/{device}/resources":{"get":{"operationId":"Device_AccessResources","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"AccessDeviceResources","tags":["Devices"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"device","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v3/users/{user}/devices/{device}/resources/{resource}":{"get":{"operationId":"Device_AccessOutputResources","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"AccessDeviceResources","tags":["Devices"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"device","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"resource","required":true,"schema":{"pattern":"^(?:.{1,32}\\/?+)","type":"string"}}],"post":{"operationId":"Device_AccessInputResources","requestBody":{"content":{"application/json":{"examples":{"Set a target":{"value":{"mode":"auto","setpoint":21.5}},"Switch a relay":{"value":{"in":true}}},"schema":{"description":"Input of the device resource: whatever JSON the resource expects (see GET .../resources for its description). Resources without input take no body."}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"AccessDeviceResources","tags":["Devices"]}},"/v3/users/{user}/devices/{device}/services":{"get":{"operationId":"Device_ListServices","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ListDeviceServices","tags":["Devices"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"device","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v3/users/{user}/devices/{device}/services/{service}":{"get":{"operationId":"Device_ReadService","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadDeviceService","tags":["Devices"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"device","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"service","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v3/users/{user}/devices/{device}/services/{service}/vnc":{"get":{"operationId":"Device_AccessRemoteDesktopVnc","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"AccessDeviceRemoteDesktop","tags":["Devices"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"device","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"service","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v3/users/{user}/devices/{device}/services/{service}/web":{"get":{"operationId":"Device_AccessWebServices","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"AccessDeviceWebServices","tags":["Devices"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"device","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"service","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v3/users/{user}/devices/{device}/stats":{"get":{"operationId":"Device_ReadStatistics","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadDeviceStatistics","tags":["Devices"]},"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"device","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/v3/users/{user}/devices/{device}/ws_proxy":{"parameters":[{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"device","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/{version}/users/{user}/buckets/{bucket}/data":{"get":{"operationId":"Bucket_ReadData","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadBucket","tags":["Buckets"]},"parameters":[{"in":"path","name":"version","required":true,"schema":{"pattern":"^(?:v1|v2)","type":"string"}},{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"bucket","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]},"/{version}/users/{user}/devices/{device}/buckets/{bucket}/data":{"get":{"operationId":"Device_ReadBucketData","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"ok"},"401":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"forbidden"}},"security":[{"bearerAuth":[],"oauth":["basic"]}],"summary":"ReadDeviceBucket","tags":["Devices"]},"parameters":[{"in":"path","name":"version","required":true,"schema":{"pattern":"^(?:v1|v2|v3)","type":"string"}},{"in":"path","name":"user","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"device","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}},{"in":"path","name":"bucket","required":true,"schema":{"pattern":"^[a-zA-Z0-9_-]{1,32}","type":"string"}}]}},"servers":[{"url":"https://perf.aws.thinger.io:443"}]}
|