Skip to content

Usage Reporting ​

Counts, never content. Here is every field.

Self-hosted GraphnAI deployments send GraphnAI a small usage report over HTTPS. It carries product counters: versions, scale and feature usage. It never carries identity data: no account names, domain names, SIDs, hostnames, IP addresses or free text. This page lists every field that can leave your deployment. One feature sends more than counts: automatic Microsoft Entra setup. To see the exact report your deployment would send now, open Admin > License, then select View today's report under Usage reporting.

This page is the field reference. An automated test in the product's build checks this table against the report format in both directions. The table can't drift unnoticed.

What every field means ​

Class legend: envelope (build and platform), identity (identifiers for the deployment or the customer organization, never a person), lifecycle (license state), inventory (graph scale), sync, feature (product usage), user (registered platform users), error (failure counts).

FieldTypeClassExampleSourceWhy GraphnAI collects it
schemaVersionnumberenvelope2Report format versionLets the receiver change the format safely
reportTypeenumenvelopedailystartup | daily | activationWhich schedule produced this report
recordedAtstring (RFC3339)envelope2026-07-06T09:14:03ZGeneration time (UTC)Orders reports. Kept the same when a report is sent again.
versionstringenvelope0.9.2Build versionProduct version distribution
gitCommitstringenvelope28691975Build commitExact build identification
goVersionstringenvelopego1.26.4Runtime versionRuntime version distribution
platformOSstringenvelopelinuxOperating systemOperating-system distribution
platformArchstringenvelopeamd64CPU architectureCPU-architecture distribution
uptimeSecondsnumberenvelope431019Time since the server startedPuts the counts since startup on a common rate
installIdstring (UUIDv4)identity0b6cbe1c-4a1e-4c6a-9f3e-1d2b8a7c5e90Created once, stored locallyIdentifies an install (a machine), never a person
tenantIdstringidentitytnt_8f2c1aLicense subjectIdentifies the customer organization (a legal entity)
licenseIdstringidentitylic_01j9x4License instanceTells license instances apart, for renewals
licenseTierstringlifecyclepreviewLicense tierTier distribution
telemetryPolicyenumlifecyclerequiredLicense policyWhether reporting is required or optional
licenseStateenumlifecycleactiveCurrent license stateactive or read_only. Shows when installs expire and convert.
capStateenumlifecycleokWhether your directory has grown past the plan's identity limitok, grace or blocked. An install over its limit still reports active, so this is the only sign that collection is paused.
effectiveExpiresAtstring (RFC3339)lifecycle2026-08-05T14:02:11ZCurrent expiry dateRenewal timing. Empty means it never expires.
inventory.identitiesTotalnumberinventory913164CountDeployment scale
inventory.identitiesByType[].typeenuminventoryUserIdentity typeMix of identity types (a fixed list)
inventory.identitiesByType[].countnumberinventory502390CountScale per identity type
inventory.edgesTotalnumberinventory8720662CountNumber of relationships in the access graph
inventory.edgesByType[].typeenuminventoryHasPermissionRelationship typeMix of permissions and memberships (a fixed list)
inventory.edgesByType[].countnumberinventory5982520CountRelationships per type
inventory.resourcesTotalnumberinventory0CountResource scale
inventory.domainCountnumberinventory6Count onlyNumber of directories, never their names
inventory.bridgeCountnumberinventory2CountNumber of Identity Bridges
inventory.entraTenantCountnumberinventory1CountNumber of Entra ID tenants
inventory.inventorySourceenuminventorysnapshotsnapshot | liveWhich collection path produced the counts
sync.sinceLastReport[].syncTypeenumsyncdeltaSync typeMix of sync types since the last report
sync.sinceLastReport[].statusenumsyncsuccessFinal statusMix of success, partial and failed syncs
sync.sinceLastReport[].countnumbersync24CountNumber of syncs since the last report
sync.lifetime[].syncTypeenumsyncfullSync typeMix of sync types since install
sync.lifetime[].statusenumsyncsuccessFinal statusMix of outcomes since install
sync.lifetime[].countnumbersync9CountNumber of syncs since install
sync.lastFullSyncDurationMsnumbersync1477402Duration (ms)Duration of the last full sync
sync.avgDurationMsnumbersync240670Average (ms)Average sync duration since the last report
sync.maxDurationMsnumbersync1477402Maximum (ms)Slowest sync since the last report
features.selectFireExecutionsByMode[].modeenumfeaturesemi-autoRemediation modeMix of Select Fire™ modes
features.selectFireExecutionsByMode[].countnumberfeature27CountNumber of runs per mode
features.selectFireRollbacksnumberfeature5Actions with the Reverted statusNumber of undone actions
features.simulationsRunnumberfeature12Count since the server startedNumber of what-if simulations
features.agentQueriesnumberfeature44Graphne activityNumber of Graphne questions answered
features.detectionsByRule[].ruleNameenumfeatureunusual_hourDetection rule nameMix of detection rules (product names only)
features.detectionsByRule[].countnumberfeature64CountNumber of detections per rule
features.alertsOpennumberfeature9Open alertsNumber of alerts open now
users.registerednumberuser4CountNumber of registered platform users
users.byRole[].roleenumuseradminRoleRole distribution
users.byRole[].countnumberuser1CountNumber of users per role
errors.syncFailuresnumbererror1Failed countNumber of failed syncs since the last report
errors.syncPartialsnumbererror0Partial countNumber of partial syncs since the last report

Example payload ​

json
{
  "schemaVersion": 2,
  "reportType": "daily",
  "recordedAt": "2026-07-06T09:14:03Z",
  "installId": "0b6cbe1c-4a1e-4c6a-9f3e-1d2b8a7c5e90",
  "tenantId": "tnt_8f2c1a",
  "licenseId": "lic_01j9x4",
  "licenseTier": "preview",
  "telemetryPolicy": "required",
  "licenseState": "active",
  "capState": "ok",
  "effectiveExpiresAt": "2026-08-05T14:02:11Z",
  "version": "0.9.2",
  "gitCommit": "28691975",
  "goVersion": "go1.26.4",
  "platformOS": "linux",
  "platformArch": "amd64",
  "uptimeSeconds": 431019,
  "inventory": {
    "identitiesTotal": 913164,
    "identitiesByType": [ { "type": "User", "count": 502390 }, { "type": "Computer", "count": 410019 } ],
    "edgesTotal": 8720662,
    "edgesByType": [ { "type": "HasPermission", "count": 5982520 }, { "type": "MemberOf", "count": 912505 } ],
    "resourcesTotal": 0,
    "domainCount": 6,
    "bridgeCount": 2,
    "entraTenantCount": 1,
    "inventorySource": "snapshot"
  },
  "sync": {
    "sinceLastReport": [ { "syncType": "delta", "status": "success", "count": 24 } ],
    "lifetime": [ { "syncType": "full", "status": "success", "count": 9 }, { "syncType": "full_pull", "status": "success", "count": 3 } ],
    "lastFullSyncDurationMs": 1477402,
    "avgDurationMs": 240670,
    "maxDurationMs": 1477402
  },
  "features": {
    "selectFireExecutionsByMode": [ { "mode": "semi-auto", "count": 27 } ],
    "selectFireRollbacks": 5,
    "simulationsRun": 12,
    "agentQueries": 44,
    "detectionsByRule": [ { "ruleName": "unusual_hour", "count": 64 } ],
    "alertsOpen": 9
  },
  "users": { "registered": 4, "byRole": [ { "role": "admin", "count": 1 }, { "role": "operator", "count": 3 } ] },
  "errors": { "syncFailures": 1, "syncPartials": 0 }
}

What's never sent ​

This list covers the usage report. Automatic Microsoft Entra setup is separate: see Automatic Microsoft Entra setup.

The report's format can't carry identity content. It has no free-text fields and no maps, and an automated test in the product's build enforces that. GraphnAI never receives:

  • Distinguished names (DNs)
  • Account names (sAMAccountName, UPN, display names)
  • Domain names or DNS names
  • Security identifiers (SIDs)
  • Hostnames or computer names
  • IP addresses
  • Free text of any kind, including error messages
  • File paths

Domains, bridges and Entra ID tenants appear only as counts, never as names.

Per-policy behavior ​

Your license sets one of two policies. The Usage reporting card on Admin > License shows which applies.

  • Required (Public Preview and free plans): reporting is part of the license terms and is always on. The card shows "Included with your plan" and has no off switch. This page lists exactly what's sent.
  • Optional (paid plans): reporting is off by default. Nothing is sent until an administrator turns it on, on the License page. The card shows "Optional" and a switch that reads "Sharing" or "Not sharing".
  • Air-gapped: a deployment with no outbound access never reports. Under the required policy, after 14 days without a successful report, administrators see a banner. Nothing else changes: syncs, sign-ins and every feature keep working, and the license expiry stays the same.

Turning it on in the app takes effect without a server restart. If you turned it off and back on since the server started, reporting resumes with the next daily report.

Turning it off ​

For deployments under the optional policy:

  • Open Admin > License and turn off the switch under Usage reporting. It takes effect before the next daily report.
  • Whoever deploys GraphnAI can also turn it off, or on, in the server's configuration before it starts.
  • When the server's configuration sets it, the switch is disabled and says so. Whoever manages the server can remove that setting and restart the server to use the switch again.

Under the required policy, reporting can't be turned off.

The Usage reporting switch and its server setting don't control the daily update check. Only GRAPHNAI_UPDATE_CHECK does.

Outbound connectivity (for firewall teams) ​

  • Host and port: api.graphnai.com:443 (HTTPS, standard public TLS certificates).
  • Schedule: a report 5 to 15 minutes after the server starts, then one every 23 to 25 hours. A one-time report follows the first successful sync.
  • Size: usually 2 to 8 KiB, with a hard limit of 32 KiB.
  • Retries: each report is tried up to 3 times. A report that still fails waits, for up to 30 days, and is sent later. The card shows how many are waiting.
  • Update check: the daily check for a new release uses the same host, but it's a separate request that carries no report. It sends only the server version in its User-Agent.
  • Direction: outbound only. Each report is signed with a key derived from your license, so the receiver can check where it came from. The usage report never carries the license itself. Automatic Microsoft Entra setup is the one exception, described below.

Automatic Microsoft Entra setup ​

Setup with Sign in with Microsoft, adding an Entra ID tenant and updating an app registration go through GraphnAI's sign-in service at api.graphnai.com. During these sign-ins only, your server sends the service your license and the return address of your GraphnAI server, which can contain an internal host name.

This differs from usage reporting in these ways:

  • It isn't counts-only, and the usage reporting setting doesn't control it.
  • Your usage reports are signed with a key derived from your license. Anyone who can read the license where GraphnAI's sign-in service receives it can derive that key.
  • It happens only when you start one of these sign-ins. Nothing is sent otherwise.

If you don't want to send the license, use Use an existing app registration and add the permissions in the Microsoft Entra admin center. The manual path sends nothing to GraphnAI. Your browser must also reach https://api.graphnai.com over HTTPS for the automatic path.

The Usage reporting card ​

The card on Admin > License shows the policy and whether reporting is on. A status line shows when the last report went out: "Last sent", "No report sent yet" or "Not sending". When reports fail, it says so and names the fix: "Reports aren't reaching GraphnAI. Allow outbound HTTPS to api.graphnai.com." Under the required policy, it adds the date to fix it by.

Under the required policy, after 14 days without a report, a banner reads "Usage reports haven't reached GraphnAI since {date}, and your license requires them." Only administrators see it. You can dismiss it for the rest of your browser session.

See your exact report ​

On Admin > License, select View today's report under Usage reporting. The Today's usage report dialog shows the exact report this deployment would send now. It works under every policy, including when reporting is off. Viewing it sends nothing.

Optional-class metrics ​

None defined yet. An optional class is reserved for future metrics that you choose to share, such as performance distributions or posture totals. It's empty today. Each metric will get a row on this page before GraphnAI collects it.