{"openapi":"3.0.1","info":{"title":"Devices API","version":"v2","description":"Entry point for device provisioning and configuration"},"servers":[{"url":"https://devices.fundamentum-iot.com"}],"components":{"securitySchemes":{"oAuthFundamentum":{"type":"oauth2","description":"See https://oauth.fundamentum-iot.com/oauth-clients for details on oauth integration.","flows":{"implicit":{"authorizationUrl":"https://oauth.fundamentum-iot.com/oauth/authorize","scopes":{}}}},"provisioningKey":{"type":"http","scheme":"bearer"},"deviceJwtKey":{"type":"http","scheme":"bearer"}},"parameters":{"projectId":{"in":"path","name":"project_id","required":true,"description":"Project's ID","schema":{"type":"integer","example":1}},"regionId":{"in":"path","name":"region_id","required":true,"description":"Region's ID","schema":{"type":"integer","example":1,"default":1}},"assetTypeId":{"in":"path","name":"asset_type_id","required":true,"description":"Asset Type's ID","schema":{"type":"integer","example":1,"default":1}},"registryId":{"in":"path","name":"registry_id","required":true,"description":"Registry's ID","schema":{"type":"integer","example":1}},"provisioningKey":{"in":"path","name":"key","required":true,"description":"Provisioning Key","schema":{"type":"string","example":"00000000-0000-0000-0000-000000000000"}},"serialNumber":{"in":"path","name":"serial_number","required":true,"description":"Device's serial number, which is case insensitive","schema":{"type":"string","example":"sn-123456-no-space"}},"serialNumberStrict":{"in":"path","name":"serial_number","required":true,"description":"Device's serial number which has to be lowercase and contain only alphanumeric characters or hyphens \"-\"","schema":{"type":"string","example":"sn-123-abc"}}},"schemas":{"RegistryIdStrict":{"type":"int","description":"The device's registry ID","example":1},"Date":{"type":"string","description":"A date in the \"yyyy-mm-dd\" format","example":"2024-02-29"},"Status":{"type":"string","description":"The response status which is either \"success\" or \"error\"","example":"success"},"SerialNumber":{"type":"string","description":"The device serial number, which is case insensitive. It must be unique in the registry.","example":"ABC123"},"SerialNumberStrict":{"type":"string","description":"The device's serial number, which is composed of lowercase alphanumeric characters and hyphens \"-\" and underscores \"_\" . It also must be unique in the registry","example":"abc123"},"PublicKey":{"type":"string","description":"Device public key","example":"-----BEGIN PUBLIC KEY-----MIIBIj...AQAB-----END PUBLIC KEY-----"},"Secret":{"type":"string","description":"Device secret. New version of public key","example":"-----BEGIN PUBLIC KEY-----MIIBIj...AQAB-----END PUBLIC KEY-----"},"Algorithm":{"type":"string","description":"Authorization algorithm. The following options are currently supported \"RS256\" and \"Password\"","example":"RS256"},"ProjectId":{"type":"integer","description":"The ID of the project associated with the device.","example":123},"RegistryId":{"type":"integer","description":"The ID of the registry.","example":123},"ErrorResponse":{"properties":{"status":{"$ref":"#/components/schemas/Status"},"message":{"type":"string","description":"The error message"},"data":{"type":"object","description":"More information about the error. This field may be empty depending on error type"}}},"Uptime":{"type":"integer","description":"Time in seconds the device has been up","example":1},"MQTT":{"type":"object","description":"MQTT configuration of the device","properties":{"host":{"type":"string","description":"MQTT Host","example":"mqtt.fundamentum.test"},"port":{"type":"string","description":"MQTT Port","example":1883}}},"DeviceTypeId":{"type":"integer","description":"Device's type","example":1},"Configuration":{"type":"object","description":"The settings currently applied on the device.","example":{}},"UndeployConfiguration":{"type":"object","description":"A requested configuration change that has not yet been confirmed by the device. The applied configuration only changes once the device confirms it, unless the update was forced.\n","example":{},"nullable":true},"MetaData":{"type":"object","description":"Free-form data attached to the device for reference. Metadata updates take effect immediately.","example":{}},"DeviceResponseContent":{"type":"object","properties":{"status":{"$ref":"#/components/schemas/Status"},"data":{"type":"object","description":"Device's data","properties":{"device_type_id":{"$ref":"#/components/schemas/DeviceTypeId"},"configuration":{"$ref":"#/components/schemas/Configuration"},"undeploy_configuration":{"$ref":"#/components/schemas/UndeployConfiguration"},"meta_data":{"$ref":"#/components/schemas/MetaData"},"mqtt":{"$ref":"#/components/schemas/MQTT"}}}}}},"responses":{"Error400":{"description":"There is an error with the request's content. For example, a field is missing or has the wrong type.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"status":"error","message":"There is an error with the request","data":{"errors":{"type":"field","msg":"Invalid value","path":"serial_number","location":"body"}}}}}},"Error403":{"description":"The user does not have the permissions to access or edit the resource","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"status":"error","message":"No permission to do this action"}}}},"Error404":{"description":"The resource does not exist","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"status":"error","message":"Resource not found"}}}},"Error409":{"description":"The request encountered a conflict with the state of the target resource","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"status":"error","message":"Authorization conflict","data":{"error":"device already provisioned"}}}}},"Error422":{"description":"The request tries to do something impossible. For example, it tries to create a resource that is already created.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"status":"error","data":{"serial_number":"The serial number has already been taken"}}}}}}},"paths":{"/status":{"get":{"operationId":"GetServiceStatus","description":"Get service's status","responses":{"200":{"description":"Service is up and running","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","description":"The response status","example":"success"},"data":{"type":"object","description":"The service's status","properties":{"version":{"type":"number","description":"The current service version","example":2},"redis_status":{"type":"string","description":"The status of the redis cache","example":"ready"},"request":{"type":"object","description":"The request's parameters"}}}}}}}}}}},"/api/{version}/swagger.json":{"get":{"operationId":"DownloadSwaggerDocumentation","description":"Downloads the json file containing the swagger documentation of the API","parameters":[{"in":"path","name":"version","description":"The version of the API. Versions 1 to 3 are currently supported","required":true,"schema":{"type":"string","example":"v3"}}],"responses":{"200":{"description":"Success"}}}},"/api/v2/projects/{project_id}/regions/{region_id}/registries/{registry_id}/devices/{serial_number}/states":{"get":{"operationId":"v2-GetDeviceStates","summary":"Get the latest states of a device","tags":["States"],"security":[{"oAuthFundamentum":[]}],"parameters":[{"$ref":"#/components/parameters/projectId"},{"$ref":"#/components/parameters/regionId"},{"$ref":"#/components/parameters/registryId"},{"$ref":"#/components/parameters/serialNumber"}],"responses":{"200":{"description":"Returns the last 25 states of the device order by time in descending order","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"$ref":"#/components/schemas/Status"},"data":{"type":"object","description":"The device's latest states"}}}}}},"400":{"$ref":"#/components/responses/Error400"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"}}}},"/api/v2/provision":{"post":{"operationId":"v2-CreateProvisioningRequest","summary":"Create a new device provisioning request.","description":"Creates a new device provisioning request for the specified project, region, and registry using the provided device serial number and access token.","tags":["Provisioning"],"requestBody":{"description":"Device provisioning request object.","required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"project_id":{"$ref":"#/components/schemas/ProjectId"},"region_id":{"type":"integer","description":"The ID of the region associated with the device.","example":1},"registry_id":{"type":"integer","description":"The ID of the registry associated with the device.","example":456},"serial_number":{"$ref":"#/components/schemas/SerialNumber"},"access_token":{"type":"string","description":"The access token required to provision the device.","example":"12345"},"public_key":{"$ref":"#/components/schemas/PublicKey"},"asset_type_id":{"type":"integer","description":"The ID of the asset type associated with the device. Defaults to 2 (IoT Device).","example":2}}}}}},"responses":{"200":{"description":"The device provisioning request was successful.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"$ref":"#/components/schemas/Status"},"data":{"type":"object","description":"The response data.","properties":{"configuration":{"type":"object","description":"The Configuration of the device","example":{}},"mqtt":{"$ref":"#/components/schemas/MQTT"}}}}}}}},"400":{"$ref":"#/components/responses/Error400"},"404":{"$ref":"#/components/responses/Error404"},"422":{"$ref":"#/components/responses/Error422"}}}},"/api/v2/projects/{project_id}/regions/{region_id}/registries/{registry_id}/devices/{serial_number}/heartbeat":{"post":{"tags":["HeartBeat"],"security":[{"oAuthFundamentum":[]}],"operationId":"v2-SendHeartbeatEvent","summary":"Send a heartbeat event","description":"Send a heartbeat event and will trigger reboot event if uptime is smaller than the last one.","parameters":[{"$ref":"#/components/parameters/projectId"},{"$ref":"#/components/parameters/regionId"},{"$ref":"#/components/parameters/registryId"},{"$ref":"#/components/parameters/serialNumber"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"uptime":{"$ref":"#/components/schemas/Uptime"}}}}}},"responses":{"200":{"description":"The heartbeat event has been sent correctly","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"$ref":"#/components/schemas/Status"}}}}}},"400":{"$ref":"#/components/responses/Error400"}}}},"/api/v2/projects/{project_id}/regions/{region_id}/registries/{registry_id}/devices/{serial_number}":{"get":{"tags":["Devices"],"security":[{"oAuthFundamentum":[]}],"operationId":"v2-GetDevice","summary":"Get device configuration","description":"Get the device's type, configuration, undeployed configuration (pending command) and metadata","parameters":[{"$ref":"#/components/parameters/projectId"},{"$ref":"#/components/parameters/regionId"},{"$ref":"#/components/parameters/registryId"},{"$ref":"#/components/parameters/serialNumber"}],"responses":{"200":{"description":"The device was found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceResponseContent"}}}},"400":{"$ref":"#/components/responses/Error400"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"}}},"post":{"tags":["Devices"],"security":[{"oAuthFundamentum":[]}],"operationId":"v2-DeleteDevice","summary":"Delete a Device","description":"Delete the device with the provided serial number","parameters":[{"$ref":"#/components/parameters/projectId"},{"$ref":"#/components/parameters/regionId"},{"$ref":"#/components/parameters/registryId"},{"$ref":"#/components/parameters/serialNumber"}],"responses":{"200":{"description":"The device was deleted successfully","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","description":"The response status which is either \"success\" or \"error\"","example":"success"}}}}}},"400":{"$ref":"#/components/responses/Error400"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"}}}},"/api/v2/projects/{project_id}/regions/{region_id}/registries/{registry_id}/devices":{"post":{"tags":["Devices"],"security":[{"oAuthFundamentum":[]}],"operationId":"v2-CreateDevice","summary":"Store a Device","description":"Store a new Device with the provided serial number into the registry","parameters":[{"$ref":"#/components/parameters/projectId"},{"$ref":"#/components/parameters/regionId"},{"$ref":"#/components/parameters/registryId"}],"requestBody":{"description":"The new device's data","required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"serial_number":{"$ref":"#/components/schemas/SerialNumber"},"name":{"type":"string","description":"Optional name for user reference only. Defaults to Serial Number when empty.","example":"12345"},"device_type_id":{"$ref":"#/components/schemas/DeviceTypeId"}}}}}},"responses":{"200":{"description":"The device was created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceResponseContent"}}}},"400":{"$ref":"#/components/responses/Error400"},"403":{"$ref":"#/components/responses/Error403"},"422":{"$ref":"#/components/responses/Error422"}}}},"/api/v2/projects/{project_id}/regions/{region_id}/registries/{registry_id}/devices/{serial_number}/set-authorization":{"post":{"tags":["Devices"],"security":[{"oAuthFundamentum":[]}],"operationId":"v2-SetDeviceAuthorization","summary":"Configure authorization for the device","description":"Upload an authorization key","parameters":[{"$ref":"#/components/parameters/projectId"},{"$ref":"#/components/parameters/regionId"},{"$ref":"#/components/parameters/registryId"},{"$ref":"#/components/parameters/serialNumber"}],"requestBody":{"description":"New authorization data","required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"authorization_type":{"$ref":"#/components/schemas/Algorithm"},"public_key":{"$ref":"#/components/schemas/PublicKey"}}}}}},"responses":{"200":{"description":"The new authorization key has successfully been uploaded","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"$ref":"#/components/schemas/Status"}}}}}},"400":{"$ref":"#/components/responses/Error400"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"}}}},"/api/v2/projects/{project_id}/regions/{region_id}/registries/{registry_id}/devices/{serial_number}/configuration":{"post":{"tags":["Devices"],"security":[{"oAuthFundamentum":[]}],"operationId":"v2-UpdateDeviceConfiguration","summary":"Update Device Configuration or Metadata","description":"Create a command to update the device configuration. Once applied, the actual device configuration will be updated in the cloud twin. Metadata updates are instantaneous.\n","parameters":[{"$ref":"#/components/parameters/projectId"},{"$ref":"#/components/parameters/regionId"},{"$ref":"#/components/parameters/registryId"},{"$ref":"#/components/parameters/serialNumber"},{"in":"query","name":"force","schema":{"type":"boolean"},"description":"Force the device configuration update without sending a command to the device"}],"requestBody":{"description":"Although the fields `configuration` or `meta_data` are marked optional, at least one of them has to be provided, otherwise it will cause an error 422.\n","required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"configuration":{"$ref":"#/components/schemas/Configuration"},"meta_data":{"$ref":"#/components/schemas/MetaData"}}}}}},"responses":{"200":{"description":"The device's configuration and/or meta data has successfully been updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceResponseContent"}}}},"400":{"$ref":"#/components/responses/Error400"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"}}}}},"tags":[]}