{"openapi":"3.1.0","info":{"title":"Things Downlinks API","description":"This specification describes the Downlinks API of the KPN Things Platform.","contact":{"name":"KPN Things Support","url":"https://portal.kpnthings.com/support","email":"iot-developer@kpn.com"},"version":"0.8.0"},"servers":[{"url":"https://api.kpnthings.com","description":"Things API Environment"}],"paths":{"/downlinks":{"get":{"summary":"Retrieve downlinks filtered and sorted by specified search and sort criteria","operationId":"searchDownlinks","parameters":[{"$ref":"#/components/parameters/cursor"},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/sort"},{"name":"q","in":"query","description":"Include only downlinks whose tagValue, networkId or message match the search term. The tagValue must match exactly. The networkId and message may match partially. Matching for every query parameter is done case-sensitively.","style":"form","explode":true,"schema":{"type":"string","minLength":1,"example":null},"example":"urn:dev:DEVEUI:1234567890abcded:"},{"name":"createdBefore","in":"query","description":"Include only downlinks created before the provided date and time. The date-time must be in ISO 8601 format.","style":"form","explode":true,"schema":{"type":"string","format":"date-time","example":null},"example":"2025-05-01T00:00:00Z"},{"name":"createdSince","in":"query","description":"Include only downlinks created at or after the provided date and time. The date-time must be in ISO 8601 format.","style":"form","explode":true,"schema":{"type":"string","format":"date-time","example":null},"example":"2025-05-01T00:00:00Z"},{"name":"modifiedBefore","in":"query","description":"Include only downlinks modified before the provided date and time. The date-time must be in ISO 8601 format.","style":"form","explode":true,"schema":{"type":"string","format":"date-time","example":null},"example":"2025-04-01T00:00:00Z"},{"name":"modifiedSince","in":"query","description":"Include only downlinks modified at or after the provided date and time. The date-time must be in ISO 8601 format.","style":"form","explode":true,"schema":{"type":"string","format":"date-time","example":null},"example":"2025-04-01T00:00:00Z"}],"responses":{"200":{"description":"Page of filtered downlinks. Only downlinks that are accessible to the caller are returned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PageOfDownlinks","example":null}}}}},"security":[{"BearerAuth":["downlink.read"]}]},"post":{"summary":"Create a new downlink","operationId":"createDownlink","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDownlinkRequest"}}}},"responses":{"201":{"description":"Downlink has been successfully created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Downlink","example":null}}}}},"security":[{"BearerAuth":["downlink.write"]}]}},"/downlinks/{downlinkId}":{"get":{"summary":"Retrieve a downlink by ID.","operationId":"getDownlink","parameters":[{"name":"downlinkId","in":"path","description":"Downlink identifier","required":true,"style":"simple","schema":{"type":"string","example":null}}],"responses":{"200":{"description":"Downlink has been successfully fetched.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Downlink","example":null}}}}},"security":[{"BearerAuth":["downlink.read"]}]},"delete":{"summary":"Accepts and schedules full or partial cancellation of downlink for further downstream handling.","operationId":"cancelDownlink","parameters":[{"name":"downlinkId","in":"path","description":"Downlink identifier","required":true,"style":"simple","schema":{"type":"string","example":null}},{"name":"forced","in":"query","description":"Whether to force the cancellation of the downlink or not.","style":"form","explode":true,"schema":{"type":"boolean","default":false,"example":null}}],"responses":{"202":{"description":"Downlink cancellation has been accepted and scheduled for further downstream processing."},"409":{"description":"Downlink status does not permit cancellation.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem","example":null}}}}},"security":[{"BearerAuth":["downlink.delete"]}]}}},"components":{"schemas":{"Page":{"type":"object","description":"Page of items","properties":{"items":{"type":"array","items":{},"example":null},"next":{"type":"string","format":"uri","description":"Pagination link pointing to the next page. Only provided when not at the last page.","example":null},"prev":{"type":"string","format":"uri","description":"Pagination link pointing to the previous page. Only provided when not at the first page.","example":null}},"required":["items"],"title":"Page","example":null},"DownlinkStatus":{"type":"string","description":"Status of the downlink message. Known values include: PENDING, EXECUTING, SENT_TO_CARRIER, CANCELLED, RETRY, DELIVERED and FAILED","example":"DELIVERED","title":"DownlinkStatus"},"DownlinkEventType":{"type":"string","description":"Name of the event which corresponds to this log entry. Known values include: DOWNLINK_PART_SENT, DOWNLINK_PART_FAILED, DOWNLINK_PART_DELIVERED, DOWNLINK_ACCEPTED, DOWNLINK_REJECTED, DOWNLINK_STARTED, DOWNLINK_DELIVERED and DOWNLINK_FAILED","example":"DOWNLINK_DELIVERED","title":"DownlinkEventType"},"DownlinkLog":{"type":"object","description":"Log entry that describes a status change or operation that happened with respect to the downlink","properties":{"createdAt":{"type":"string","format":"date-time","description":"The creation timestamp of the downlink log","example":"2025-01-11T09:27:26.272Z"},"event":{"$ref":"#/components/schemas/DownlinkEventType","example":null},"errorCode":{"type":"string","description":"Error code indicating the reason for a failure, if applicable.","example":"CANCELLED","pattern":".*\\S.*"}},"required":["createdAt"],"title":"DownlinkLog","example":null},"Downlink":{"type":"object","description":"A message that is sent to an IoT device.","properties":{"id":{"type":"string","description":"Unique identifier for the downlink.","example":"12345678-1234-1234-1234-123456789012","readOnly":true},"networkId":{"type":"string","description":"An identifier for a device that is on an activated network.","example":"urn:dev:DEVEUI:1234567890abcded:"},"externalReference":{"type":"string","description":"Optional external identifier that can be provided by API caller to reference the downlink with. Must be unique for the client that owns the device.","example":"someExternalReference123"},"status":{"$ref":"#/components/schemas/DownlinkStatus","example":null},"message":{"type":"string","description":"SenML message to send to the device","example":"[{\"bn\":\"urn:dev:ow:10e2073a01080063:\"},{\"n\":\"temperature\",\"u\":\"Cel\",\"v\":23.1},{\"n\":\"heating\",\"u\":\"/\",\"v\":1},{\"n\":\"fan\",\"u\":\"/\",\"v\":0}]"},"createdAt":{"type":"string","format":"date-time","description":"The timestamp when the downlink is created in the system.","example":"2025-01-10T10:59:12.821Z","readOnly":true},"modifiedAt":{"type":"string","format":"date-time","description":"The timestamp when the downlink is last modified in the system.","example":"2025-01-11T09:27:26.272Z","readOnly":true},"logs":{"type":"array","description":"Logs of downlink message","items":{"$ref":"#/components/schemas/DownlinkLog"},"example":null}},"required":["networkId","status"],"title":"Downlink","example":null},"PageOfDownlinks":{"type":"object","allOf":[{"$ref":"#/components/schemas/Page","example":null},{"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Downlink"},"example":null}},"example":null}],"description":"A paginated list of downlinks","title":"PageOfDownlinks","example":null},"SenMLRecord":{"type":"object","description":"A single record in a SenML pack.","properties":{"i_":{"type":"number","format":"int32","example":null},"bn":{"type":"string","example":null},"bt":{"type":"number","format":"double","example":null},"bv":{"type":"number","format":"double","example":null},"bs":{"type":"number","format":"double","example":null},"bu":{"type":"string","example":null},"bver":{"type":"integer","format":"int32","example":null},"l":{"type":"string","example":null},"n":{"type":"string","example":null},"s":{"type":"number","format":"double","example":null},"t":{"type":"number","format":"double","example":null},"u":{"type":"string","example":null},"ut":{"type":"number","format":"double","example":null},"v":{"type":"number","format":"double","example":null},"vb":{"type":"boolean","example":null},"vs":{"type":"string","example":null},"vd":{"type":"string","example":null}},"title":"SenMLRecord","example":null},"SenMLPack":{"type":"array","items":{"$ref":"#/components/schemas/SenMLRecord"},"title":"SenMLPack","example":null},"HttpMethod":{"type":"object","description":"Method of delivering a downlink over HTTP.","properties":{"protocol":{"type":"string","description":"The protocol type. For HttpMethod, this must be HTTP.","example":null}},"required":["protocol"],"title":"HttpMethod","example":null},"LoraMethod":{"type":"object","description":"Method of delivering a downlink using the LoRa protocol.","properties":{"protocol":{"type":"string","description":"The protocol type. For LoraMethod, this must be LORA.","example":null},"fPort":{"type":"integer","description":"LoRaWAN FPort used by the device for this downlink.","example":3}},"required":["protocol"],"title":"LoraMethod","example":null},"MqttMethod":{"type":"object","description":"Method of delivering a downlink using the MQTT protocol.","properties":{"protocol":{"type":"string","description":"The protocol type. For MqttMethod, this must be MQTT.","example":null},"topic":{"type":"string","default":"downlink","description":"MQTT topic to which the message should be published.","example":"downlink"},"contentType":{"type":"string","description":"MIME type of the message content.","example":"text/plain"}},"required":["protocol"],"title":"MqttMethod","example":null},"SmsMethod":{"type":"object","description":"Method of delivering a downlink by SMS","properties":{"protocol":{"type":"string","description":"The protocol type. For SmsMethod, this must be SMS.","example":null}},"required":["protocol"],"title":"SmsMethod","example":null},"SimpleDuration":{"type":"string","format":"duration","description":"Duration that supports a subset of ISO 8601, where only days, hours, minutes, and seconds can be specified. Days are treated as exactly 24 hours, thus ignoring daylight savings effects.","example":"P3DT4H5M6.5S","pattern":"^P(?:(\\d+D)(T(?:(\\d+H)?(\\d+M)?(\\d+(\\.\\d{1,9})?S)?)?)|T(\\d+H)?(\\d+M)?(\\d+(\\.\\d{1,9})?S)?)$"},"CreateDownlinkRequest":{"type":"object","description":"A request to create a downlink to be sent to an IoT device.","properties":{"externalReference":{"type":"string","description":"Optional external identifier that can be provided by API caller to reference the downlink with. Must be unique for the client that owns the device.","example":"someExternalReference123"},"instruction":{"allOf":[{"$ref":"#/components/schemas/SenMLPack","example":null},{"description":"Instruction in SenML format to send to the device. The provided instruction must contain a bn that identifies the device. The SenML instruction will be transformed into a protocol specific downlink using the configured encoder.","example":[{"bn":"urn:dev:ow:10e2073a01080063:"},{"n":"temperature","u":"Cel","v":23.1},{"n":"heating","u":"/","v":1},{"n":"fan","u":"/","v":0}]}],"example":null},"method":{"type":"object","discriminator":{"propertyName":"protocol","mapping":{"HTTP":"#/components/schemas/HttpMethod","LORA":"#/components/schemas/LoraMethod","MQTT":"#/components/schemas/MqttMethod","SMS":"#/components/schemas/SmsMethod"}},"oneOf":[{"$ref":"#/components/schemas/HttpMethod","example":null},{"$ref":"#/components/schemas/LoraMethod","example":null},{"$ref":"#/components/schemas/MqttMethod","example":null},{"$ref":"#/components/schemas/SmsMethod","example":null}],"example":null},"retryLimit":{"type":"integer","default":0,"description":"The maximum number of retries that should be performed for the downlink.","example":3,"minimum":0},"feedbackTimeout":{"allOf":[{"$ref":"#/components/schemas/SimpleDuration","example":null},{"description":"The duration after which feedback is expected for the downlink. Must be at least 10 minutes.","example":"PT25H"}],"example":null},"dryRun":{"type":"boolean","default":false,"description":"Indicates if this is a dry run.","example":null}},"required":["instruction","method"],"title":"CreateDownlinkRequest","example":null},"Problem":{"type":"object","description":"Error information details","properties":{"type":{"type":"string","format":"uri-reference","default":"about:blank","description":"A URI reference that uniquely identifies the problem type only in the\ncontext of the provided API. Opposed to the specification in RFC-9457,\nit is neither recommended to be dereferenceable and point to a\nhuman-readable documentation nor globally unique for the problem type.","example":"/some/uri-reference"},"title":{"type":"string","description":"A short summary of the problem type. Written in English and readable\nfor engineers, usually not suited for non technical stakeholders and\nnot localized.","example":"some title for the error situation"},"status":{"type":"integer","format":"int32","description":"The HTTP status code generated by the origin server for this occurrence\nof the problem.","example":"400","exclusiveMaximum":600,"minimum":100},"detail":{"type":"string","description":"A human readable explanation specific to this occurrence of the\nproblem that is helpful to locate the problem and give advice on how\nto proceed. Written in English and readable for engineers, usually not\nsuited for non technical stakeholders and not localized.","example":"Some description for the error situation"},"instance":{"type":"string","format":"uri-reference","description":"A URI reference that identifies the specific occurrence of the problem,\ne.g. by adding a fragment identifier or sub-path to the problem type.\nMay be used to locate the root of this problem in the source code.","example":"/some/uri-reference#specific-occurrence-context"}},"title":"Problem","example":null}},"parameters":{"cursor":{"name":"cursor","in":"query","description":"String that encodes all necessary information to retrieve a page.","style":"form","explode":true,"schema":{"type":"string","format":"cursor"}},"limit":{"name":"limit","in":"query","description":"Limit the number of results (per page).","style":"form","explode":true,"schema":{"type":"integer","default":50}},"sort":{"name":"sort","in":"query","description":"Sorting fields separated by comma. Default order is Ascending (ASC), minus(-) should be used in front of field name for Descending (DESC) order.","style":"form","explode":true,"schema":{"type":"string"},"example":"createdAt,-name"}},"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}}}}