The TowerOps GraphQL API provides a flexible, strongly-typed interface for querying and managing your network infrastructure. Request exactly the data you need in a single request — no over-fetching, no under-fetching.
The GraphQL API uses the same authentication as the <.link navigate={~p"/docs/api"} class="text-blue-600 hover:text-blue-500 dark:text-blue-400">REST API and provides equivalent functionality with the added benefit of nested queries and precise field selection.
Authenticate using a Bearer token in the Authorization header.
API tokens can be created in your organization settings.
Authorization: Bearer <%= @sample_token %>
All GraphQL requests are sent as POST to a single endpoint:
POST https://app.towerops.net/api/graphql
Send a JSON body with a query field
and optional variables:
curl -X POST https://app.towerops.net/api/graphql \
-H "Authorization: Bearer <%= @sample_token %>" \
-H "Content-Type: application/json" \
-d '{"query": "{ devices { id name ipAddress status } }"}'
List all devices. Optionally filter by site or status.
| Argument | Type | Description |
|---|---|---|
| siteId | ID | Filter by site |
| status | String | Filter by status (up, down, unknown) |
| limit | Int | Max results (default: 100) |
{
devices(siteId: "uuid", status: "up") {
id
name
ipAddress
status
lastCheckedAt
monitoringEnabled
snmpEnabled
deviceRole
site {
id
name
location
}
}
}
Get a single device by ID.
{
device(id: "device-uuid") {
id
name
ipAddress
status
description
snmpVersion
snmpPort
checkIntervalSeconds
site { id name }
}
}
List all sites for the organization.
{
sites {
id
name
description
location
snmpVersion
snmpCommunity
insertedAt
}
}
Get a single site by ID.
{ site(id: "site-uuid") { id name location } }
List alerts. Filter by status or device.
| Argument | Type | Description |
|---|---|---|
| status | String | active, acknowledged, or resolved |
| deviceId | ID | Filter by device |
| limit | Int | Max results (default: 100) |
{
alerts(status: "active", limit: 10) {
id
alertType
message
triggeredAt
acknowledgedAt
resolvedAt
deviceId
device {
id
name
ipAddress
}
acknowledgedByEmail
}
}
{
agents {
id
name
enabled
lastSeenAt
lastIp
isCloudPoller
deviceCount
metadata
}
}
# Single agent
{ agent(id: "agent-uuid") { id name enabled deviceCount } }
{
organization {
id
name
slug
subscriptionPlan
useSites
snmpVersion
snmpCommunity
snmpPort
snmpTransport
mikrotikEnabled
mikrotikUsername
mikrotikPort
mikrotikUseSsl
defaultAgentTokenId
}
}
{
members {
id
email
role
insertedAt
}
}
{
integrations {
id
provider
enabled
syncIntervalMinutes
lastSyncedAt
lastSyncStatus
}
}
{
activity(limit: 20) {
summary
detail
timestamp
severity
deviceName
siteName
link
type
}
}
Get time-series metrics for a device.
| Argument | Type | Description |
|---|---|---|
| deviceId | ID! | Required device ID |
| sensorType | String | Filter by sensor type |
| timeRange | String | e.g. "24h", "72h" (default: "24h") |
{
deviceMetrics(deviceId: "device-uuid", timeRange: "48h") {
timestamp
value
status
checkName
checkType
}
}
Get SNMP interfaces for a device.
{
deviceInterfaces(deviceId: "device-uuid") {
id
ifIndex
ifName
ifDescr
ifType
ifSpeed
ifAdminStatus
ifOperStatus
ifAlias
}
}
mutation {
createDevice(input: {
ipAddress: "192.168.1.1"
name: "Core Router"
siteId: "site-uuid"
snmpEnabled: true
snmpVersion: "2c"
snmpCommunity: "public"
}) {
id
name
ipAddress
status
}
}
mutation {
updateDevice(id: "device-uuid", input: {
name: "Updated Router"
monitoringEnabled: false
}) {
id
name
monitoringEnabled
}
}
mutation {
deleteDevice(id: "device-uuid") {
success
message
}
}
mutation {
createSite(input: {
name: "Main Office"
location: "New York, NY"
snmpCommunity: "public"
}) {
id
name
location
}
}
Same pattern as device mutations.
mutation {
acknowledgeAlert(id: "alert-uuid") {
id
acknowledgedAt
acknowledgedByEmail
}
}
mutation {
resolveAlert(id: "alert-uuid") {
id
resolvedAt
}
}
Creates a new agent token. The raw token is only returned once.
mutation {
createAgent(name: "DC1 Agent") {
id
name
token
}
}
mutation { deleteAgent(id: "agent-uuid") { success message } }
mutation {
updateOrganization(input: {
name: "My Network"
useSites: true
snmpVersion: "2c"
snmpCommunity: "public"
mikrotikEnabled: true
mikrotikUsername: "admin"
mikrotikPort: 8729
mikrotikUseSsl: true
}) {
id
name
useSites
snmpVersion
mikrotikEnabled
}
}
mutation {
sendInvitation(email: "user@example.com", role: "admin") {
id
email
role
expiresAt
}
}
mutation {
updateMemberRole(id: "user-uuid", role: "admin") {
id
email
role
}
}
mutation { removeMember(id: "user-uuid") { success message } }
mutation { cancelInvitation(id: "invitation-uuid") { success message } }
mutation {
createIntegration(input: {
provider: "preseem"
enabled: true
credentials: "{\"api_key\": \"xxx\"}"
syncIntervalMinutes: 10
}) {
id
provider
enabled
}
}
mutation {
testIntegration(id: "integration-uuid") {
success
message
}
}
All field names use camelCase in GraphQL queries (Absinthe automatically converts from Elixir's snake_case).
id, name, ipAddress, description, displayOrder, status, lastCheckedAt, lastStatusChangeAt, monitoringEnabled, checkIntervalSeconds, snmpEnabled, snmpVersion, snmpCommunity, snmpCommunitySource, snmpPort, snmpTransport, snmpTransportSource, lastDiscoveryAt, lastSnmpPollAt, snmpv3SecurityLevel, snmpv3Username, snmpv3AuthProtocol, snmpv3PrivProtocol, snmpv3CredentialSource, mikrotikUsername, mikrotikPort, mikrotikSshPort, mikrotikUseSsl, mikrotikEnabled, mikrotikCredentialSource, deviceRole, deviceRoleSource, siteId, organizationId, insertedAt, updatedAt, site
id, name, description, location, displayOrder, snmpVersion, snmpCommunity, snmpPort, snmpTransport, snmpv3SecurityLevel, snmpv3Username, snmpv3AuthProtocol, snmpv3PrivProtocol, mikrotikUsername, mikrotikPort, mikrotikSshPort, mikrotikUseSsl, mikrotikEnabled, organizationId, agentTokenId, parentSiteId, insertedAt, updatedAt
id, alertType, message, triggeredAt, acknowledgedAt, resolvedAt, emailSentAt, deviceId, acknowledgedById, gaiiaImpact, insertedAt, device, acknowledgedByEmail
id, name, enabled, isCloudPoller, allowRemoteDebug, lastSeenAt, lastIp, metadata, organizationId, insertedAt, updatedAt, deviceCount
id, name, slug, subscriptionPlan, useSites, snmpVersion, snmpCommunity, snmpPort, snmpTransport, snmpv3SecurityLevel, snmpv3Username, snmpv3AuthProtocol, snmpv3PrivProtocol, mikrotikEnabled, mikrotikUsername, mikrotikPort, mikrotikSshPort, mikrotikUseSsl, defaultAgentTokenId, insertedAt, updatedAt
id, email, role, isDefault, userId, insertedAt
id, provider, enabled, syncIntervalMinutes, lastSyncedAt, lastSyncStatus, organizationId, insertedAt, updatedAt
summary, detail, timestamp, severity, icon, deviceName, siteName, link, type
DeleteResult: success (Boolean!), message (String)
TestResult: success (Boolean!), message (String)
MetricPoint: timestamp, value, status, checkName, checkType
Interface: id, ifIndex, ifName, ifDescr, ifType, ifSpeed, ifAdminStatus, ifOperStatus, ifAlias
Invitation: id, email, role, expiresAt, acceptedAt, insertedAt
AgentWithToken: id, name, enabled, token, insertedAt
curl -X POST https://app.towerops.net/api/graphql \
-H "Authorization: Bearer <%= @sample_token %>" \
-H "Content-Type: application/json" \
-d '{"query": "{ devices { id name ipAddress status site { id name location } } }"}'
curl -X POST https://app.towerops.net/api/graphql \
-H "Authorization: Bearer <%= @sample_token %>" \
-H "Content-Type: application/json" \
-d '{"query": "{ alerts(status: \"active\") { id alertType message triggeredAt device { name ipAddress } } }"}'
curl -X POST https://app.towerops.net/api/graphql \
-H "Authorization: Bearer <%= @sample_token %>" \
-H "Content-Type: application/json" \
-d '{"query": "mutation { createDevice(input: { ipAddress: \"192.168.1.1\", name: \"Core Router\", snmpEnabled: true }) { id name status } }"}'
curl -X POST https://app.towerops.net/api/graphql \
-H "Authorization: Bearer <%= @sample_token %>" \
-H "Content-Type: application/json" \
-d '{"query": "mutation { acknowledgeAlert(id: \"alert-uuid\") { id acknowledgedAt } }"}'
curl -X POST https://app.towerops.net/api/graphql \
-H "Authorization: Bearer <%= @sample_token %>" \
-H "Content-Type: application/json" \
-d '{
"query": "query GetDevice($id: ID!) { device(id: $id) { id name ipAddress status site { name } } }",
"variables": {"id": "device-uuid"}
}'