openapi: 3.2.0
info:
version: 0.7.0
title: Aeris IoT Watchtower™ Devices API
description: '## Introduction
The Aeris IoT Watchtower™ API provides access to resources such as real-time events, aggregated events, risk assessment reports, and device group operations.'
termsOfService: https://www.aeris.com/services-terms-of-use/
contact:
email: support@aeris.net
url: https://www.aeris.com/support/
license:
name: Aeris License
url: https://www.aeris.com/services-terms-of-use/
x-audience: external-public
servers:
- url: https://watchtower-api-prd.aeriscloud.com
security:
- oAuth2ClientCredentials: []
tags:
- name: Devices
description: 'Endpoints for Devices (IMEI changes) and per-device deep forensics analytics: Data Transactions, Data Volume, DNS Queries, Destination Endpoints, IP Flow Metrics.'
paths:
/watchtower/v1/devices/imei-change:
get:
summary: Retrieve Devices' Last IMEI changes
description: This endpoint provides a list of Devices' last IMEI changes within the time range.
operationId: getDevicesChanges
parameters:
- $ref: '#/components/parameters/authorization'
- $ref: '#/components/parameters/accountId'
- $ref: '#/components/parameters/startTime'
- $ref: '#/components/parameters/endTime'
- $ref: '#/components/parameters/offset'
- $ref: '#/components/parameters/limit'
tags:
- Devices
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/PagedDeviceImeiChanges'
'400':
$ref: '#/components/responses/400'
'401':
$ref: '#/components/responses/401'
'403':
$ref: '#/components/responses/403'
'429':
$ref: '#/components/responses/429'
'500':
$ref: '#/components/responses/500'
/watchtower/v1/devices/{deviceId}/imei-change:
get:
summary: Retrieve IMEI change history of a device
description: This endpoint provides IMEI change history for a device within the time range.
operationId: getDeviceChanges
parameters:
- $ref: '#/components/parameters/authorization'
- $ref: '#/components/parameters/accountId'
- $ref: '#/components/parameters/deviceId'
- $ref: '#/components/parameters/startTime'
- $ref: '#/components/parameters/endTime'
- $ref: '#/components/parameters/offset'
- $ref: '#/components/parameters/limit'
tags:
- Devices
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/PagedDeviceImeiChanges'
'400':
$ref: '#/components/responses/400'
'401':
$ref: '#/components/responses/401'
'403':
$ref: '#/components/responses/403'
'404':
$ref: '#/components/responses/404'
'429':
$ref: '#/components/responses/429'
'500':
$ref: '#/components/responses/500'
/watchtower/v1/devices/flow-aggregates/metrics/search:
post:
summary: Get Device Metrics Chart
description: 'Returns hourly time-series of device network metrics for a single device. Use `metricGroup` to select which group of metrics to retrieve:
- `DATA_TRANSACTIONS` — average data per transaction
(`avgMoDataBytes`, `avgMtDataBytes`).
- `DATA_VOLUME` — total data volume
(`sumMoDataBytes`, `sumMtDataBytes`).
- `DNS_QUERIES` — DNS activity metrics
(`privateOccurrences`, `publicOccurrences`).
Optional DNS filter fields: `isPublicDns`, `domainHosts`, `domainHostsOperation`.
- `DESTINATION_ENDPOINTS` — unique destination count
(`uniqueServerIpCount`).
- `IP_FLOWS` — IP flow event count (`occurrences`).
Optional IP-flow filter fields: `sourceIp`, `sourcePort`, `destinationPort`.
Only metric fields belonging to the requested group are populated in the response; all other metric fields are `null`. A `400` is returned if group-specific filter fields are used with the wrong group.'
operationId: getDeviceFlowAggregatesMetrics
tags:
- Devices
parameters:
- $ref: '#/components/parameters/authorization'
- $ref: '#/components/parameters/accountId'
- $ref: '#/components/parameters/startTime'
- $ref: '#/components/parameters/endTime'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/DeviceMetricsChartRequest'
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/DeviceMetricsChartResponse'
'400':
$ref: '#/components/responses/400'
'401':
$ref: '#/components/responses/401'
'403':
$ref: '#/components/responses/403'
'413':
$ref: '#/components/responses/413'
'429':
$ref: '#/components/responses/429'
'500':
$ref: '#/components/responses/500'
/watchtower/v1/devices/flow-aggregates/search:
post:
summary: Get Flow Aggregates Table
description: Returns a paginated breakdown of network flow aggregates for a specific device, grouped by destination endpoint (server FQDN, IP, protocol, port), including occurrence counts and total MO/MT/combined byte volumes per group. Scope the query to a device via `iccid` in the request body and apply optional filters by destination FQDN, IP, application protocol, or port.
operationId: getDeviceFlowAggregatesTable
tags:
- Devices
parameters:
- $ref: '#/components/parameters/authorization'
- $ref: '#/components/parameters/accountId'
- $ref: '#/components/parameters/startTime'
- $ref: '#/components/parameters/endTime'
- $ref: '#/components/parameters/offset'
- $ref: '#/components/parameters/limit'
- $ref: '#/components/parameters/sort'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/DeviceFlowTableRequest'
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/PagedFlowAggregatesTable'
'400':
$ref: '#/components/responses/400'
'401':
$ref: '#/components/responses/401'
'403':
$ref: '#/components/responses/403'
'413':
$ref: '#/components/responses/413'
'429':
$ref: '#/components/responses/429'
'500':
$ref: '#/components/responses/500'
/watchtower/v1/devices/dns-queries/search:
post:
summary: Get DNS Queries Table
description: Returns a paginated breakdown of DNS Queries for a specific device, grouped by DNS server (FQDN, IP, protocol, port, public/private type). Scope to a device via `iccid`, optionally filter by DNS FQDN/IP, protocol, port, or public/private type. Use `domainHosts` with `domainHostsOperation` to include or exclude specific DNS servers (max 1000 entries); `domainHostsOperation` defaults to `in` when omitted.
operationId: getDeviceDnsQueriesTable
tags:
- Devices
parameters:
- $ref: '#/components/parameters/authorization'
- $ref: '#/components/parameters/accountId'
- $ref: '#/components/parameters/startTime'
- $ref: '#/components/parameters/endTime'
- $ref: '#/components/parameters/offset'
- $ref: '#/components/parameters/limit'
- $ref: '#/components/parameters/sort'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/DnsQueriesTableRequest'
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/PagedDnsQueriesTable'
'400':
$ref: '#/components/responses/400'
'401':
$ref: '#/components/responses/401'
'403':
$ref: '#/components/responses/403'
'413':
$ref: '#/components/responses/413'
'429':
$ref: '#/components/responses/429'
'500':
$ref: '#/components/responses/500'
/watchtower/v1/devices/ip-flows/search:
post:
summary: Search Device IP Flows
description: 'Returns a paginated list of raw IP flow records for a specific device, with per-flow timing, source/destination endpoint, and data volume detail. Scope to a device via `iccid` and filter optionally by destination/source FQDN, IP, protocol, or port. Default sort: `startTime:asc`.
**Distinct from `POST /watchtower/v1/ip-flows/search`:** - This endpoint is **device-scoped** via `iccid` and returns raw per-flow
metric records (timing, bytes, source/destination) without enforcement context.
- The account-level `/ip-flows/search` searches across all devices and returns
structured `BLOCKED`/`ALLOWED` flow DTOs with policy enforcement detail.'
operationId: getDeviceIpFlows
tags:
- Devices
parameters:
- $ref: '#/components/parameters/authorization'
- $ref: '#/components/parameters/accountId'
- $ref: '#/components/parameters/startTime'
- $ref: '#/components/parameters/endTime'
- $ref: '#/components/parameters/offset'
- $ref: '#/components/parameters/limit'
- $ref: '#/components/parameters/sort'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/DeviceIpFlowFilter'
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/PagedIpFlowMetricsTable'
'400':
$ref: '#/components/responses/400'
'401':
$ref: '#/components/responses/401'
'403':
$ref: '#/components/responses/403'
'413':
$ref: '#/components/responses/413'
'429':
$ref: '#/components/responses/429'
'500':
$ref: '#/components/responses/500'
components:
schemas:
DeviceMetricsChartRequest:
allOf:
- $ref: '#/components/schemas/DeviceDnsFilter'
- type: object
required:
- interval
- metricGroup
properties:
interval:
type: string
description: Time bucket size in ISO 8601 duration format. Only `PT1H` is currently supported.
example: PT1H
metricGroup:
$ref: '#/components/schemas/MetricGroup'
sourceIp:
type: string
description: Filter by source (device) IP address. Valid only for the `IP_FLOWS` metric group; a `400` is returned if used with any other group.
sourcePort:
type: integer
description: Filter by source (device) port number. Valid only for the `IP_FLOWS` metric group; a `400` is returned if used with any other group.
destinationPort:
type: integer
description: Filter by destination server port number. Valid only for the `IP_FLOWS` metric group; a `400` is returned if used with any other group.
DeviceFlowTableRequest:
$ref: '#/components/schemas/DeviceFlowFilter'
total:
type: integer
format: int64
description: Total number of items available.
example: 1
minimum: 0
offset:
description: Position in pagination.
type: integer
format: int32
default: 0
minimum: 0
deviceId:
description: Internal Device ID.
type: integer
format: int32
example: 10407778
minimum: 0
limit:
type: integer
format: int32
description: Number of items to retrieve (10000 max).
minimum: 1
maximum: 10000
default: 20
DeviceImeiChange:
type: object
properties:
deviceId:
$ref: '#/components/schemas/deviceId'
iccid:
$ref: '#/components/schemas/iccid'
imei:
$ref: '#/components/schemas/imei'
previousImei:
$ref: '#/components/schemas/imei'
changeTime:
$ref: '#/components/schemas/dateTime'
deviceType:
description: Device type info derived from IMEI/TAC.
type: string
example: Modem
deviceBrand:
description: Device brand info derived from IMEI/TAC.
type: string
example: Apple
deviceModel:
description: Device model derived info from IMEI/TAC.
type: string
example: iPhone 7
required:
- iccid
- imei
- previousImei
- changeTime
MetricGroup:
type: string
description: 'Selects which group of metrics to retrieve for the `/devices/flow-aggregates/metrics/search` endpoint. Each group maps to a fixed set of response fields:
`DATA_TRANSACTIONS` — `avgMoDataBytes`, `avgMtDataBytes`.
`DATA_VOLUME` — `sumMoDataBytes`, `sumMtDataBytes`.
`DNS_QUERIES` — `privateOccurrences`, `publicOccurrences`. DNS filter fields apply.
`DESTINATION_ENDPOINTS` — `uniqueServerIpCount`.
`IP_FLOWS` — `occurrences`. IP-flow filter fields apply.'
enum:
- DATA_TRANSACTIONS
- DATA_VOLUME
- DNS_QUERIES
- DESTINATION_ENDPOINTS
- IP_FLOWS
PagedFlowAggregatesTable:
allOf:
- $ref: '#/components/schemas/DeepForensicsPagedBase'
- type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/FlowAggregatesTableRow'
accountId:
description: Account Id.
type: integer
format: int32
example: 10407
minimum: 0
PagedIpFlowMetricsTable:
allOf:
- $ref: '#/components/schemas/DeepForensicsPagedBase'
- type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/IpFlowMetricsTableRow'
DeepForensicsPagedBase:
type: object
properties:
total:
type: integer
description: Total number of matching records across all pages.
offset:
type: integer
limit:
type: integer
PagedDnsQueriesTable:
allOf:
- $ref: '#/components/schemas/DeepForensicsPagedBase'
- type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/DnsQueriesTableRow'
DeviceMetricsChartRow:
type: object
description: One time-bucket row in the device metrics chart response. Only the fields corresponding to the requested `metrics` are populated; others are omitted.
properties:
eventHour:
type: string
format: date-time
description: Start of the time bucket (UTC).
avgMoDataBytes:
type:
- number
- 'null'
format: double
description: Average mobile-originated data bytes per transaction.
avgMtDataBytes:
type:
- number
- 'null'
format: double
description: Average mobile-terminated data bytes per transaction.
sumMoDataBytes:
type:
- integer
- 'null'
format: int64
description: Total mobile-originated data bytes in the time bucket.
sumMtDataBytes:
type:
- integer
- 'null'
format: int64
description: Total mobile-terminated data bytes in the time bucket.
uniqueServerIpCount:
type:
- integer
- 'null'
description: Count of unique destination server IPs in the time bucket.
privateOccurrences:
type:
- integer
- 'null'
description: Count of private DNS queries in the time bucket.
publicOccurrences:
type:
- integer
- 'null'
description: Count of public DNS queries in the time bucket.
occurrences:
type:
- integer
- 'null'
description: Count of IP flow events in the time bucket.
DeviceMetricsChartResponse:
type: object
description: Response for the device metrics chart endpoint. Contains all matching time-series rows; no pagination.
properties:
data:
type: array
items:
$ref: '#/components/schemas/DeviceMetricsChartRow'
Error:
type: object
properties:
code:
type: integer
description: HTTP code
example: 500
message:
type: string
description: Error message
example: An error encountered in processing the request
timestamp:
type: string
description: ISO DateTime
example: '2025-06-02 09:01:53.678'
path:
type: string
description: Endpoint path at which the error occured
example: /watchtower/v1/events
traceId:
type: string
description: Trace Id
example: ed81f29f-ea9b-4099-aa00-f8ed40b7a567
PagedDeviceImeiChanges:
allOf:
- $ref: '#/components/schemas/Pagination'
- type: object
properties:
data:
type: array
description: Array of IMEI change events
items:
$ref: '#/components/schemas/DeviceImeiChange'
DnsQueriesTableRequest:
$ref: '#/components/schemas/DeviceDnsFilter'
iccid:
description: Integrated Circuit Card Identifier.
type: string
minLength: 18
maxLength: 22
example: '891004234814455936'
dateTime:
description: ISO 8601 date time
type: string
format: date-time
example: '2021-07-04T17:36:47Z'
Pagination:
type: object
properties:
total:
$ref: '#/components/schemas/total'
offset:
$ref: '#/components/schemas/offset'
limit:
$ref: '#/components/schemas/limit'
DeviceIpFlowFilter:
type: object
description: Filter parameters for device-scoped IP Flow Metrics queries. `iccid` is required to scope the query to a single device.
required:
- iccid
properties:
iccid:
type: string
description: ICCID of the device to scope this query to.
example: '99987240680301008462'
destinationFqdn:
type: string
description: Filter by destination server FQDN.
destinationIp:
type: string
description: Filter by destination server IP address.
sourceIp:
type: string
description: Filter by source (device) IP address.
sourcePort:
type: integer
description: Filter by source (device) port number.
applicationProtocol:
type: string
description: Filter by application-layer protocol.
destinationPort:
type: integer
description: Filter by destination server port number.
networkProtocol:
type: array
description: Filter by one or more network transport protocols.
items:
type: string
enum:
- TCP
- UDP
- ICMP
example:
- TCP
- UDP
DeviceDnsFilter:
allOf:
- $ref: '#/components/schemas/DeviceFlowFilter'
- type: object
properties:
isPublicDns:
type: boolean
description: When `true`, returns only public DNS queries. When `false`, returns only private DNS queries. Omit to return both.
domainHosts:
type: array
maxItems: 1000
items:
type: string
description: List of DNS server FQDNs or IPs to match against. When `domainHostsOperation` is omitted, defaults to `in` (include).
example:
- dns.google
- 1.1.1.1
- 8.8.8.8
domainHostsOperation:
type: string
enum:
- in
- ni
default: in
description: '`in` — return only queries to hosts in the `domainHosts` list. `ni` — exclude queries to those hosts. Defaults to `in` when omitted.'
DeviceFlowFilter:
type: object
description: Filter parameters for device-scoped flow aggregate queries. `iccid` is required to scope the query to a single device.
required:
- iccid
properties:
iccid:
type: string
description: ICCID of the device to scope this query to.
example: '99987240680301008462'
destinationFqdn:
type: string
description: Filter by destination server FQDN (partial match).
example: eicar.host
destinationIp:
type: string
description: Filter by destination server IP address.
example: 103.126.211.51
applicationProtocol:
type: string
description: Filter by application-layer protocol (e.g. HTTPS, DNS, ICMP).
example: HTTPS
serverPort:
type: integer
description: Filter by destination server port number.
example: 443
networkProtocol:
type: array
description: Filter by one or more network transport protocols.
items:
type: string
enum:
- TCP
- UDP
- ICMP
example:
- TCP
- UDP
imei:
description: IMEI (International Mobile Equipment Identity) of the device.
type: string
minLength: 14
maxLength: 15
example: '86715704097269'
DnsQueriesTableRow:
type: object
properties:
serverFqdn:
type:
- string
- 'null'
serverIp:
type: string
applicationProtocol:
type: string
serverPort:
type:
- integer
- 'null'
isPrivateIp:
type: boolean
description: True when the DNS server IP is a private/RFC-1918 address.
networkProtocol:
type: string
occurrences:
type: integer
format: int64
sumMoDataBytes:
type: integer
format: int64
sumMtDataBytes:
type: integer
format: int64
sumDataBytes:
type: integer
format: int64
FlowAggregatesTableRow:
type: object
description: Per-destination endpoint aggregate row, used by the Flow Aggregates table.
properties:
serverFqdn:
type:
- string
- 'null'
serverIp:
type: string
applicationProtocol:
type: string
serverPort:
type:
- integer
- 'null'
networkProtocol:
type: string
occurrences:
type: integer
format: int64
description: Number of unique connection occurrences to this destination endpoint.
sumMoDataBytes:
type: integer
format: int64
sumMtDataBytes:
type: integer
format: int64
sumDataBytes:
type: integer
format: int64
IpFlowMetricsTableRow:
type: object
properties:
startTime:
type: string
format: date-time
endTime:
type: string
format: date-time
serverFqdn:
type:
- string
- 'null'
serverIp:
type: string
deviceIp:
type: string
devicePort:
type:
- integer
- 'null'
serverPort:
type:
- integer
- 'null'
networkProtocol:
type: string
applicationProtocol:
type: string
sumMoDataBytes:
type: integer
format: int64
sumMtDataBytes:
type: integer
format: int64
sumDataBytes:
type: integer
format: int64
occurrences:
type: integer
parameters:
startTime:
name: startTime
in: query
required: true
description: The start timestamp. (inclusive)
example: '2021-07-01T06:30:00Z'
schema:
$ref: '#/components/schemas/dateTime'
endTime:
name: endTime
in: query
required: true
description: The end timestamp. (exclusive)
example: '2021-07-05T06:30:00Z'
schema:
$ref: '#/components/schemas/dateTime'
sort:
name: sort
in: query
description: Use sort=comma-separated-fields[:asc|desc] to sort the result.
example: deviceId,updateTime:desc
schema:
type: string
accountId:
name: X-Watchtower-Account-Id
in: header
description: Account Id
required: true
schema:
$ref: '#/components/schemas/accountId'
example: 1002000010
offset:
name: offset
in: query
description: The position in pagination. Specifies the starting row offset into the result set returned. For example, if the page size (limit) is 10, then to select the second page, pass the offset as 10 to retrieve items 11 to 20.
Search parameters must be consistent across pages.
schema:
$ref: '#/components/schemas/offset'
authorization:
name: Authorization
in: header
description: Bearer Token for authentication
required: true
schema:
type: string
pattern: ^Bearer [A-Za-z0-9-._~+/]+=*$
example: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ...
deviceId:
name: deviceId
in: path
required: true
schema:
$ref: '#/components/schemas/deviceId'
limit:
name: limit
in: query
description: The number of items to retrieve per page (10000 max).
schema:
$ref: '#/components/schemas/limit'
responses:
'429':
description: Too many requests.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
code: 429
message: 'Rate Limit Exceeded (XX) for clientId: XXXXXX. Please retry after XXX seconds'
timestamp: 2025-06-01 13:28:03.967000
path: /watchtower/v1/...
traceId: c3db9d7a432317363c8bc5ddb5aadf4b
'401':
description: Not authorized.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
code: 401
message: Unauthorized
timestamp: 2025-06-01 13:28:03.967000
path: /watchtower/v1/...
traceId: c3db9d7a432317363c8bc5ddb5aadf4b
'403':
description: Forbidden.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
code: 403
message: Forbidden
timestamp: 2025-06-01 13:28:03.967000
path: /watchtower/v1/...
traceId: c3db9d7a432317363c8bc5ddb5aadf4b
'400':
description: Bad Request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
code: 400
message: Bad Request
timestamp: 2025-06-01 13:28:03.967000
path: /watchtower/v1/...
traceId: c3db9d7a432317363c8bc5ddb5aadf4b
'404':
description: Not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
code: 404
message: Not found
timestamp: 2025-06-01 13:28:03.967000
path: /watchtower/v1/...
traceId: c3db9d7a432317363c8bc5ddb5aadf4b
'413':
description: Requested data too large
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
code: 413
message: Requested data too large. Please use /watchtower/v1/.../export for requesting larger amounts of data
timestamp: 2025-06-01 13:28:03.967000
path: /watchtower/v1/...
traceId: c3db9d7a432317363c8bc5ddb5aadf4b
'500':
description: Internal Server Error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
code: 500
message: Internal Server Error
timestamp: 2025-06-01 13:28:03.967000
path: /watchtower/v1/...
traceId: c3db9d7a432317363c8bc5ddb5aadf4b
securitySchemes:
oAuth2ClientCredentials:
type: oauth2
description: This API uses OAuth 2 with the Client Credentials flow.
flows:
clientCredentials:
tokenUrl: /watchtower/v1/auth/token
scopes: {}