Deployments
Discover capacity, preview costs, and manage deployment creation, upgrades, and deletion
Set variables to auto-fill all examples and run requests in-browser.
Use api.laserdata.cloud for deployment creation, upgrades, and deletion. Use {supervisor_url} for runtime status, nodes, and credentials. See API Architecture.
Reading requires deployment:read. Creation, changes, and deletion require deployment:manage.
Discovery
Before creating a deployment, retrieve the configurations available to your plan and region.
List Available Clouds
GET/tenants/{tenant_id}/cloudsList cloud providers available to the tenant.
curl https://api.laserdata.cloud/tenants/{tenant_id}/clouds \
-H "ld-api-key: YOUR_API_KEY"List Regions
GET/tenants/{tenant_id}/clouds/{cloud}/regionsList regions available for a given cloud provider.
curl https://api.laserdata.cloud/tenants/{tenant_id}/clouds/aws/regions \
-H "ld-api-key: YOUR_API_KEY"List Available Tiers
GET/tenants/{tenant_id}/clouds/{cloud}/regions/{region}/tiersList the Compute sizes available in a region for the tenant, with resources, supported storage, and remaining counts.
curl https://api.laserdata.cloud/tenants/{tenant_id}/clouds/aws/regions/us-west-1/tiers \
-H "ld-api-key: YOUR_API_KEY"[
{
"key": "free",
"name": "Free",
"description": "Perfect for getting started.",
"available": true,
"limit": 1,
"clusters": ["standalone"],
"storages": ["network_balanced"],
"rate_limit": "100 KB/s"
},
{
"key": "large",
"name": "Large",
"available": true,
"limit": 2,
"clusters": ["cluster"],
"storages": ["local_ssd", "network_balanced"],
"rate_limit": null
}
]List Available Storage Types
GET/tenants/{tenant_id}/clouds/{cloud}/regions/{region}/storagesList the storage types available to the tenant in a region.
curl https://api.laserdata.cloud/tenants/{tenant_id}/clouds/aws/regions/us-west-1/storages \
-H "ld-api-key: YOUR_API_KEY"Create Deployments
Preview Deployment Cost
POST/tenants/{tenant_id}/divisions/{division_id}/environments/{environment_id}/deployments/previewValidate a deployment shape and return its monthly configuration price, estimated total, and technical sizing metadata without provisioning it.
curl -X POST https://api.laserdata.cloud/tenants/{tenant_id}/divisions/{division_id}/environments/{environment_id}/deployments/preview \
-H "ld-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"cloud": "aws",
"region": "us-east-1",
"managed_tier": "standard",
"tier": "small",
"storage": { "type": "network_balanced", "size": 100 },
"target_network_tput": 100,
"network_scope": "same_region",
"availability_mode": "single_az"
}'A paid preview requires managed_tier, cloud, region, and tier. A Free preview omits managed_tier and returns zero cost. Preview accepts storage, throughput, network scope, and availability without creating resources. The product determines node count, so the request has no node-count field.
The response reports cloud, region, tier, nodes, compute_profile_id, included_telemetry_days, pricing_version, monthly_base_usd, and monthly_total_usd. breakdown contains compute_usd, storage_usd, and network_usd. capacity reports shards_per_node, default_segment_bytes, min_segment_bytes, partitions_per_node_at_default_segment, and partitions_per_node_at_min_segment.
target_network_tput uses KB/s. 100 means 0.1 MB/s, and 1000 means 1 MB/s. Omit it to use the tier's default throughput estimate. If storage is omitted, preview uses 100 GB of Network Drive per node. If availability is omitted, preview uses Single AZ. Preview requires deployment:read. monthly_base_usd excludes transfer. monthly_total_usd includes estimated transfer, which is billed for actual usage. Segment-based capacity fields are diagnostic values, not guaranteed partition limits.
Create a Managed Deployment
POST/tenants/{tenant_id}/divisions/{division_id}/environments/{environment_id}/deployments/managedProvision a fully managed deployment on LaserData infrastructure.
curl -X POST https://api.laserdata.cloud/tenants/{tenant_id}/divisions/{division_id}/environments/{environment_id}/deployments/managed \
-H "ld-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "prod-cluster",
"cloud": "aws",
"region": "us-west-1",
"managed_tier": "standard",
"tier": "small",
"cluster": "cluster",
"storage": {
"type": "network_balanced",
"size": 250
},
"target_network_tput": 1000,
"network_scope": "same_region",
"availability_mode": "single_az",
"protected": true,
"encrypted": true,
"public_ip_enabled": true,
"subdomain_enabled": true,
"retention": {
"telemetry_days": 14
},
"spend_limit": 500.00
}'| Field | Required | Values / Description |
|---|---|---|
name | Yes | Deployment name |
cloud | Yes | aws or gcp |
region | Yes | Cloud region, for example us-west-1 or europe-west1 |
managed_tier | Paid | standard, performance, or enterprise. Required for every paid deployment and omitted for Free |
tier | Yes | Compute size: free, small, medium, large, xlarge, 2xlarge, 4xlarge, 8xlarge, or 16xlarge |
cluster | Yes | cluster for paid deployments. Free uses standalone |
storage.type | No | network_balanced for Network Drive or local_ssd for Local NVMe. Defaults to 100 GB of Network Drive per node |
storage.size | No | Network Drive size in GB per node, from 100 to 30,000. Local NVMe size follows the Compute size |
target_network_tput | No | Throughput estimate in KB/s. Defaults to the tier's default throughput estimate. Used for compute sizing and estimating transfer, never a transfer commitment or a rate limit on paid streaming servers |
network_scope | No | same_region (default), cross_region_same_cloud, or cross_cloud |
availability_mode | No | single_az (default) or multi_az. Multi AZ requires Enterprise |
protected | No | Enable resource protection. Default false |
encrypted | No | Enable custom key encryption of message data. Default false |
public_ip_enabled | No | Assign a static public IP. Default true |
subdomain_enabled | No | Assign a custom subdomain. Requires a public IP. Default true |
data_access_enabled | No | Turn on data access. Default true. A managed deployment without a public IP cannot use data access, so it defaults to false and rejects true |
dedicated | No | Dedicated infrastructure isolation. Requires the Enterprise plan entitlement. Default false |
retention.telemetry_days | No | Telemetry retention in days. Defaults to 14 days for Standard, 30 for Performance, or 90 for Enterprise. Free uses 7 days. Higher values are rejected |
spend_limit | No | Monthly spend monitoring threshold in USD |
Catalog presets do not override omitted creation fields. To create an Enterprise preset with Local NVMe and Multi AZ, send its storage and availability explicitly.
The endpoint returns 202 Accepted with resource IDs in ld-environment and ld-deployment. Valid payment information is required. Local NVMe requires Performance or Enterprise. Multi AZ requires Enterprise. Unsupported tier features return 400 with field_issues.
Generate BYOC Setup
POST/tenants/{tenant_id}/divisions/{division_id}/environments/{environment_id}/deployments/byoc/setupGenerate the trust policy and permissions policy needed to create a BYOC deployment. Returns cloud-specific setup instructions.
curl -X POST https://api.laserdata.cloud/tenants/{tenant_id}/divisions/{division_id}/environments/{environment_id}/deployments/byoc/setup \
-H "ld-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"cloud": "aws",
"region": "us-west-1"
}'AWS setup returns laserdata_org_id, external_id, trust_policy, and permissions_policy. GCP setup returns service-account instructions.
Validate BYOC Credentials
POST{supervisor_url}/tenants/{tenant_id}/divisions/{division_id}/environments/{environment_id}/byoc/validateValidate that the provided credentials are correctly configured before creating the deployment.
curl -X POST {supervisor_url}/tenants/{tenant_id}/divisions/{division_id}/environments/{environment_id}/byoc/validate \
-H "ld-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"cloud": "aws",
"region": "us-west-1",
"account_id": "123456789012",
"identity_arn": "arn:aws:iam::123456789012:role/LaserDataByocRole",
"external_id": "unique-external-id-123",
"vpc_id": "vpc-12345678"
}'Create a BYOC Deployment (AWS)
POST/tenants/{tenant_id}/divisions/{division_id}/environments/{environment_id}/deployments/byocDeploy to your own AWS account. Use the cloud deployment fields and an aws object with IAM role details. Managed commercial fields do not apply.
curl -X POST https://api.laserdata.cloud/tenants/{tenant_id}/divisions/{division_id}/environments/{environment_id}/deployments/byoc \
-H "ld-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "prod-byoc",
"cloud": "aws",
"tier": "large",
"cluster": "cluster",
"region": "us-east-1",
"storage": {
"type": "network_balanced",
"size": 500
},
"aws": {
"account_id": "123456789012",
"identity_arn": "arn:aws:iam::123456789012:role/LaserDataByocRole",
"external_id": "your-external-id",
"vpc_id": "vpc-0abc123def456",
"vpc_cidr": "10.0.0.0/16"
}
}'A successful request returns 202 Accepted with ld-environment and ld-deployment. See BYOC Setup for IAM configuration.
Create a BYOC Deployment (GCP)
POST/tenants/{tenant_id}/divisions/{division_id}/environments/{environment_id}/deployments/byocDeploy to your own GCP project using a service account. Pass a gcp object instead of aws.
curl -X POST https://api.laserdata.cloud/tenants/{tenant_id}/divisions/{division_id}/environments/{environment_id}/deployments/byoc \
-H "ld-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "byoc-gcp-prod",
"cloud": "gcp",
"tier": "large",
"cluster": "cluster",
"region": "europe-west1",
"storage": {
"type": "network_balanced",
"size": 100
},
"gcp": {
"project_id": "my-gcp-project-123",
"service_account_email": "[email protected]",
"vpc_name": "default"
}
}'A successful request returns 202 Accepted with ld-environment and ld-deployment.
Create a Starter Deployment
POST/tenants/{tenant_id}/divisions/{division_id}/deployments/starterCreate a Free single-node deployment on shared infrastructure for development or testing.
curl -X POST https://api.laserdata.cloud/tenants/{tenant_id}/divisions/{division_id}/deployments/starter \
-H "ld-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"cloud": "aws",
"region": "us-west-1"
}'| Field | Required | Description |
|---|---|---|
cloud | Yes | aws, gcp |
region | Yes | Cloud region |
environment_id | No | Existing environment ID to deploy into |
environment_name | No | Name for a new environment (defaults to sandbox) |
deployment_name | No | Deployment name (auto-generated if omitted) |
data_access_enabled | No | Turn on data access. Default true |
Read Deployments
List Deployments
GET/tenants/{tenant_id}/divisions/{division_id}/environments/{environment_id}/deploymentsList all deployments in an environment.
curl https://api.laserdata.cloud/tenants/{tenant_id}/divisions/{division_id}/environments/{environment_id}/deployments \
-H "ld-api-key: YOUR_API_KEY"{
"items": [
{
"id": 1,
"name": "prod-cluster",
"code": "abc123",
"variant": "managed",
"domain": "prod-cluster-abc123.laserdata.cloud",
"cloud": "aws",
"region": "us-west-1",
"tier": "large",
"cluster": "cluster",
"supervisor_url": "https://supervisor-aws-us.laserdata.cloud",
"created_at": "2025-01-15T10:30:00Z"
}
],
"page": 1,
"total_results": 1,
"total_pages": 1
}List Division Deployments
GET/tenants/{tenant_id}/divisions/{division_id}/deploymentsList the deployments of every environment in a division where the caller has deployment:read, newest first.
curl "https://api.laserdata.cloud/tenants/{tenant_id}/divisions/{division_id}/deployments?environments=1201,1202&name=telemetry&page=1&results=20" \
-H "ld-api-key: YOUR_API_KEY"Environments where the caller lacks deployment:read are skipped. environments takes one environment id or a comma-separated list and narrows the result to those environments. name matches part of the deployment name, ignoring case. page and results work as on every paged route.
Each row carries the fields of List Deployments plus environment_id and environment_name. supervisor_urls holds the distinct supervisor_url of every deployment that matches the filter, including deployments on other pages, so one request per address covers the whole result. A deployment without a supervisor_url adds nothing to it.
The route answers 403 when the caller has deployment:read in no environment of the division, or lacks it in a requested environment. It answers 404 when a requested environment is not part of the division. A division the caller may read without deployments returns an empty page.
{
"total_pages": 1,
"total_results": 2,
"page": 1,
"items": [
{
"id": 31842260173701377,
"name": "telemetry-eu",
"variant": "managed",
"cloud": "aws",
"area": "eu",
"region": "eu-west-1",
"tier": "large",
"supervisor_url": "https://supervisor-aws-eu.laserdata.cloud",
"environment_id": 1202,
"environment_name": "staging",
"created_at": "2026-10-02T09:00:00Z"
},
{
"id": 31842260173701121,
"name": "telemetry",
"variant": "managed",
"cloud": "aws",
"area": "us",
"region": "us-east-1",
"tier": "large",
"supervisor_url": "https://supervisor-aws-us.laserdata.cloud",
"environment_id": 1201,
"environment_name": "production",
"created_at": "2026-10-01T09:00:00Z"
}
],
"supervisor_urls": [
"https://supervisor-aws-eu.laserdata.cloud",
"https://supervisor-aws-us.laserdata.cloud"
]
}List Division Deployments With Figures (Supervisor API)
GET{supervisor_url}/tenants/{tenant_id}/divisions/{division_id}/deploymentsList the deployments of a division that one supervisor runs, with health, Iggy version, storage, connections, and session figures, filtered, sorted, and paged.
curl "{supervisor_url}/tenants/{tenant_id}/divisions/{division_id}/deployments?environments=1201,1202&name=telemetry&sort=storage_used&order=desc&results=25" \
-H "ld-api-key: YOUR_API_KEY"Each supervisor answers for the deployments it runs. List Division Deployments returns every supervisor that holds a matching deployment in supervisor_urls, so send the same query to each of them.
| Query Parameter | Description |
|---|---|
environments | Comma-separated environment ids |
deployments | Comma-separated deployment ids |
name | Part of the deployment name, ignoring case and matched literally |
health | Comma-separated states: healthy, degraded, unavailable, unknown |
sort | created_at (default), name, health, storage_used, storage_used_percent, connections, agent_sessions_active, agent_sessions, streams, or topics |
order | desc (default) or asc |
page | Page number (default 1) |
results | Items per page (default 10, from 1 to 100) |
Filters combine. The route needs deployment:read and skips environments where the caller lacks it. It answers 403 when the caller has deployment:read in no environment of the division, or lacks it in a requested environment. A supervisor cannot check that an environment belongs to the division, so for a caller who reads every environment an unknown environment id matches nothing.
Rows without a value for the sort key come last in both directions, and ties break on the deployment id in the sort direction. Names compare bytewise as UTF-8, health states in the order healthy, degraded, unavailable, unknown, and storage_used_percent compares the exact ratio of used_bytes to total_bytes. Compare ids and counters as 64-bit integers.
The reply uses the standard page fields: total_pages, total_results, page, and items, with totals alongside them. Request another page with page and results. A page beyond the last one returns empty items and preserves totals. To merge supervisors, keep a page number and unread rows for each one. Fetch its next numbered page only when its buffer is empty. Restart paging after changing filters or ordering. Live changes do not provide a snapshot across requests.
health counts the deployment's current nodes. fresh_nodes counts nodes that reported in the last 120 seconds, and serving_nodes the fresh nodes that are ready. quorum is the cluster's view-change quorum: 1 for one node, 2 for two, and n - min(ceil(n / 2), 3) + 1 otherwise. state is healthy when every node serves, degraded with quorum, unavailable without quorum while a node reports, and unknown when no node reported in the last 120 seconds. Health describes node readiness and quorum, not the leader of every partition.
iggy_version, storage, and connections come from node samples of the last 120 seconds. storage sums used and total bytes of the filesystems that hold Iggy data on the reporting nodes, other files on them included. connections sums transport connections, so a client connected to every node counts once per node. iggy_version.lowest is the lowest version reported and uniform is false when reporting nodes differ. agent_sessions holds the highest agent session counts among nodes whose agent session index is complete, never a sum. Each group has sampled_at, the time of its oldest sample, and is null when no node reports it. resources holds the deployment's stream and topic counts from the Supervisor's metadata copy with synced_at, its last metadata sync, and resyncing, which is true while Warden rebuilds the copy, so the counts are those of the last complete copy. It is null until the first sync completes. catalog counts the deployment's AGDX catalog from the last complete snapshot Warden sent, and a snapshot sent in several parts counts only once its last part arrives: saved consumer filters and the consumer groups bound to them (filter_bindings), projections of every kind with graph_projections among them, forks of the managed tables, destinations, schemas in the deployment-wide registry without dropped ones, and kv_namespaces with their kv_entries, where key-value and memory items share namespaces. synced_at is when the Supervisor received that snapshot, and catalog is null until the first one arrives.
totals cover every matching deployment of the supervisor, not only the page. health counts each state and ignores the health filter. agent_sessions sums the agent session counts of matching deployments that report them, with deployments_reporting and deployments_missing, and its counts are null when none does. resources sums the stream and topic counts the same way over deployments with a completed metadata sync, and is null when none has one.
{
"items": [
{
"deployment_id": 31842260173701121,
"environment_id": 1201,
"name": "telemetry-eu",
"status": "initialized",
"cloud": "aws",
"region": "eu-central-1",
"created_at": "2026-09-02T08:14:00Z",
"health": {
"state": "healthy",
"expected_nodes": 3,
"fresh_nodes": 3,
"serving_nodes": 3,
"quorum": 2,
"quorum_available": true,
"all_nodes_serving": true
},
"iggy_version": { "lowest": "0.9.6", "uniform": true, "nodes_reporting": 3, "sampled_at": "2026-10-17T10:00:05Z" },
"storage": { "used_bytes": 199715979264, "total_bytes": 536870912000, "nodes_reporting": 3, "sampled_at": "2026-10-17T10:00:05Z" },
"connections": { "count": 14, "nodes_reporting": 3, "sampled_at": "2026-10-17T10:00:05Z" },
"agent_sessions": { "indexed": 820, "active": 37, "streams": 3, "rebuilding": 0, "sampled_at": "2026-10-17T10:00:05Z" },
"resources": { "streams": 12, "topics": 30, "synced_at": "2026-10-17T10:00:02Z", "resyncing": false },
"catalog": {
"filters": 3,
"filter_bindings": 5,
"projections": 2,
"graph_projections": 1,
"forks": 1,
"destinations": 2,
"schemas": 4,
"kv_namespaces": 6,
"kv_entries": 1500,
"synced_at": "2026-10-17T10:00:03Z"
}
}
],
"total_pages": 1,
"total_results": 1,
"page": 1,
"totals": {
"matching": 1,
"health": { "healthy": 1, "degraded": 0, "unavailable": 0, "unknown": 0 },
"agent_sessions": {
"indexed": 820,
"active": 37,
"streams": 3,
"rebuilding": 0,
"deployments_reporting": 1,
"deployments_missing": 0
},
"resources": {
"streams": 12,
"topics": 30,
"deployments_reporting": 1,
"deployments_missing": 0
}
}
}List Division Streams (Supervisor API)
GET{supervisor_url}/tenants/{tenant_id}/divisions/{division_id}/streamsList the streams of every deployment in a division that one supervisor runs, filtered and paged.
curl "{supervisor_url}/tenants/{tenant_id}/divisions/{division_id}/streams?environments=1201&agentic=true&results=25" \
-H "ld-api-key: YOUR_API_KEY"The Supervisor answers from its copy of each deployment's stream and topic metadata, which Warden keeps current, so the route never calls a deployment. A deployment appears once its first metadata sync completes. Send the same query to every supervisor in supervisor_urls, as for List Division Deployments With Figures.
| Query Parameter | Description |
|---|---|
environments | Comma-separated environment ids |
deployments | Comma-separated deployment ids |
name | Part of the stream name, ignoring case and matched literally, at most 255 characters |
agentic | true lists only streams with an agent.sessions topic, false only the others |
projected | true lists only streams a projection reads, false only the others |
filtered | true lists only streams with a consumer group bound to a saved filter, false only the others |
page | Page number (default 1) |
results | Items per page (default 10, from 1 to 100) |
Filters combine. A name longer than 255 characters answers 400 with invalid_name, and a blank one is ignored. The route needs deployment:read and skips environments where the caller lacks it. It answers 403 when the caller has deployment:read in no environment of the division, or lacks it in a requested environment. For a caller who reads every environment an unknown environment id matches nothing. An unknown deployment id matches nothing.
Streams come in ascending order of environment id, deployment id, and stream id. The reply uses the standard page fields: total_pages, total_results, page, and items. total_results counts every matching stream of the supervisor, not only the page. A page beyond the last one returns empty items.
created_at is the stream's creation time in Iggy with microsecond precision. Its text carries 0, 3, or 6 fraction digits, as many as the value needs, so compare parsed times rather than strings. Iggy reuses the id of a deleted stream, so stream_id together with created_at identifies one stream. options holds the stream options the Supervisor stores: encryption names who chose the stream's at-rest key (stream for a key the client sent, server for a generated one) with the key fingerprint and the fingerprints of the server keys that wrap it, and is null for a stream stored in plain text. Keys never leave Iggy. options is null when the Supervisor never read the stream's options, and options_readable is false when the last change carried options it cannot read. agentic is true when the stream has a topic named agent.sessions. filters_count counts the distinct saved filters bound to consumer groups of the stream's topics, filtered_groups_count those groups, and projections_count the distinct projections that read one of its topics. They come from the deployment's last AGDX catalog snapshot and are 0 before the first one. counters holds size_bytes and messages_count as one node read them at sampled_at, never a sum over replicas, and is null until the first reading. sessions counts the agent sessions the Supervisor holds for the stream: indexed all of them and active those with the active status. sessions.synced_at is when the Supervisor last accepted the stream's session feed. sessions is null until the first one is accepted, so always for a stream that is not agentic. synced_at is the deployment's last metadata sync, not the time the counters were read. An idle sender confirms its position every minute, so synced_at stays current while the sync is healthy. resyncing is true while Warden rebuilds the deployment's copy. The rows stay listed meanwhile and are those of the last complete copy, as of synced_at.
{
"items": [
{
"deployment_id": 31842260173701121,
"environment_id": 1201,
"stream_id": 3,
"created_at": "2026-10-13T12:00:00.123456Z",
"name": "support-agents",
"topics_count": 2,
"agentic": true,
"filters_count": 1,
"filtered_groups_count": 2,
"projections_count": 1,
"options": {
"encryption": { "key_source": "server", "key_fingerprint": "f1c4a8e2", "kek_fingerprints": ["0a9b"] }
},
"options_readable": true,
"counters": { "size_bytes": 1048576, "messages_count": 800, "sampled_at": "2026-10-26T08:13:40Z" },
"sessions": { "indexed": 12, "active": 2, "synced_at": "2026-10-26T08:14:00Z" },
"synced_at": "2026-10-26T08:14:00Z",
"resyncing": false
}
],
"total_pages": 1,
"total_results": 1,
"page": 1
}List Division Topics (Supervisor API)
GET{supervisor_url}/tenants/{tenant_id}/divisions/{division_id}/topicsList the topics of every deployment in a division that one supervisor runs, with their options, filtered and paged.
curl "{supervisor_url}/tenants/{tenant_id}/divisions/{division_id}/topics?deployments=31842260173701121&name=orders" \
-H "ld-api-key: YOUR_API_KEY"| Query Parameter | Description |
|---|---|
environments | Comma-separated environment ids |
deployments | Comma-separated deployment ids |
name | Part of the topic name, ignoring case and matched literally, at most 255 characters |
projected | true lists only topics a projection reads, false only the others |
filtered | true lists only topics with a consumer group bound to a saved filter, false only the others |
page | Page number (default 1) |
results | Items per page (default 10, from 1 to 100) |
Filters, the name limit, permissions, paging, counters, synced_at, and resyncing work as in List Division Streams, and filters_count, filtered_groups_count, and projections_count count for the topic alone. Topics come in ascending order of environment id, deployment id, stream id, and topic id. Each topic names its stream with stream_id, stream_created_at, and stream_name. created_at identifies the topic the same way as for a stream, because Iggy also reuses topic ids. Both times carry microsecond precision with 0, 3, or 6 fraction digits. Partition ids run from 0 to partitions_count - 1 with no gaps.
options holds the effective topic options. message_expiry is in microseconds and null means messages never expire. max_topic_size is in bytes and null means unlimited. replication_factor is the number of nodes that store each partition, resolved when the topic was created, and null when the deployment's streaming server does not report it. Any other null option is unknown. explicit_options names the options the client set when it created or updated the topic, and every other value is a server default. options_readable is false when the last change carried options the Supervisor cannot read, so options may be out of date. options is null when the Supervisor never read the topic's options, for example when the topic was created with options it cannot read.
{
"items": [
{
"deployment_id": 31842260173701121,
"environment_id": 1201,
"stream_id": 3,
"stream_created_at": "2026-10-13T12:00:00.123456Z",
"stream_name": "support-agents",
"topic_id": 1,
"created_at": "2026-10-13T12:00:01.234567Z",
"name": "orders",
"partitions_count": 3,
"consumer_groups_count": 1,
"filters_count": 1,
"filtered_groups_count": 1,
"projections_count": 1,
"options": {
"compression_algorithm": "none",
"message_expiry": 604800000000,
"max_topic_size": null,
"segment_size": 1073741824,
"durability": "replicated",
"consumer_offset_durability": "replicated",
"messages_required_to_save": 1024,
"size_of_messages_required_to_save": 1048576,
"preallocate_segments": false,
"partition_resize_policy": "mutable",
"replication_factor": 3
},
"options_readable": true,
"explicit_options": ["message_expiry"],
"counters": null,
"synced_at": "2026-10-26T08:14:00Z",
"resyncing": false
}
],
"total_pages": 1,
"total_results": 1,
"page": 1
}List Stream Topics (Supervisor API)
GET{supervisor_url}/tenants/{tenant_id}/divisions/{division_id}/deployments/{deployment_id}/streams/{stream_id}/topicsList the topics of one stream in topic id order, paged.
curl "{supervisor_url}/tenants/{tenant_id}/divisions/{division_id}/deployments/{deployment_id}/streams/3/topics?created_at=2026-10-13T12:00:00.123456Z" \
-H "ld-api-key: YOUR_API_KEY"| Query Parameter | Description |
|---|---|
created_at | The stream's created_at. A stream deleted and recreated with the same id since then answers 404 |
page | Page number (default 1) |
results | Items per page (default 10, from 1 to 100) |
Items have the same fields as in List Division Topics. The route needs deployment:read in the deployment's environment. Without any grant in that environment it answers 404 with environment_not_found, and with a grant that lacks deployment:read it answers 403. A deployment outside the organization or workspace answers 404. A stream the Supervisor has not synced, or one recreated since the given created_at, answers 404 with stream_not_found.
List Division Filters (Supervisor API)
GET{supervisor_url}/tenants/{tenant_id}/divisions/{division_id}/filtersList the saved consumer filters of every deployment in a division that one supervisor runs, filtered and paged.
curl "{supervisor_url}/tenants/{tenant_id}/divisions/{division_id}/filters?state=active&name=orders" \
-H "ld-api-key: YOUR_API_KEY"The Supervisor answers from the AGDX catalog snapshot Warden sends for each deployment, so the route never calls a deployment. A filter's policy never leaves the deployment. The Supervisor holds only its name, description, state, codec, latest revision, digest, and the consumer group that owns it. A deployment appears once its first catalog snapshot arrives. Send the same query to every supervisor in supervisor_urls.
| Query Parameter | Description |
|---|---|
environments | Comma-separated environment ids |
deployments | Comma-separated deployment ids |
name | Part of the filter name, ignoring case and matched literally, at most 255 characters |
state | active, archived, or dropped |
page | Page number (default 1) |
results | Items per page (default 10, from 1 to 100) |
Filters combine. A name longer than 255 characters answers 400. Permissions work as in List Division Streams. Filters come in ascending order of environment id, deployment id, and filter id, with the standard page fields. name is the name the caller gave the filter. A group's own filter saved before the managed backend recorded caller names shows its group's name instead. owner names the consumer group whose own policy the filter is, with stream_id, stream_name, topic_id, topic_name, group_id, and group_name, and is null for a filter saved by name. Its stream and topic names are joined by identity from the Supervisor's metadata copy, so they are current and null while the copy has no such stream or topic. Several group filters can share one name, so tell them apart by owner. bindings_count counts the consumer groups bound to any revision of the filter. state and codec are null for a value this Supervisor release does not know. synced_at is when the Supervisor received the deployment's catalog snapshot.
{
"items": [
{
"deployment_id": 31842260173701121,
"environment_id": 1201,
"filter_id": 7,
"name": "big-orders",
"description": "Orders above one hundred",
"state": "active",
"codec": "json",
"latest_revision": 2,
"latest_digest": "4f2a9c0d6e1b7a3f8c5d2e9b0a7f6c3d1e8b5a2f9c6d3e0b7a4f1c8d5e2b9a6f",
"bindings_count": 2,
"owner": null,
"created_at": "2026-10-20T09:12:00.120000Z",
"updated_at": "2026-10-24T15:40:11.875000Z",
"synced_at": "2026-10-26T08:14:03Z"
},
{
"deployment_id": 31842260173701121,
"environment_id": 1201,
"filter_id": 9,
"name": "late-orders",
"description": "",
"state": "active",
"codec": "json",
"latest_revision": 1,
"latest_digest": "9b1e4d7a2c5f8e0b3d6a9c2f5e8b1d4a7c0f3e6b9d2a5c8f1e4b7d0a3c6f9e2b",
"bindings_count": 1,
"owner": {
"stream_id": 3,
"stream_name": "support-agents",
"topic_id": 1,
"topic_name": "orders",
"group_id": 5,
"group_name": "anomaly-desk"
},
"created_at": "2026-10-24T15:41:02.004000Z",
"updated_at": "2026-10-24T15:41:02.004000Z",
"synced_at": "2026-10-26T08:14:03Z"
}
],
"total_pages": 1,
"total_results": 2,
"page": 1
}List Filter Bindings (Supervisor API)
GET{supervisor_url}/tenants/{tenant_id}/divisions/{division_id}/deployments/{deployment_id}/filters/{filter_id}/bindingsList the consumer groups bound to one saved filter of a deployment, paged.
curl "{supervisor_url}/tenants/{tenant_id}/divisions/{division_id}/deployments/{deployment_id}/filters/7/bindings" \
-H "ld-api-key: YOUR_API_KEY"| Query Parameter | Description |
|---|---|
page | Page number (default 1) |
results | Items per page (default 10, from 1 to 100) |
Bindings come in ascending order of stream id, topic id, and group id. Each one names its stream and topic by id and creation time, as in List Division Topics, with stream_name and topic_name from the Supervisor's metadata copy, null while the copy has no such stream or topic. revision and digest name the filter revision the group is pinned to. Permissions work as in List Stream Topics. A filter the deployment's catalog snapshot does not hold answers 404 with filter_not_found.
{
"items": [
{
"stream_id": 3,
"stream_created_at": "2026-10-13T12:00:00.123456Z",
"stream_name": "support-agents",
"topic_id": 1,
"topic_created_at": "2026-10-13T12:00:01.234567Z",
"topic_name": "orders",
"group_id": 2,
"group_name": "billing",
"revision": 2,
"digest": "4f2a9c0d6e1b7a3f8c5d2e9b0a7f6c3d1e8b5a2f9c6d3e0b7a4f1c8d5e2b9a6f",
"bound_at": "2026-10-24T15:41:02.004000Z"
}
],
"total_pages": 1,
"total_results": 1,
"page": 1
}List Division Projections (Supervisor API)
GET{supervisor_url}/tenants/{tenant_id}/divisions/{division_id}/projectionsList the row and graph projections of every deployment in a division that one supervisor runs, with the topics they read, filtered and paged.
curl "{supervisor_url}/tenants/{tenant_id}/divisions/{division_id}/projections?kind=graph" \
-H "ld-api-key: YOUR_API_KEY"| Query Parameter | Description |
|---|---|
environments | Comma-separated environment ids |
deployments | Comma-separated deployment ids |
name | Part of the projection name, ignoring case and matched literally, at most 255 characters |
kind | row or graph |
page | Page number (default 1) |
results | Items per page (default 10, from 1 to 100) |
The source and the rules are those of List Division Filters, including the name limit. A projection's extraction plan never leaves the deployment. Projections come in ascending order of environment id, deployment id, and projection id. kind is null for a kind this Supervisor release does not know. sources lists each topic the projection reads by stream and topic name, with stream_id, topic_id, and topic_created_at while the deployment has such a topic, and null otherwise.
{
"items": [
{
"deployment_id": 31842260173701121,
"environment_id": 1201,
"projection_id": "orders.v2",
"name": "orders",
"version": 2,
"kind": "row",
"content_type": "json",
"sources": [
{
"stream_name": "support-agents",
"topic_name": "orders",
"stream_id": 3,
"topic_id": 1,
"topic_created_at": "2026-10-13T12:00:01.234567Z"
}
],
"synced_at": "2026-10-26T08:14:03Z"
}
],
"total_pages": 1,
"total_results": 1,
"page": 1
}List Division Forks (Supervisor API)
GET{supervisor_url}/tenants/{tenant_id}/divisions/{division_id}/forksList the forks of the managed tables of every deployment in a division that one supervisor runs, filtered and paged.
curl "{supervisor_url}/tenants/{tenant_id}/divisions/{division_id}/forks?status=open" \
-H "ld-api-key: YOUR_API_KEY"| Query Parameter | Description |
|---|---|
environments | Comma-separated environment ids |
deployments | Comma-separated deployment ids |
kind | severed or continuous |
status | open, promoted, or squashed |
page | Page number (default 1) |
results | Items per page (default 10, from 1 to 100) |
The source and the rules are those of List Division Filters. A fork's rows never leave the deployment. Forks come in ascending order of environment id, deployment id, and fork id. user_id is the Iggy user that created the fork. kind and status are null for a value this Supervisor release does not know.
{
"items": [
{
"deployment_id": 31842260173701121,
"environment_id": 1201,
"fork_id": "what-if",
"parent": "main",
"kind": "severed",
"status": "open",
"user_id": 5,
"row_count": 1200,
"created_at": "2026-10-25T11:02:33.500000Z",
"synced_at": "2026-10-26T08:14:03Z"
}
],
"total_pages": 1,
"total_results": 1,
"page": 1
}List Division Agent Sessions (Supervisor API)
GET{supervisor_url}/tenants/{tenant_id}/divisions/{division_id}/agent_sessionsList the agent sessions of every agentic stream in a division that one supervisor runs, filtered and paged.
curl "{supervisor_url}/tenants/{tenant_id}/divisions/{division_id}/agent_sessions?deployments=31842260173701121&status=active&results=25" \
-H "ld-api-key: YOUR_API_KEY"The Supervisor answers from the session summaries Warden sends for each agentic stream, so the route never calls a deployment. A session's tags, events, state, memory, and graph data never leave the deployment. The Supervisor holds only the fields below. A stream's sessions appear once the Supervisor accepts its first complete session listing. Send the same query to every supervisor in supervisor_urls.
| Query Parameter | Description |
|---|---|
environments | Comma-separated environment ids |
deployments | Comma-separated deployment ids |
stream | Iggy stream id. Stream ids repeat across deployments, so pair it with one deployment |
stream_created_at | The stream's created_at, so a stream recreated with the same id matches nothing |
status | submitted, active, paused, completed, failed, canceled, or unrecognized |
agent | Agent id, matched exactly |
root | Session id of a root session, matched exactly. Returns that session and every session under it |
label | Part of the label, ignoring case and matched literally, at least three characters |
page | Page number (default 1) |
results | Items per page (default 10, from 1 to 100) |
Filters combine. The route needs deployment:read and skips environments where the caller lacks it. It answers 403 when the caller has deployment:read in no environment of the division, or lacks it in a requested environment. For a caller who reads every environment an unknown environment id matches nothing. An unknown deployment id matches nothing.
Sessions come newest first by last_event_at, then in ascending order of deployment id, stream id, and session id. The reply uses the standard page fields: total_pages, total_results, page, and items. total_results counts every matching session of the supervisor, not only the page. A page beyond the last one returns empty items.
session_id is the session's conversation id, unique within its stream. stream_id together with stream_created_at identifies the stream, as in List Division Streams, and deployment_name and stream_name come from the Supervisor's metadata copy. agent is the agent id the session's SDK reported, and it is the session's actor: the streaming server records no Iggy user for session records, so no session names one. label and namespace are cut to 255 characters. parent names the session that started this one and root the session at the top of its tree, both null for a root session. status is unrecognized for a status Warden does not know. idle and over_budget are the flags the deployment's session index reported. held counts the records held while the session was paused and not yet handled. cost_micros and budget_cost_micros are in micro-units of the deployment's configured currency, and cost_micros is summed from the session's usage records. budget_tokens and budget_cost_micros are null for a session without that budget. Times are null until they happen. synced_at is when the Supervisor last wrote the row from the deployment's session feed.
{
"items": [
{
"deployment_id": 31842260173701121,
"environment_id": 1201,
"deployment_name": "telemetry-eu",
"stream_id": 3,
"stream_created_at": "2026-10-13T12:00:00.123456Z",
"stream_name": "support-agents",
"session_id": "01JB9Q7M2Z8V3K4T6N5R0XW1YB",
"label": "safe-mode-triage",
"namespace": "operations",
"agent": "triage-agent",
"parent": "01JB9Q7M2Z8V3K4T6N5R0XW1YA",
"root": "01JB9Q7M2Z8V3K4T6N5R0XW1YA",
"status": "active",
"idle": false,
"over_budget": false,
"started_at": "2026-10-26T08:00:00.123456Z",
"ended_at": null,
"first_event_at": "2026-10-26T08:00:00.123456Z",
"last_event_at": "2026-10-26T08:12:41.002315Z",
"last_heartbeat_at": "2026-10-26T08:13:00.000412Z",
"events": 42,
"model_calls": 6,
"tool_calls": 9,
"tokens_in": 12400,
"tokens_out": 3100,
"cost_micros": 81000,
"errors": 0,
"held": 0,
"budget_tokens": 50000,
"budget_cost_micros": null,
"sdk_language": "rust",
"sdk_version": "0.9.0",
"synced_at": "2026-10-26T08:14:00Z"
}
],
"total_pages": 1,
"total_results": 1,
"page": 1
}Get Division Agent Session (Supervisor API)
GET{supervisor_url}/tenants/{tenant_id}/divisions/{division_id}/deployments/{deployment_id}/streams/{stream_id}/agent_sessions/{session_id}Read one agent session of a stream from the Supervisor's copy.
curl "{supervisor_url}/tenants/{tenant_id}/divisions/{division_id}/deployments/{deployment_id}/streams/3/agent_sessions/01JB9Q7M2Z8V3K4T6N5R0XW1YB?stream_created_at=2026-10-13T12:00:00.123456Z" \
-H "ld-api-key: YOUR_API_KEY"| Query Parameter | Description |
|---|---|
stream_created_at | The stream's created_at. A stream deleted and recreated with the same id since then answers 404 |
The reply is one session with the fields of List Division Agent Sessions. The route needs deployment:read in the deployment's environment. Without any grant in that environment it answers 404 with environment_not_found, and with a grant that lacks deployment:read it answers 403. A deployment outside the organization or workspace answers 404. A session the Supervisor does not hold answers 404 with agent_session_not_found.
List Division Agents (Supervisor API)
GET{supervisor_url}/tenants/{tenant_id}/divisions/{division_id}/agentsList the agents of every deployment in a division that one supervisor runs, with their cards and live connections, filtered and paged.
curl "{supervisor_url}/tenants/{tenant_id}/divisions/{division_id}/agents?deployments=31842260173701121&connected=true&results=25" \
-H "ld-api-key: YOUR_API_KEY"The Supervisor answers from the agent records Warden sends for each deployment, so the route never calls a deployment. A row joins three sources: the live connections each node reports, the capability cards and quarantine facts on each agentic stream's agent.registry topic, and the agent sessions the Supervisor holds. Skill input and output schemas, card metadata, connections of clients that are not agents, and message bodies never leave the deployment. A deployment appears once its first metadata sync completes. Send the same query to every supervisor in supervisor_urls.
A row is an agent's card on one agentic stream, so an agent with cards on two streams has two rows. A quarantined agent keeps a row on its stream even without a current card. An agent id that a live connection advertises, with no card on any stream of its deployment, has one row whose stream fields are null. A connection's presence names no stream, so connections match an agent by deployment and agent id, and every row of the agent shows the same connections.
Each node's Warden reads its live connections every 5 seconds and reports them when they change, and otherwise at least once a minute by default. A disconnected agent leaves with its node's next report. A node that stops reporting loses its connections after three of its report intervals, 3 minutes by default. Cards are read from the registry once a minute by default, and a stream's cards are replaced together once all of them arrive. A card past its ttl belongs to an agent that stopped, so it leaves with the next card sync. A stream's cards leave with the stream.
| Query Parameter | Description |
|---|---|
environments | Comma-separated environment ids |
deployments | Comma-separated deployment ids |
stream | Iggy stream id of the agent's card. Stream ids repeat across deployments, so pair it with one deployment. Leaves out agents without a card |
stream_created_at | The stream's created_at, so a stream recreated with the same id matches nothing. Leaves out agents without a card |
connected | true lists only agents with a live connection, false only the others |
quarantined | true lists only quarantined agents, false only the others |
search | Part of the agent id or card name, ignoring case and matched literally, from 3 to 255 characters |
page | Page number (default 1) |
results | Items per page (default 10, from 1 to 100) |
Filters combine. search is trimmed and a blank value is ignored. A shorter or longer one answers 400 with invalid_search. Permissions work as in List Division Agent Sessions.
Agents come in ascending order of deployment id, agent id, stream id, and stream creation time. The reply uses the standard page fields: total_pages, total_results, page, and items. total_results counts every matching row of the supervisor, not only the page. A page beyond the last one returns empty items.
deployment_name and stream_name come from the Supervisor's metadata copy. stream_id together with stream_created_at identifies the card's stream, as in List Division Streams. The three stream fields are null for an agent known only from a live connection. agent_id holds up to 256 characters and is never cut. name and version are the card's display name and version label, cut to 255 characters. skills lists the card's skills with skill_id, the health the agent advertises (healthy, degraded, unavailable, or unrecognized for a value Warden does not know), load in thousandths of the advertised capacity, and max_concurrency, each null when the card leaves it out. An agent without a card has null names, no skills, and quarantined set to false. quarantined is true when the agent is quarantined on that stream, so routing skips it. connected is true when at least one node holds a live connection that advertises the agent id. connections_count counts those connections and nodes lists their node ids in ascending order. active_sessions_count counts the agent's submitted, active, and paused sessions on the card's stream, or in the whole deployment for an agent without a card. card_observed_at is the time of the card's registry record, null without a card. card_expires_at is when the card goes stale, null for a card published without a ttl, which never goes stale. last_seen_at is the later of the card time and the latest connection report, null for a quarantined agent with neither. synced_at is when the Supervisor last stored the card or a node last reported the agent's connections, whichever is later.
For the live state, open the deployment in Stream UI, whose agent, client, and session views read cards, connections, and sessions from the deployment itself.
{
"items": [
{
"deployment_id": 31842260173701121,
"environment_id": 1201,
"deployment_name": "telemetry-eu",
"stream_id": null,
"stream_created_at": null,
"stream_name": null,
"agent_id": "report-writer",
"name": null,
"version": null,
"skills": [],
"quarantined": false,
"connected": true,
"connections_count": 1,
"nodes": [3],
"active_sessions_count": 0,
"card_observed_at": null,
"card_expires_at": null,
"last_seen_at": "2026-10-26T08:14:00Z",
"synced_at": "2026-10-26T08:14:00Z"
},
{
"deployment_id": 31842260173701121,
"environment_id": 1201,
"deployment_name": "telemetry-eu",
"stream_id": 3,
"stream_created_at": "2026-10-13T12:00:00.123456Z",
"stream_name": "support-agents",
"agent_id": "triage-agent",
"name": "Triage",
"version": "1.4.0",
"skills": [
{ "skill_id": "summarize", "health": "healthy", "load": 250, "max_concurrency": 4 }
],
"quarantined": false,
"connected": true,
"connections_count": 2,
"nodes": [1, 2],
"active_sessions_count": 1,
"card_observed_at": "2026-10-26T08:12:30.123456Z",
"card_expires_at": "2026-10-26T08:22:30.123456Z",
"last_seen_at": "2026-10-26T08:14:00Z",
"synced_at": "2026-10-26T08:14:00Z"
}
],
"total_pages": 1,
"total_results": 2,
"page": 1
}Get Division Agent (Supervisor API)
GET{supervisor_url}/tenants/{tenant_id}/divisions/{division_id}/deployments/{deployment_id}/agents/{agent_id}Read one agent of a deployment with its cards on every stream and its live connections from the Supervisor's copy.
curl "{supervisor_url}/tenants/{tenant_id}/divisions/{division_id}/deployments/{deployment_id}/agents/team%2Ftriage%20agent" \
-H "ld-api-key: YOUR_API_KEY"Percent-encode the agent id in the path, so team/triage agent becomes team%2Ftriage%20agent. cards holds the agent's card on every agentic stream of the deployment that has one, in ascending order of stream id and creation time, and is empty for an agent known only from a live connection. A card has the fields of List Division Agents, with observed_at and expires_at in place of card_observed_at and card_expires_at, its own active_sessions_count for that stream, and synced_at, when the Supervisor stored the stream's cards. observed_at is null for a quarantined agent without a current card. The top-level active_sessions_count counts the agent's submitted, active, and paused sessions in the whole deployment, and last_seen_at is the latest card time or connection report.
connections lists the agent's live connections in ascending order of node id and client id. client_id is the streaming server's id of the connection on its node, and user_id the Iggy user it authenticated as. transport is tcp, quic, http, websocket, or unrecognized for a value Warden does not know. address is the client address, cut to 64 characters. inbox is the topic the agent consumes its work on, as its presence names it, and null when the presence names none. first_seen_at is when the Supervisor first saw the connection advertise this agent, and confirmed_at is the node's latest report.
The route needs deployment:read in the deployment's environment. Without any grant in that environment it answers 404 with environment_not_found, and with a grant that lacks deployment:read it answers 403. A deployment outside the organization or workspace answers 404. An agent with neither a card nor a live connection answers 404 with agent_not_found, and so does every agent of a deployment whose first metadata sync has not completed.
{
"deployment_id": 31842260173701121,
"environment_id": 1201,
"deployment_name": "telemetry-eu",
"agent_id": "triage-agent",
"cards": [
{
"stream_id": 3,
"stream_created_at": "2026-10-13T12:00:00.123456Z",
"stream_name": "support-agents",
"name": "Triage",
"version": "1.4.0",
"skills": [
{ "skill_id": "summarize", "health": "healthy", "load": 250, "max_concurrency": 4 }
],
"quarantined": false,
"observed_at": "2026-10-26T08:12:30.123456Z",
"expires_at": "2026-10-26T08:22:30.123456Z",
"active_sessions_count": 1,
"synced_at": "2026-10-26T08:13:00Z"
}
],
"connections": [
{
"node_id": 1,
"client_id": 42,
"user_id": 5,
"transport": "tcp",
"address": "10.0.4.17:51522",
"inbox": "triage.work",
"first_seen_at": "2026-10-26T07:58:12.413000Z",
"confirmed_at": "2026-10-26T08:14:00Z"
},
{
"node_id": 2,
"client_id": 17,
"user_id": 5,
"transport": "quic",
"address": "10.0.5.23:40112",
"inbox": "triage.work",
"first_seen_at": "2026-10-26T08:01:40.002000Z",
"confirmed_at": "2026-10-26T08:13:55Z"
}
],
"active_sessions_count": 1,
"last_seen_at": "2026-10-26T08:14:00Z"
}Get Deployment (Main API)
GET/tenants/{tenant_id}/divisions/{division_id}/environments/{environment_id}/deployments/{deployment_id}Retrieve business metadata: protection, description, and upgrade history.
curl https://api.laserdata.cloud/tenants/{tenant_id}/divisions/{division_id}/environments/{environment_id}/deployments/{deployment_id} \
-H "ld-api-key: YOUR_API_KEY"The Main API adds code, protected, description, upgrades, data_access_revision, the number of the newest data access change it accepted, metadata_sync_enabled and metadata_sync_revision, the state and number of the newest metadata sync change it accepted, the rename state in name_revision, applied_name_revision, and rename_failure, and the move state in environment_revision, applied_environment_revision, and move_failure. Managed deployments with pricing terms include managed_tier and monthly_base. These describe their active terms and can change after an upgrade or an agreed terms update. target_network_tput reports the throughput estimate. can_upgrade reports whether the cooldown permits a change.
Get Deployment (Supervisor API)
GET{supervisor_url}/deployments/{deployment_id}Retrieve live runtime status, node IPs, active configs, and cloud networking info.
curl {supervisor_url}/deployments/{deployment_id} \
-H "ld-api-key: YOUR_API_KEY"The Supervisor adds status, network_mode, cidr, configs, nodes, aws or gcp network details, the applied data access state in data_access_enabled, data_access_revision, and data_access_rule, and the applied metadata sync state in metadata_sync_enabled and metadata_sync_revision.
Request both responses in parallel for the full deployment details.
Get Deployment Credentials
GET{supervisor_url}/deployments/{deployment_id}/credentialsRetrieve the Iggy username and password for client connections.
curl {supervisor_url}/deployments/{deployment_id}/credentials \
-H "ld-api-key: YOUR_API_KEY"{
"username": "iggy",
"password": "your-deployment-password"
}Modify Deployments
Upgrade a Deployment
POST/tenants/{tenant_id}/divisions/{division_id}/environments/{environment_id}/deployments/{deployment_id}/upgradeMove to a larger Compute size, grow Network Drive storage, or move to a higher tier. At least one of tier, storage, or managed_tier is required.
curl -X POST https://api.laserdata.cloud/tenants/{tenant_id}/divisions/{division_id}/environments/{environment_id}/deployments/{deployment_id}/upgrade \
-H "ld-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"tier": "xlarge",
"storage": {
"type": "network_balanced",
"size": 500
}
}'The endpoint returns 202 Accepted. Warden applies hardware changes asynchronously. Storage cannot shrink. This endpoint cannot change Compute or Storage on Local NVMe deployments.
A tier-only upgrade sends {"managed_tier":"performance"}. It changes commercial terms and telemetry retention without changing hardware. Monthly pricing changes from the effective time, with charges calculated for each active period. This endpoint rejects downgrades, which require agreed terms. Enterprise requires approved account features. Every upgrade requires valid payment information.
Extend a Deployment
POST/tenants/{tenant_id}/divisions/{division_id}/environments/{environment_id}/deployments/{deployment_id}/extendReserved endpoint. Adding nodes is not currently supported.
The request has a nodes array, such as [{"count": 2}], but an authorized call for an existing deployment returns cluster_extension_not_allowed. Use supported Compute or Storage upgrades instead.
Update Spend Limit
PUT/tenants/{tenant_id}/divisions/{division_id}/environments/{environment_id}/deployments/{deployment_id}/spend_limitSet or update the monthly spend monitoring threshold in USD.
curl -X PUT https://api.laserdata.cloud/tenants/{tenant_id}/divisions/{division_id}/environments/{environment_id}/deployments/{deployment_id}/spend_limit \
-H "ld-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"spend_limit": 1000.00
}'A successful request returns 200 OK. It requires environment-level deployment:manage.
Update Retention
PUT/tenants/{tenant_id}/divisions/{division_id}/environments/{environment_id}/deployments/{deployment_id}/retentionUpdate telemetry retention period for metrics, logs, and heartbeats.
curl -X PUT https://api.laserdata.cloud/tenants/{tenant_id}/divisions/{division_id}/environments/{environment_id}/deployments/{deployment_id}/retention \
-H "ld-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"retention": {
"telemetry_days": 14
}
}'A successful request returns 200 OK.
Update Data Access
PUT/tenants/{tenant_id}/divisions/{division_id}/environments/{environment_id}/deployments/{deployment_id}/data_accessTurn data access on or off for a deployment.
curl -X PUT https://api.laserdata.cloud/tenants/{tenant_id}/divisions/{division_id}/environments/{environment_id}/deployments/{deployment_id}/data_access \
-H "ld-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"data_access_enabled": true
}'While data access is on, LaserData keeps an access rule that admits its own fixed addresses to the deployment's Warden on port 443. Turning data access off removes that rule. While data access is on, Stream UI sends its requests through the Supervisor, which forwards them to Warden, so stream contents, message bodies, and query results pass through LaserData. Data access through LaserData describes the checks on each request.
A successful request returns 200 OK with no body. It requires environment-level deployment:manage and is accepted while another operation on the deployment runs, except a deletion. The Supervisor that runs the deployment applies the change after the request returns, so read the result from the Supervisor deployment details:
| Field | Description |
|---|---|
data_access_enabled | The applied value |
data_access_revision | The newest change the Supervisor applied. A change is still pending while the Main API reports a greater data_access_revision |
data_access_rule | applied when the LaserData access rule matches the applied value, pending while LaserData updates the rule, failed when the last update failed and LaserData retries it |
A managed deployment without a public IP cannot turn data access on and returns 400 with data_access_requires_public_ip. BYOC deployments without a public IP and on-premise deployments are reached through Warden outgoing data access. A deployment that is being deleted returns 400 with already_deleting_deployment for either value. The audit log records each applied change as deployment_data_access_updated.
Update Metadata Sync
PUT/tenants/{tenant_id}/divisions/{division_id}/environments/{environment_id}/deployments/{deployment_id}/metadata_syncTurn the sync of stream and topic metadata on or off for a deployment.
curl -X PUT https://api.laserdata.cloud/tenants/{tenant_id}/divisions/{division_id}/environments/{environment_id}/deployments/{deployment_id}/metadata_sync \
-H "ld-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"metadata_sync_enabled": false,
"purge_metadata": true
}'| Field | Required | Description |
|---|---|---|
metadata_sync_enabled | Yes | false stops the metadata sync of the deployment, true resumes it. New deployments sync |
purge_metadata | No | With metadata_sync_enabled set to false, also delete the stream, topic, AGDX catalog, agent, and agent session records the Supervisor holds for the deployment. The records leave the lists at once and a background job deletes them in small batches, so a large deployment never blocks other work and an interrupted deletion finishes after a restart. The deployment's activity is kept. Default false |
A caller with deployment:manage, including a built-in developer, can request this purge. It removes synced metadata only. Deployment activity and the Iggy usernames that name its actors are kept, like the organization audit log, which also retains the metadata-sync change and its purge request.
With metadata sync off, the Supervisor accepts no metadata from the deployment and chooses none of its nodes to send it, and every node's Warden stops reading and sending it once it reloads its configuration. Without purge_metadata the stream and topic lists keep showing the last synced state with its synced_at. With it, the deployment's streams, topics, catalog, agents, and agent sessions leave the lists and the deployment reports no resources or catalog. Turning sync back on before the deletion finished takes effect once it has, because no node is chosen while rows still wait for deletion. Turning sync back on continues from the position the Supervisor kept, or rebuilds the copy from the current state when the records were deleted or the change log moved on.
A successful request returns 200 OK with no body. It requires environment-level deployment:manage and is accepted while another operation on the deployment runs. The Supervisor that runs the deployment applies the change after the request returns, so read the result from the Supervisor deployment details:
| Field | Description |
|---|---|
metadata_sync_enabled | The applied value |
metadata_sync_revision | The newest change the Supervisor applied. A change is still pending while the Main API reports a greater metadata_sync_revision |
The audit log records each applied change, and each deletion of stored records, as deployment_metadata_sync_updated.
Update Deployment
PUT/tenants/{tenant_id}/divisions/{division_id}/environments/{environment_id}/deployments/{deployment_id}Update protection status, description, or display name.
curl -X PUT https://api.laserdata.cloud/tenants/{tenant_id}/divisions/{division_id}/environments/{environment_id}/deployments/{deployment_id} \
-H "ld-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"protected": true,
"description": "Production streaming cluster for analytics pipeline",
"name": "telemetry-prod"
}'Every field is optional and the request requires environment-level deployment:manage. Removing protection requires the organization owner. A successful request returns 200 OK with no body, whether or not it renames the deployment.
name renames the deployment. The new name must be unique in the environment, compared without case or punctuation and with hyphens, underscores, and spaces treated alike, so Telemetry_Prod and telemetry prod conflict with telemetry-prod. A name used in another environment is allowed. Renaming changes only the display name: the connection address, node names, certificates, and cloud resources keep the name the deployment was created with, so existing connections and connection strings keep working.
The Main API lists and deployment details show the new name at once. The Supervisor that runs the deployment applies it after the request returns, also while another operation on the deployment runs. Read whether the rename is pending, complete, or refused from the Main API deployment details:
| Field | Description |
|---|---|
name_revision | The newest rename the Main API accepted. name holds its name |
applied_name_revision | The newest rename the Supervisor applied. A rename is pending while this is lower than name_revision and rename_failure is null, and complete when they are equal |
rename_failure | null, or name_conflict when the Supervisor refused the rename at name_revision because another deployment of the environment uses the name. name then shows the name the deployment kept |
A name that is not a valid deployment name returns 400 with invalid_deployment_name. A name another deployment of the environment uses returns 400 with deployment_already_exists. A name equal to the current one changes nothing and returns 200 OK. The audit log records each applied rename as deployment_renamed.
Move a Deployment
PUT/tenants/{tenant_id}/divisions/{division_id}/environments/{environment_id}/deployments/{deployment_id}/environmentMove a deployment to another environment of the same division.
curl -X PUT https://api.laserdata.cloud/tenants/{tenant_id}/divisions/{division_id}/environments/{environment_id}/deployments/{deployment_id}/environment \
-H "ld-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"target_environment_id": 4402
}'The request requires deployment:manage in both the current and the target environment, and the target must belong to the same division. A successful request returns 200 OK with no body, also when the deployment already is in the target environment.
A move changes the environment the deployment belongs to, and with it who can read and manage the deployment. Members who can read deployments only in the previous environment lose access, and members of the target environment gain it. The deployment keeps its ID, name, connection address, nodes, certificates, cloud resources, data, and billing terms. Clients stay connected and no runtime restarts. Each node's Warden restarts once to load a credential issued for the target environment.
The Main API lists the deployment under the target environment at once, and its address under the previous environment returns 404. The Supervisor that runs the deployment applies the move after the request returns, then waits until every node reports with its new credential. If nodes have not reported, the Supervisor completes the move on a recovery sweep after the configured timeout, which defaults to 15 minutes. The sweep runs every 60 seconds. A node that has not reported by then, for example because it is offline, loads its new credential when it comes back. Read whether the move is pending, complete, or refused from the Main API deployment details. They are under the target environment while the move is pending or complete, and under the environment the deployment kept after a refusal:
| Field | Description |
|---|---|
environment_revision | The newest move the Main API accepted. The deployment is listed in its target |
applied_environment_revision | The newest move completed after all nodes reported with the new credential or the move timeout elapsed. A move is pending while this is lower than environment_revision and move_failure is null, and complete when they are equal |
move_failure | null, or name_conflict when the Supervisor refused the move at environment_revision because another deployment of the target environment uses the name. The deployment then is back in the environment it kept |
A target that does not exist or belongs to another division returns 404 with environment_not_found. A name another deployment of the target environment uses, compared as for a rename, returns 400 with deployment_already_exists. While an operation, another move, or a rename of the deployment is in progress, the request returns 409 with deployment_operation_in_progress. A rename is accepted while a move is pending, and its name must then be free in both environments. Until the move completes or is refused, the previous environment keeps the deployment's name reserved and cannot be deleted.
Records of the past keep the environment they were made in: audit entries, logs, metrics history, and billing reports of earlier periods. The audit log records each applied move as deployment_moved. Notification subscriptions stay as they are. Events after a move carry the target environment, so a subscription scoped to the previous environment no longer matches the deployment.
Delete a Deployment
DELETE/tenants/{tenant_id}/divisions/{division_id}/environments/{environment_id}/deployments/{deployment_id}Permanently delete a deployment. Protected deployments require a resource code. This action is irreversible.
curl -X DELETE "https://api.laserdata.cloud/tenants/{tenant_id}/divisions/{division_id}/environments/{environment_id}/deployments/{deployment_id}?code={protection_code}" \
-H "ld-api-key: YOUR_API_KEY"The endpoint returns 202 Accepted. Deletion permanently destroys all nodes, data, configuration, backups, and telemetry.