REST API Access
Synopsis
Exposes DataStream's management operations over a versioned REST API, so resources can be created and managed programmatically instead of through the web interface. A request authenticates with either of two credentials: an API token that you create and govern from the web interface, or a PowerShell sign-in session from the VirtualMetric PowerShell module or Cloud Shell.
The web interface has two surfaces for the API:
- API Tokens — a tab under
Organization >Settings where you generate, manage, regenerate, and delete the tokens that authenticate API requests. Covered in the sections below. - Show template — a drawer on the Create screens of most resources, with a Template tab (the resource as a Bicep template) and an API request tab that renders a ready-to-run command (PowerShell or Bash) calling the public API (
/api/v1) to create the same resource. See Show Template.
The API is served under the base path /api/v1. The full, interactive endpoint reference is published as a Swagger document — see API Reference.
Authentication
Every API request authenticates with a bearer token in the Authorization header:
Authorization: Bearer <token>
The token is one of two kinds:
- An API token carries the permissions of the single role assigned to it when it was created. The API enforces that role on every request.
- A PowerShell sign-in session acts as the user who approved it: their role, their access to tenants and their email on every audit row apply, exactly as in the web interface. It works in one tenant at a time, and is created by
Connect-VMetricor by opening Cloud Shell. See PowerShell.
Either way, an operation succeeds only if the credential's role grants the required permission. The API returns 401 Unauthorized when the token is missing, unrecognized, or expired.
An API token acts as no user. When it acknowledges or resolves an alert, the alert names it API Token: <name>, as the audit log does. See Alerts.
Both kinds share the same plan gate: a tenant without REST API access refuses API tokens and PowerShell sign-ins alike.
To obtain a token, generate one from the API Tokens tab. The full token value is shown only once, at creation time; afterward only a masked form is available.
Treat API tokens as secrets. Anyone holding a token can call the API with that token's role permissions until the token expires or is deleted. Store tokens in a secure location and regenerate them if you suspect exposure.
API Tokens
An API token is a credential that authenticates REST API requests. Each token has a name, an optional description, an assigned role that determines its permissions, and an optional time limit after which it stops working.
Accessing API Tokens
To open the API token management interface:
- Click the hamburger menu in the top left corner.
- Select
Organization >Settings . - Open the
API Tokens tab.
API Tokens Table
The table lists every API token in the current organization:
- Token Name — Human-readable identifier. Click to open the token detail drawer.
- Description — Optional free-text note.
- Token — The masked token value. Tokens are hidden by default; clicking the show icon reveals the token value.
- Time Limit — The expiration date, or Indefinite when no time limit is set.
- Status — Active or Expired. A token with a time limit moves to Expired automatically once that time is reached.
Controls
Above the table, the
Actions Menu
On the right side of each row, the actions menu provides:
Manage API token — Opens the token detail page.Delete API token — Prompts for confirmation; see Regenerate and Delete.
Create an API Token
Click
Token Settings
Token name — Required. Between 3 and 128 characters.Description — Optional free-text note (up to 500 characters).
Token Configuration
API Key expiration — Optional. LeaveSet expiration unchecked to create a token that never expires. When checked, the checkbox label changes toSet API token time limit and anAPI token expiration field appears — choose a preset (8 hours, 24 hours, 1 week, 1 month) or a custom date and time. After the expiration date, the token is disabled.Assign role — Required. Select one role from the existing custom roles or the pre-defined API roles. The token inherits this role's permissions.
You can assign only a role whose permissions you already hold. The check compares permission sets rather than role names, so your own role — and any pre-defined API role whose permissions you hold in full — is a valid choice, with the exception of Owner noted below, while a role carrying a permission you lack is refused with 403 API_TOKEN_ROLE_NOT_GRANTABLE. Working in a managed tenant as an MSSP user, you can assign that tenant's roles provided you hold MSSP_SWITCH in your own organization.
The Owner role cannot be assigned to an API token.
Review and Create
Review the summary of the preceding steps — Token Name, Description, Token Time Limit, and Assign Role. Use
Save Token
The token is created and displayed. Use the reveal icon to show the value, the copy control to copy it, or
The full token value is shown only on this step. You will not be able to see or retrieve it again later. Copy or download it before leaving the page.
API Token Details
Click a token's Token Name in the table, then
General Overview
Name andDescription — Editable. ClickManage token details to modify.- An information panel shows the read-only
Created andLast updated timestamps.
Token Configuration
Token Time Limit — Read-only. The expiration set at creation cannot be changed from this page.Assigned Role — Editable. ClickManage token configuration to assign a different role. The same restriction applies as at creation: you can select only a role whose permissions you already hold.Regenerate API token — Invalidates the current token value and issues a new one. The link appears only after clickingManage token configuration to enter edit mode; see Regenerate and Delete.
Activity Logs
An audit trail of actions performed on this token, with the columns
Regenerate and Delete
Regenerate — On the Token Configuration tab, click
Delete — Select
Both Regenerate and Delete break any integration currently using the token. Update every application that relies on a token before regenerating or deleting it.
Show Template
The Template and API request drawer shows the resource you are creating as a Bicep template, and the equivalent REST API request. It appears on the Review step of the Create flow for the following resources:
- Directors and Clusters
- Devices and Agent enrollment templates
- Targets
- Datasets and Profiles
- Advanced Routes
- Pipelines
- Vault secrets and provider configurations
- Library grok patterns, schemas, lookup tables, scripts and samples
- Alert rules, rule actions and detection rules
- Enrollment templates
- Roles (API request tab only)
On the review step, click
The Template tab shows the resource as a Bicep template, with
The
- The HTTP method and endpoint path for the resource (for example,
POST /devices). - A
PowerShell tab and aBash tab, each containing a copyable command that reproduces the request, populated with the values from the form. A secret you typed shows as a placeholder named after its field, for example<password>. The detection wizard prints one command per rule. - A
View API tokens button that opens the API Tokens tab, and aView API docs button that opens the Swagger reference.
Each command starts by setting BASE_URL, already filled in with this host's /api/v1, and API_TOKEN, set to <your API token>: replace it with a token from the API Tokens tab before you run the command. For example, the Bash command to create a device:
BASE_URL="https://datastream.example.com/api/v1"
API_TOKEN="<your API token>"
curl -X POST "$BASE_URL/devices" \
-H "Authorization: Bearer $API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "my-device"
}'
The equivalent PowerShell command:
$BASE_URL = "https://datastream.example.com/api/v1"
$API_TOKEN = "<your API token>"
$headers = @{
"Authorization" = "Bearer $API_TOKEN"
}
$body = @'
{
"name": "my-device"
}
'@
Invoke-RestMethod -Method POST -Uri "$BASE_URL/devices" `
-Headers $headers `
-ContentType "application/json" `
-Body $body
The request runs only if the supplied token's role grants the permission the endpoint requires.
On a plan without REST API access, the API request tab shows the upgrade prompt instead of the commands; the Template tab is unaffected.
API Resources
The Public API v1 registers the following resource groups under /api/v1. Each group supports standard CRUD operations; the full request and response schemas are defined in the Swagger reference.
| Resource | Base path |
|---|---|
| Directors | /api/v1/directors |
| Clusters | /api/v1/clusters |
| Devices | /api/v1/devices |
| Agents | /api/v1/agents |
| Targets | /api/v1/targets |
| Datasets | /api/v1/datasets |
| Profiles | /api/v1/profiles |
| Pipelines, with their children and staging | /api/v1/pipelines |
| Quick Routes | /api/v1/quickroutes |
| Advanced Routes | /api/v1/advancedroutes |
| Library | /api/v1/library/{kind} |
| Content Hub | /api/v1/contenthub |
| Alert rules | /api/v1/alert-rules |
| Alerts | /api/v1/alerts |
| Rule actions | /api/v1/rule-actions |
| Detection rules | /api/v1/detections |
| Enrollment templates | /api/v1/enrollment-templates |
| Deployment resources | /api/v1/deployments/resources |
| Vault | /api/v1/vault |
| Audit | /api/v1/audit |
| Users | /api/v1/users |
| Roles | /api/v1/roles |
| Tenant | /api/v1/tenant |
Pipelines, clusters, quick routes, the Library, Content Hub, alert rules, rule actions, detection rules and enrollment templates speak the JSON a Bicep template writes for the resource. A read by id answers {id, name, resourceType, properties}, and a create or update takes {name, properties}. A write is validated as a template is, and each route needs the permissions of the console action it stands for. The Library's {kind} is one of grokpatterns, schemas, lookups, scripts, samples, snmpvendors and sensitivedatarules. A pipeline write through the API is committed and merged directly, unless the request sets review: true to leave the commit for a reviewer.
Alert rules need the monitoring.rules feature, detection rules monitoring.detections, and enrollment templates enrollment. Rule actions have no feature gate, as in the console. Alert rules and rule actions also have PUT /{id}/status, which enables or disables them as the console's toggle does.
Targets, directors and agents accept the fields the console sends:
- Targets —
relations(the directors or clusters to publish to; without it a target goes to every director),libraries,proxyOptionsanddetectionRuleIds. - Directors —
stage,tokensandtokenEnabled.propertiesis required and must carryproxy_tls.mode:self-signed,customoroffloaded. - Agents —
description,tagsandcredentialIds. On update, a list left out keeps its value.
Deployment resources deploy resources given in that same form as a one-off template: POST /deployments/resources deploys them, POST /deployments/resources/preview shows what the engine would change, and POST /deployments/resources/read reads their current state. The PowerShell module writes through these routes, so that -WhatIf shows the engine's real change.
Health, Pipeline Tests and Search
These routes read what the console's health views, unit tests and Search page read. The PowerShell health, pipeline test and search cmdlets call them.
| Route | What it does | Permissions |
|---|---|---|
GET /devices/{id}/health | A device's health | STATS_READ, DEVICE_READ, DIRECTOR_READ, TARGET_READ, PIPELINE_READ |
GET /directors/{id}/health | A director's health | STATS_READ, DIRECTOR_READ, DEVICE_READ, TARGET_READ |
GET /targets/{id}/health | A target's health | STATS_READ, TARGET_READ |
GET /pipelines/{id}/tests | A pipeline's unit tests, with their last status | PIPELINE_READ |
POST /pipelines/{id}/tests/run | Runs a pipeline's unit tests | PIPELINE_READ |
GET /search/sources | The sources a search can read | LIVEDATA_READ |
POST /search/run | Reads the rows of one source | LIVEDATA_READ |
The health routes take their window as from and to, in Unix seconds. Without them, the window is the last hour, and a to in the future is brought back to now. A window is 299 days long at the most and cannot start before 1970. A longer or earlier window, or a from after to or in the future, is refused with 400.
POST /search/run treats the query as a filter, not a program. The source applies the time range and the filters it can, and the answer's warnings say what of the query was not applied. See PowerShell for what each source applies.
Alerts
While an alert is Open or Acknowledged, its rule raises no new alert for the same resource. When the rule triggers again, the existing alert counts the repeat instead. So a team that tracks alerts somewhere else, such as in Jira issues, has to resolve them in DataStream too. Otherwise the next trigger on that resource raises no alert. These routes let a script or an automation list, acknowledge and resolve alerts. Each action goes through the same checks as in the console, and writes the same timeline entry and audit row. See Alerts.
The routes need the monitoring.alerts feature. The PowerShell alert cmdlets call them.
| Route | What it does | Permissions |
|---|---|---|
GET /alerts | Lists alerts, newest first. Filters: status (open, acknowledged, resolved, or active for open and acknowledged together), severity, resourceType, ruleType, ruleId, resourceId, search, searchRuleTypes, searchLabelRuleTypes and ticket. search is part of the resource's name, the name of the device a log source's alert belongs to, the rule's name or the rule type, ignoring case; disk utilization also finds disk_utilization. searchRuleTypes takes comma-separated resourceType:ruleType pairs, such as director:memory_utilization,device:memory_utilization, and keeps only alerts of those rule types; with search set, an alert must also match it. searchLabelRuleTypes takes the same form and also keeps alerts of those rule types that search does not match; without search it changes nothing. A pair names the alert's resource type (director, device or target) and its rule type, as the alert list returns them. A list holds at most 200 pairs, and one that is not such pairs is refused with 400 INVALID_QUERY naming the parameter. Apart from searchLabelRuleTypes, which widens search, the filters combine by AND | ALERT_READ |
GET /alerts/{id} | One alert, with its acknowledgement and resolution: when, the note, and who acted | ALERT_READ |
PUT /alerts/{id}/acknowledge | Acknowledges an open alert, with an optional note. Any other alert is refused with 409 ALERT_NOT_ELIGIBLE | ALERT_EDIT |
DELETE /alerts/{id}/acknowledge | Removes the acknowledgement: an acknowledged alert goes back to open. Any other alert is refused with 409 ALERT_NOT_ELIGIBLE | ALERT_EDIT |
PUT /alerts/{id}/resolve | Resolves an open or acknowledged alert. A note of up to 200 characters is required. An alert already resolved is refused with 409 ALERT_ALREADY_RESOLVED | ALERT_EDIT |
PUT /alerts/acknowledge | Acknowledges up to 500 alerts, given as ids, with one optional note | ALERT_EDIT |
PUT /alerts/resolve | Resolves up to 500 alerts, given as ids, with one required note | ALERT_EDIT |
- Several alerts at once.
PUT /alerts/acknowledgeandPUT /alerts/resolvealways answer200to a well-formed request, even when some alerts are refused. Each refused alert is listed infailed, with its code. An emptyidsis refused with400. - Tickets. Each alert carries
tickets: the Jira issue keys, and the Freshservice or Freshdesk ticket ids, that its rule's actions opened or commented on.ticket=OPS-123finds the alerts behind one, ignoring case. One issue can hold several alerts, when a notification grouped them or a later alert was added to the issue as a comment. - How the value was measured. An alert's
triggerConditionhas two optional fields, on alerts from rules that compare a value with a threshold. Alerts raised before they were added have neither.aggregationsays how the value was formed from the time period's readings:average(a Director's CPU, memory and disk usage),every_reading(every reading was past the threshold, and the value is the one closest to it: a Director's queue usage in Percentage mode) orpeak(the highest reading: a Director's queue usage in Size mode, target queue usage, target delivery lag, consumer lag, the slowest disk sync, the slowest write to the store and the slowest witness answer); other rules leave it out.measuredOnsays what the value was measured on, as{ "host": "dir-02", "volume": "/data", "stream": "sender" }, each part optional:hostis the Director machine (one for each replica),volumethe disk's volume or mount point (the disk rule only), andstreamthe pipeline queue,ingester,routerorsender, with-persistenton a Director that keeps its queues on disk (the queue rule in Percentage mode only). Only a Director's CPU, memory and disk rules and its queue rule in Percentage mode setmeasuredOn. While an alert is Open or Acknowledged, each evaluation updates the value and both fields to the latest time period; the timeline's triggered entry keeps the first. - Who acted. A PowerShell or Cloud Shell session acts as its user. An API token acts as no user, so the alert names it
API Token: <name>, as the audit log does: inby, on the alert's timeline and in the console.
For example, a Jira automation that runs when an issue is closed can resolve the issue's alerts:
set -o pipefail
ids=$(curl -sf "$BASE_URL/alerts?ticket=OPS-123&status=active&itemCount=100" -H "Authorization: Bearer $API_TOKEN" | jq -c '[.items[].id]') || exit 1
[ "$ids" = "[]" ] || curl -sf -X PUT "$BASE_URL/alerts/resolve" -H "Authorization: Bearer $API_TOKEN" -H 'Content-Type: application/json' \
-d '{"ids":'"$ids"',"note":"Closed in Jira OPS-123"}'
The second call is skipped when none of the issue's alerts is still active, because an empty ids is refused.
Data Usage
GET /usage reads how much data was ingested over a window, in bytes and events, as the console's Usage and Limits screen counts it. It can split the total by tenant, by UTC day, by device and by source, in any mix, and lists the rows by bytes, largest first. The PowerShell Get-VMetricUsage cmdlet calls it.
| Route | What it does | Permissions |
|---|---|---|
GET /usage | Data usage over a window, split by groupBy | USAGE_READ, and also STATS_READ and DEVICE_READ to group by device or source |
- The window.
fromandtoare Unix seconds. Without them the window is the last 7 days. A window can be 90 days at most, because usage is kept for 90 days. Atoin the future is read as now. tenantId. Left out, you read your own tenant. A main tenant can give the id of one of its subtenants, orallfor itself and every subtenant. A subtenant can read only itself, andallmeans itself too. Any other id gets404 TENANT_NOT_FOUND_ERROR, with the same answer whether or not the id exists.groupBytakestenant,day,deviceandsource, separated by commas. The default istenant.dayis the UTC date (YYYY-MM-DD). When the window does not start or end at midnight UTC, the first and the last day count only the part of the day inside the window.- The answer is
{items, total, from, to}, paged withpageNumberanditemCount(20 rows by default, 100 at most). Pass the sametoon every page: without it, the end of the window moves on between requests, and the groups can change place as their bytes grow.totalis the number of groups. Every row hasbytes,eventsandkey. Besides those, a row has only the fields of the groups you asked for:tenantIdandtenantName,day,deviceId,deviceNameanddeviceType, andsource. - What
sourceholds depends on the device type. For syslog, TCP, UDP, HTTP and Splunk HEC devices, it is the sender's IP address; HTTP and Splunk HEC devices take it fromX-Forwarded-Forwhen a proxy sets one. Other devices name what their input reads: a Kafka topic, an Event Hub, a NATS subject, a blob or S3 object path, a poller's endpoint, an agent's file path, or the device itself. It is empty for a device that names nothing, such as a Windows agent's event logs.
API Reference
The complete endpoint reference is published as an interactive Swagger document at /api/v1/swagger/index.html on your DataStream host. It lists every available resource, request and response schema, and the permissions each endpoint requires. The