# Dispositivos

## Listar dispositivos

> Requiere el tipo de acceso con llave `READ` o `READ_WRITE` api.

```json
{"openapi":"3.0.3","info":{"title":"RUFUS Public REST API","version":"0.1.0"},"tags":[{"name":"Devices"}],"servers":[{"url":"https://api.runonrufus.com/v0","description":"Production (v0)"}],"security":[{"ApiKeyHeader":[]},{"XApiKeyHeader":[]}],"components":{"securitySchemes":{"ApiKeyHeader":{"type":"apiKey","in":"header","name":"api_key","description":"API key for authentication."},"XApiKeyHeader":{"type":"apiKey","in":"header","name":"x-api-key","description":"API key for authentication (alternate header)."}},"parameters":{"Page":{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1},"description":"1-based page."},"LimitDevices":{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":5000,"default":5000},"description":"Max items per page (devices)."}},"schemas":{"DevicesListResponse":{"type":"object","additionalProperties":false,"properties":{"body":{"type":"object","additionalProperties":false,"properties":{"description":{"type":"string"},"result":{"type":"array","items":{"$ref":"#/components/schemas/DeviceSummary"}},"pagination":{"$ref":"#/components/schemas/Pagination"}},"required":["description","pagination"]}},"required":["body"]},"DeviceSummary":{"type":"object","additionalProperties":false,"properties":{"deviceid":{"type":"string"},"type":{"type":"string"},"model":{"type":"string"},"alias":{"type":"string"},"firmware":{"type":"string","nullable":true},"serial_number":{"type":"string"},"last_login":{"type":"string","format":"date-time","nullable":true},"creation_date":{"type":"string","format":"date-time","nullable":true},"sessions":{"type":"integer","minimum":0},"device_status":{"type":"string","nullable":true},"battery_percentage":{"type":"integer","minimum":0,"maximum":100,"nullable":true},"charging":{"type":"boolean","nullable":true},"last_telemetry_at":{"type":"string","format":"date-time","nullable":true},"last_reported_latitude":{"type":"number","nullable":true},"last_reported_longitude":{"type":"number","nullable":true}},"required":["deviceid","type","model","alias","serial_number"]},"Pagination":{"type":"object","additionalProperties":false,"properties":{"page":{"type":"integer","minimum":1},"limit":{"type":"integer","minimum":1},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"}},"required":["page","limit","total","has_more"]},"EnvelopeAny":{"type":"object","additionalProperties":false,"properties":{"body":{"description":"Operation result body."}}},"EnvelopeNull":{"type":"object","additionalProperties":false,"properties":{"body":{"nullable":true}},"required":["body"]}},"responses":{"Forbidden":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvelopeAny"}}}},"InternalError":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvelopeNull"}}}}}},"paths":{"/devices":{"get":{"tags":["Devices"],"summary":"List devices","description":"Requires `READ` or `READ_WRITE` api key access type.","parameters":[{"$ref":"#/components/parameters/Page"},{"$ref":"#/components/parameters/LimitDevices"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevicesListResponse"}}}},"403":{"$ref":"#/components/responses/Forbidden"},"500":{"$ref":"#/components/responses/InternalError"}}}}}}
```

## Vincular (crear) dispositivo

> Requiere el tipo de acceso con llave `WRITE` o `READ_WRITE` api.

```json
{"openapi":"3.0.3","info":{"title":"RUFUS Public REST API","version":"0.1.0"},"tags":[{"name":"Devices"}],"servers":[{"url":"https://api.runonrufus.com/v0","description":"Production (v0)"}],"security":[{"ApiKeyHeader":[]},{"XApiKeyHeader":[]}],"components":{"securitySchemes":{"ApiKeyHeader":{"type":"apiKey","in":"header","name":"api_key","description":"API key for authentication."},"XApiKeyHeader":{"type":"apiKey","in":"header","name":"x-api-key","description":"API key for authentication (alternate header)."}},"schemas":{"BindDeviceRequest":{"type":"object","additionalProperties":false,"properties":{"type":{"type":"string"},"model":{"type":"string"},"serial_number":{"type":"string"},"alias":{"type":"string"},"firmware":{"type":"string"}},"required":["type","model","serial_number"]},"BindDeviceResponse":{"type":"object","additionalProperties":false,"properties":{"body":{"type":"object","additionalProperties":false,"properties":{"description":{"type":"string"},"deviceid":{"type":"string"},"already_binded":{"type":"boolean","nullable":true}},"required":["description","deviceid"]}},"required":["body"]},"EnvelopeAny":{"type":"object","additionalProperties":false,"properties":{"body":{"description":"Operation result body."}}},"EnvelopeNull":{"type":"object","additionalProperties":false,"properties":{"body":{"nullable":true}},"required":["body"]}},"responses":{"BadRequest":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvelopeAny"}}}},"Forbidden":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvelopeAny"}}}},"InternalError":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvelopeNull"}}}}}},"paths":{"/devices":{"post":{"tags":["Devices"],"summary":"Bind (create) device","description":"Requires `WRITE` or `READ_WRITE` api key access type.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BindDeviceRequest"}}}},"responses":{"201":{"description":"Device binded succesfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BindDeviceResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvelopeNull"}}}},"500":{"$ref":"#/components/responses/InternalError"}}}}}}
```

## Obtener dispositivo por ID

> Requiere el tipo de acceso con llave `READ` o `READ_WRITE` api.

```json
{"openapi":"3.0.3","info":{"title":"RUFUS Public REST API","version":"0.1.0"},"tags":[{"name":"Devices"}],"servers":[{"url":"https://api.runonrufus.com/v0","description":"Production (v0)"}],"security":[{"ApiKeyHeader":[]},{"XApiKeyHeader":[]}],"components":{"securitySchemes":{"ApiKeyHeader":{"type":"apiKey","in":"header","name":"api_key","description":"API key for authentication."},"XApiKeyHeader":{"type":"apiKey","in":"header","name":"x-api-key","description":"API key for authentication (alternate header)."}},"schemas":{"DeviceGetResponse":{"type":"object","additionalProperties":false,"properties":{"body":{"type":"object","additionalProperties":false,"properties":{"description":{"type":"string"},"result":{"$ref":"#/components/schemas/DeviceDetails"}},"required":["description"]}},"required":["body"]},"DeviceDetails":{"allOf":[{"$ref":"#/components/schemas/DeviceSummary"},{"type":"object","additionalProperties":false,"properties":{"passings":{"type":"integer","minimum":0},"last_seen":{"type":"string","format":"date-time","nullable":true},"battery_volts":{"type":"number","nullable":true},"temperature_celsius":{"type":"integer","nullable":true},"gps_accuracy_m":{"type":"number","nullable":true},"network_type":{"type":"string","nullable":true},"signal_strength":{"type":"integer","nullable":true}}}]},"DeviceSummary":{"type":"object","additionalProperties":false,"properties":{"deviceid":{"type":"string"},"type":{"type":"string"},"model":{"type":"string"},"alias":{"type":"string"},"firmware":{"type":"string","nullable":true},"serial_number":{"type":"string"},"last_login":{"type":"string","format":"date-time","nullable":true},"creation_date":{"type":"string","format":"date-time","nullable":true},"sessions":{"type":"integer","minimum":0},"device_status":{"type":"string","nullable":true},"battery_percentage":{"type":"integer","minimum":0,"maximum":100,"nullable":true},"charging":{"type":"boolean","nullable":true},"last_telemetry_at":{"type":"string","format":"date-time","nullable":true},"last_reported_latitude":{"type":"number","nullable":true},"last_reported_longitude":{"type":"number","nullable":true}},"required":["deviceid","type","model","alias","serial_number"]},"EnvelopeAny":{"type":"object","additionalProperties":false,"properties":{"body":{"description":"Operation result body."}}},"EnvelopeNull":{"type":"object","additionalProperties":false,"properties":{"body":{"nullable":true}},"required":["body"]}},"responses":{"Forbidden":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvelopeAny"}}}},"NotFound":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvelopeAny"}}}},"InternalError":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvelopeNull"}}}}}},"paths":{"/devices/{deviceid}":{"get":{"tags":["Devices"],"summary":"Get device by id","description":"Requires `READ` or `READ_WRITE` api key access type.","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceGetResponse"}}}},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}}}}
```

## Desvincular (eliminar) dispositivo

> Requiere una llave api con `allow_unbind=true`.

```json
{"openapi":"3.0.3","info":{"title":"RUFUS Public REST API","version":"0.1.0"},"tags":[{"name":"Devices"}],"servers":[{"url":"https://api.runonrufus.com/v0","description":"Production (v0)"}],"security":[{"ApiKeyHeader":[]},{"XApiKeyHeader":[]}],"components":{"securitySchemes":{"ApiKeyHeader":{"type":"apiKey","in":"header","name":"api_key","description":"API key for authentication."},"XApiKeyHeader":{"type":"apiKey","in":"header","name":"x-api-key","description":"API key for authentication (alternate header)."}},"schemas":{"UnbindDeviceResponse":{"type":"object","additionalProperties":false,"properties":{"body":{"type":"object","additionalProperties":false,"properties":{"description":{"type":"string"},"deviceid":{"type":"string"}},"required":["description","deviceid"]}},"required":["body"]},"EnvelopeAny":{"type":"object","additionalProperties":false,"properties":{"body":{"description":"Operation result body."}}},"EnvelopeNull":{"type":"object","additionalProperties":false,"properties":{"body":{"nullable":true}},"required":["body"]}},"responses":{"Forbidden":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvelopeAny"}}}},"NotFound":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvelopeAny"}}}},"InternalError":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvelopeNull"}}}}}},"paths":{"/devices/{deviceid}":{"delete":{"tags":["Devices"],"summary":"Unbind (delete) device","description":"Requires an api key with `allow_unbind=true`.","responses":{"200":{"description":"Device unbinded succesfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnbindDeviceResponse"}}}},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}}}}
```

## Informar de la telemetría/estado del dispositivo

> Requiere el tipo de acceso de clave `WRITE` o `READ_WRITE` api.
> 
> Las actualizaciones obsoletas se ignoran si `reported_at` es anterior a la `last_telemetry_at` actual.

```json
{"openapi":"3.0.3","info":{"title":"RUFUS Public REST API","version":"0.1.0"},"tags":[{"name":"Devices"}],"servers":[{"url":"https://api.runonrufus.com/v0","description":"Production (v0)"}],"security":[{"ApiKeyHeader":[]},{"XApiKeyHeader":[]}],"components":{"securitySchemes":{"ApiKeyHeader":{"type":"apiKey","in":"header","name":"api_key","description":"API key for authentication."},"XApiKeyHeader":{"type":"apiKey","in":"header","name":"x-api-key","description":"API key for authentication (alternate header)."}},"schemas":{"DeviceTelemetryRequest":{"type":"object","additionalProperties":false,"description":"At least one telemetry field is required.","properties":{"reported_at":{"type":"string","format":"date-time"},"device_status":{"type":"string"},"battery_percentage":{"type":"integer","minimum":0,"maximum":100},"battery_volts":{"type":"number","minimum":0},"charging":{"type":"boolean"},"temperature_celsius":{"type":"integer","minimum":-100,"maximum":200},"latitude":{"type":"number","minimum":-90,"maximum":90},"longitude":{"type":"number","minimum":-180,"maximum":180},"gps_accuracy_m":{"type":"number","minimum":0},"network_type":{"type":"string"},"signal_strength":{"type":"integer","minimum":-200,"maximum":200}}},"DeviceTelemetryResponse":{"type":"object","additionalProperties":false,"properties":{"body":{"type":"object","additionalProperties":false,"properties":{"description":{"type":"string"},"deviceid":{"type":"string"},"result":{"type":"object","additionalProperties":false,"properties":{"deviceid":{"type":"string"},"last_telemetry_at":{"type":"string","format":"date-time"},"device_status":{"type":"string","nullable":true},"battery_percentage":{"type":"integer","nullable":true},"battery_volts":{"type":"number","nullable":true},"charging":{"type":"boolean","nullable":true},"temperature_celsius":{"type":"integer","nullable":true},"last_reported_latitude":{"type":"number","nullable":true},"last_reported_longitude":{"type":"number","nullable":true},"gps_accuracy_m":{"type":"number","nullable":true},"network_type":{"type":"string","nullable":true},"signal_strength":{"type":"integer","nullable":true}}}},"required":["description","deviceid"]}},"required":["body"]},"EnvelopeAny":{"type":"object","additionalProperties":false,"properties":{"body":{"description":"Operation result body."}}},"EnvelopeNull":{"type":"object","additionalProperties":false,"properties":{"body":{"nullable":true}},"required":["body"]}},"responses":{"BadRequest":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvelopeAny"}}}},"Forbidden":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvelopeAny"}}}},"NotFound":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvelopeAny"}}}},"PayloadTooLarge":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvelopeAny"}}}},"InternalError":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvelopeNull"}}}}}},"paths":{"/devices/{deviceid}/status":{"patch":{"tags":["Devices"],"summary":"Report device telemetry/status","description":"Requires `WRITE` or `READ_WRITE` api key access type.\n\nStale updates are ignored if `reported_at` is older than the current `last_telemetry_at`.\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceTelemetryRequest"}}}},"responses":{"200":{"description":"Updated (or ignored if stale)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceTelemetryResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"500":{"$ref":"#/components/responses/InternalError"}}}}}}
```
