API Reference
Manage ingest endpoints, S3 destinations, schema views, and monitor data delivery.
Base URL: https://api.edge.mq
All requests require a Bearer JWT in the Authorization header, obtained via token exchange. The token exchange endpoint itself accepts an API key directly — no prior token needed.
The full OpenAPI spec is available at `/openapi/edgemq-openapi.json` for programmatic use.
Contents
Auth
Authentication and token management
POST /v1/token/exchange
Exchange API key for access token
Exchange a long-lived API key for a short-lived JWT access token. The returned token is scoped to a single permission level and should be used in the Authorization header for all subsequent API calls.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
api_key | string | Yes | Your EdgeMQ API key |
scope | ingest | metrics | admin |
ttl | string | No | Token lifetime as a duration string (e.g. '15m', '1h'). Defaults to 15 minutes. |
{ "api_key":: "emq_live_a1b2c3d4e5f6g7h8i9j0", "scope":: "admin", "ttl":: "15m" }
Response 200 — Token issued successfully
{ "access_token":: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzY29wZXMiOlsiYWRtaW4iXSwiaWF0IjoxNzA1MzEyNjAwLCJleHAiOjE3MDUzMTM1MDB9.signature", "token_type":: "Bearer", "expires_in":: 900 }
Errors
| Status | Description |
|---|---|
401 | Invalid API key |
403 | Scope not permitted for this API key |
422 | Validation error |
Example
curl -X POST https://api.edge.mq/v1/token/exchange \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"api_key":"emq_live_a1b2c3d4e5f6g7h8i9j0","scope":"admin","ttl":"15m"}'
Endpoints
Ingest endpoint lifecycle
POST /v1/endpoints
Create an ingest endpoint
Provision a new ingest endpoint in the specified region. Each endpoint accepts both HTTP and MQTT ingest traffic. Optionally bind an S3 destination and configure MQTT settings at creation time. DNS records and TLS certificates are provisioned automatically. The endpoint transitions from deploying to active within 2-5 minutes.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
region | string | Yes | Three-letter region code (e.g. iad, lhr, fra) |
destination_id | string (uuid) | No | Optional. UUID of an existing S3 destination to bind at creation time. Create a destination first via POST /v1/destinations, then pass its id here. |
segment_bytes | integer | No | WAL segment size in bytes (8MB - 1GB). Applies on next rotation. |
output_formats | segments | parquet | parquet_views[] |
mqtt_config | object | null | No |
{ "region":: "iad", "mqtt_config":: { "enabled":: true, "max_connections":: 5000, "keepalive_max_s":: 300, "qos_max":: 0 } }
Response 201 — Endpoint created
{ "id":: "550e8400-e29b-41d4-a716-446655440000", "region":: "iad", "status":: "deploying", "destination_id":: "b2c3d4e5-f6a7-8901-bcde-f12345678901", "destination_name":: "Production S3", "destination_status":: "valid", "created_at":: "2026-01-15T10:30:00.000Z", "dns_ipv4":: [], "dns_ipv6":: [], "segment_bytes":: 33554432, "segment_max_age_seconds":: 60, "output_formats":: [ "segments", "parquet" ], "mqtt_config":: { "enabled":: true, "max_connections":: 5000, "keepalive_max_s":: 300, "qos_max":: 0 } }
Errors
| Status | Description |
|---|---|
401 | Missing or invalid authentication token |
403 | Insufficient permissions |
422 | Request validation failed |
Example
curl -X POST https://api.edge.mq/v1/endpoints \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"region":"iad","mqtt_config":{"enabled":true,"max_connections":5000,"keepalive_max_s":300,"qos_max":0}}'
GET /v1/endpoints
List your ingest endpoints
Returns a paginated list of your ingest endpoints. Filter by status to find active, deploying, or degraded endpoints. Status is computed in real time from node health, DNS, and certificate state.
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
status | deploying | active | degraded |
limit | integer | No | Maximum number of items to return (1-200). Default: 50 |
offset | integer | No | Number of items to skip for pagination. Default: 0 |
Response 200 — Paginated list of endpoints
{ "items":: [ { "id":: "550e8400-e29b-41d4-a716-446655440000", "region":: "iad", "status":: "active", "destination_id":: "b2c3d4e5-f6a7-8901-bcde-f12345678901", "destination_name":: "Production S3", "destination_status":: "valid", "created_at":: "2026-01-15T10:30:00.000Z", "dns_ipv4":: [ "149.248.213.170" ], "dns_ipv6":: [ "2001:19f0:ac01:1d2b:5400:04ff:fe5e:39a1" ], "segment_bytes":: 33554432, "segment_max_age_seconds":: 60, "output_formats":: [ "segments", "parquet" ], "mqtt_config":: null } ], "total":: 1, "limit":: 50, "offset":: 0, "next_offset":: null }
Errors
| Status | Description |
|---|---|
401 | Missing or invalid authentication token |
422 | Request validation failed |
Example
curl -X GET https://api.edge.mq/v1/endpoints \ -H "Authorization: Bearer $TOKEN"
PATCH /v1/endpoints/{id}
Update an endpoint
Update endpoint settings such as the bound S3 destination, WAL segment size, segment max age, output formats, or MQTT configuration. Changes trigger a config refresh on ingest nodes. MQTT can be enabled or disabled per endpoint — set mqtt_config to an object to enable, or null to disable.
Path parameters
| Parameter | Type | Description |
|---|---|---|
id | string (uuid) | Endpoint ID |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
destination_id | string (uuid) | null | No |
segment_bytes | integer | null | No |
segment_max_age_seconds | integer | null | No |
output_formats | segments | parquet | parquet_views[] |
mqtt_config | object | null | No |
{ "segment_bytes":: 16777216, "output_formats":: [ "segments", "parquet" ], "mqtt_config":: { "enabled":: true, "max_connections":: 5000, "keepalive_max_s":: 300, "qos_max":: 1 } }
Response 200 — Endpoint updated
{ "id":: "550e8400-e29b-41d4-a716-446655440000", "region":: "iad", "status":: "active", "destination_id":: "b2c3d4e5-f6a7-8901-bcde-f12345678901", "destination_name":: "Production S3", "destination_status":: "valid", "created_at":: "2026-01-15T10:30:00.000Z", "dns_ipv4":: [ "149.248.213.170" ], "dns_ipv6":: [ "2001:19f0:ac01:1d2b:5400:04ff:fe5e:39a1" ], "segment_bytes":: 16777216, "segment_max_age_seconds":: 60, "output_formats":: [ "segments", "parquet", "parquet_views" ], "mqtt_config":: { "enabled":: true, "max_connections":: 5000, "keepalive_max_s":: 300, "qos_max":: 1 } }
Errors
| Status | Description |
|---|---|
401 | Missing or invalid authentication token |
403 | Insufficient permissions |
404 | Resource not found |
422 | Request validation failed |
Example
curl -X PATCH https://api.edge.mq/v1/endpoints/<id> \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"segment_bytes":16777216,"output_formats":["segments","parquet"],"mqtt_config":{"enabled":true,"max_connections":5000,"keepalive_max_s":300,"qos_max":1}}'
Destinations
S3 destination configuration and validation
POST /v1/destinations
Create an S3 destination
Register a new S3 destination with IAM role-based access. EdgeMQ assumes the provided IAM role using an external ID unique to your account. After creation, call the validate endpoint to verify connectivity.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Human-readable name (must be unique within your account) |
bucket | string | Yes | S3 bucket name |
prefix | string | No | S3 key prefix. Leading/trailing slashes are normalized. Default: |
region | string | Yes | AWS region of the S3 bucket |
role_arn | string | Yes | IAM role ARN that EdgeMQ will assume |
kms_key_arn | string | No | KMS key ARN for SSE-KMS encryption. Omit for SSE-S3. |
path_style | boolean | No | Use path-style S3 URLs Default: false |
{ "name":: "Analytics Data Lake", "bucket":: "acme-data-lake", "prefix":: "events/prod", "region":: "us-east-1", "role_arn":: "arn:aws:iam::123456789012:role/EdgeMqDelivery", "kms_key_arn":: null, "path_style":: false }
Response 201 — Destination created
{ "id":: "1f1a9a3d-3a2e-4b1a-9f6a-8f6d8a7e3c1b", "name":: "Analytics Data Lake", "bucket":: "acme-data-lake", "prefix":: "events/prod", "region":: "us-east-1", "role_arn":: "arn:aws:iam::123456789012:role/EdgeMqDelivery", "external_id":: "edgemq-abcdef0123456789", "kms_key_arn":: null, "path_style":: false, "status":: "pending", "validated_at":: null, "last_error":: null, "created_at":: "2026-01-15T10:30:00.000Z", "updated_at":: "2026-01-15T10:30:00.000Z" }
Errors
| Status | Description |
|---|---|
401 | Missing or invalid authentication token |
403 | Insufficient permissions |
409 | Destination name already exists |
422 | Request validation failed |
Example
curl -X POST https://api.edge.mq/v1/destinations \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"name":"Analytics Data Lake","bucket":"acme-data-lake","prefix":"events/prod","region":"us-east-1","role_arn":"arn:aws:iam::123456789012:role/EdgeMqDelivery","kms_key_arn":null,"path_style":false}'
POST /v1/destinations/{id}/validate
Validate S3 destination connectivity
Assumes the configured IAM role and attempts to write and delete a test object in S3 to verify permissions. On success, the destination status changes to valid. Throttled to one validation per 30 seconds per destination.
Path parameters
| Parameter | Type | Description |
|---|---|---|
id | string (uuid) | Destination ID |
Response 200 — Validation complete
{ "id":: "1f1a9a3d-3a2e-4b1a-9f6a-8f6d8a7e3c1b", "name":: "Analytics Data Lake", "bucket":: "acme-data-lake", "prefix":: "events/prod", "region":: "us-east-1", "role_arn":: "arn:aws:iam::123456789012:role/EdgeMqDelivery", "external_id":: "edgemq-abcdef0123456789", "kms_key_arn":: null, "path_style":: false, "status":: "valid", "validated_at":: "2026-01-15T10:35:00.000Z", "last_error":: null, "created_at":: "2026-01-15T10:30:00.000Z", "updated_at":: "2026-01-15T10:35:00.000Z" }
Errors
| Status | Description |
|---|---|
401 | Missing or invalid authentication token |
403 | Insufficient permissions |
404 | Resource not found |
429 | Validation throttled (max 1 per 30 seconds) |
Example
curl -X POST https://api.edge.mq/v1/destinations/<id>/validate \ -H "Authorization: Bearer $TOKEN"
GET /v1/destinations
List your S3 destinations
Returns a paginated list of your S3 destinations. Each destination includes a ref_count indicating how many endpoints reference it.
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
limit | integer | No | Maximum number of items to return (1-200). Default: 50 |
offset | integer | No | Number of items to skip for pagination. Default: 0 |
Response 200 — Paginated list of destinations
{ "items":: [ { "id":: "1f1a9a3d-3a2e-4b1a-9f6a-8f6d8a7e3c1b", "name":: "Analytics Data Lake", "bucket":: "acme-data-lake", "prefix":: "events/prod", "region":: "us-east-1", "role_arn":: "arn:aws:iam::123456789012:role/EdgeMqDelivery", "external_id":: "edgemq-abcdef0123456789", "kms_key_arn":: null, "path_style":: false, "status":: "valid", "validated_at":: "2026-01-15T10:35:00.000Z", "last_error":: null, "created_at":: "2026-01-15T10:30:00.000Z", "updated_at":: "2026-01-15T10:35:00.000Z", "ref_count":: 2 } ], "total":: 1, "limit":: 50, "offset":: 0, "next_offset":: null }
Errors
| Status | Description |
|---|---|
401 | Missing or invalid authentication token |
403 | Insufficient permissions |
422 | Request validation failed |
Example
curl -X GET https://api.edge.mq/v1/destinations \ -H "Authorization: Bearer $TOKEN"
GET /v1/destinations/{id}
Get a destination
Retrieve the full details of an S3 destination including its validation status and the number of endpoints referencing it.
Path parameters
| Parameter | Type | Description |
|---|---|---|
id | string (uuid) | Destination ID |
Response 200 — Destination details
{ "id":: "1f1a9a3d-3a2e-4b1a-9f6a-8f6d8a7e3c1b", "name":: "Analytics Data Lake", "bucket":: "acme-data-lake", "prefix":: "events/prod", "region":: "us-east-1", "role_arn":: "arn:aws:iam::123456789012:role/EdgeMqDelivery", "external_id":: "edgemq-abcdef0123456789", "kms_key_arn":: null, "path_style":: false, "status":: "valid", "validated_at":: "2026-01-15T10:35:00.000Z", "last_error":: null, "created_at":: "2026-01-15T10:30:00.000Z", "updated_at":: "2026-01-15T10:35:00.000Z", "ref_count":: 2 }
Errors
| Status | Description |
|---|---|
401 | Missing or invalid authentication token |
403 | Insufficient permissions |
404 | Resource not found |
Example
curl -X GET https://api.edge.mq/v1/destinations/<id> \ -H "Authorization: Bearer $TOKEN"
PATCH /v1/destinations/{id}
Update a destination
Update S3 destination settings. When critical fields (bucket, prefix, region, role_arn, kms_key_arn, path_style) are changed, the destination status resets to pending and must be re-validated.
Path parameters
| Parameter | Type | Description |
|---|---|---|
id | string (uuid) | Destination ID |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | No | New name |
bucket | string | No | New S3 bucket name (triggers re-validation) |
prefix | string | No | New S3 key prefix (triggers re-validation) |
region | string | No | New AWS region (triggers re-validation) |
role_arn | string | No | New IAM role ARN (triggers re-validation) |
kms_key_arn | string | null | No |
path_style | boolean | No | Use path-style S3 URLs (triggers re-validation) |
{ "name":: "Analytics Data Lake v2", "prefix":: "events/prod/v2" }
Response 200 — Destination updated
{ "id":: "1f1a9a3d-3a2e-4b1a-9f6a-8f6d8a7e3c1b", "name":: "Analytics Data Lake v2", "bucket":: "acme-data-lake", "prefix":: "events/prod/v2", "region":: "us-east-1", "role_arn":: "arn:aws:iam::123456789012:role/EdgeMqDelivery", "external_id":: "edgemq-abcdef0123456789", "kms_key_arn":: null, "path_style":: false, "status":: "pending", "validated_at":: null, "last_error":: null, "created_at":: "2026-01-15T10:30:00.000Z", "updated_at":: "2026-01-15T11:00:00.000Z" }
Errors
| Status | Description |
|---|---|
401 | Missing or invalid authentication token |
403 | Insufficient permissions |
404 | Resource not found |
422 | Request validation failed |
Example
curl -X PATCH https://api.edge.mq/v1/destinations/<id> \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"name":"Analytics Data Lake v2","prefix":"events/prod/v2"}'
DELETE /v1/destinations/{id}
Delete a destination
Permanently delete an S3 destination. The destination cannot be deleted if it is still referenced by one or more endpoints. Unbind the destination from all endpoints first.
Path parameters
| Parameter | Type | Description |
|---|---|---|
id | string (uuid) | Destination ID |
Response 204 — Destination deleted
Errors
| Status | Description |
|---|---|
401 | Missing or invalid authentication token |
403 | Insufficient permissions |
404 | Resource not found |
409 | Destination is referenced by endpoints |
Example
curl -X DELETE https://api.edge.mq/v1/destinations/<id> \ -H "Authorization: Bearer $TOKEN"
Views
Schema view definitions and lifecycle
POST /v1/views
Create a view definition
Create a new schema view definition in draft status. A view defines how raw JSON payloads are transformed into typed, columnar Parquet output using JSONPath column mappings and optional row filters. Views must be published before they can be attached to endpoints.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | View name (lowercase alphanumeric with underscores, must start with a letter) |
description | string | No | Human-readable description |
definition | object | Yes | |
format | yaml | json | No |
tags | string[] | No | Tags for filtering and organization Default: |
{ "name":: "user_events", "description":: "Extract user event fields for analytics pipeline", "definition":: { "columns":: [ { "name":: "user_id", "type":: "VARCHAR", "path":: "$.userId", "required":: true }, { "name":: "event_type", "type":: "VARCHAR", "path":: "$.event" }, { "name":: "timestamp", "type":: "TIMESTAMP", "path":: "$.ts" }, { "name":: "amount", "type":: "DOUBLE", "path":: "$.payload.amount", "cast_failures":: "dlq" } ], "filters":: [ { "condition":: "event_type != 'heartbeat'", "description":: "Exclude keepalive events" } ] }, "format":: "yaml", "tags":: [ "analytics", "user-events" ] }
Response 201 — View created in draft status
{ "id":: "c9d0e1f2-a3b4-5678-9012-cdef01234567", "name":: "user_events", "version":: 1, "definition":: { "columns":: [ { "name":: "user_id", "type":: "VARCHAR", "path":: "$.userId", "required":: true }, { "name":: "event_type", "type":: "VARCHAR", "path":: "$.event" }, { "name":: "timestamp", "type":: "TIMESTAMP", "path":: "$.ts" }, { "name":: "amount", "type":: "DOUBLE", "path":: "$.payload.amount", "cast_failures":: "dlq" } ], "filters":: [ { "condition":: "event_type != 'heartbeat'", "description":: "Exclude keepalive events" } ] }, "format":: "yaml", "status":: "draft", "description":: "Extract user event fields for analytics pipeline", "tags":: [ "analytics", "user-events" ], "created_by":: "admin@example.com", "created_at":: "2026-01-15T10:30:00.000Z", "published_at":: null }
Errors
| Status | Description |
|---|---|
401 | Missing or invalid authentication token |
403 | Insufficient permissions |
422 | Request validation failed |
Example
curl -X POST https://api.edge.mq/v1/views \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"name":"user_events","description":"Extract user event fields for analytics pipeline","definition":{"columns":[{"name":"user_id","type":"VARCHAR","path":"$.userId","required":true},{"name":"event_type","type":"VARCHAR","path":"$.event"},{"name":"timestamp","type":"TIMESTAMP","path":"$.ts"},{"name":"amount","type":"DOUBLE","path":"$.payload.amount","cast_failures":"dlq"}],"filters":[{"condition":"event_type != 'heartbeat'","description":"Exclude keepalive events"}]},"format":"yaml","tags":["analytics","user-events"]}'
POST /v1/views/{id}/archive
Archive a view
Transition a published view to archived status. Archived views are detached from all endpoints and can no longer be attached. This is a soft-delete for published views.
Path parameters
| Parameter | Type | Description |
|---|---|---|
id | string (uuid) | View ID (must be in published status) |
Response 200 — View archived
{ "id":: "c9d0e1f2-a3b4-5678-9012-cdef01234567", "name":: "user_events", "version":: 1, "definition":: { "columns":: [ { "name":: "user_id", "type":: "VARCHAR", "path":: "$.userId", "required":: true } ] }, "format":: "yaml", "status":: "archived", "description":: "Extract user event fields for analytics pipeline", "tags":: [ "analytics" ], "created_by":: "admin@example.com", "created_at":: "2026-01-15T10:30:00.000Z", "published_at":: "2026-01-15T11:00:00.000Z" }
Errors
| Status | Description |
|---|---|
401 | Missing or invalid authentication token |
403 | Insufficient permissions |
404 | Resource not found |
422 | Request validation failed |
Example
curl -X POST https://api.edge.mq/v1/views/<id>/archive \ -H "Authorization: Bearer $TOKEN"
POST /v1/views/{id}/publish
Publish a view
Transition a view from draft to published status. Once published, the view definition becomes immutable and can be attached to endpoints. To make changes, create a new version.
Path parameters
| Parameter | Type | Description |
|---|---|---|
id | string (uuid) | View ID (must be in draft status) |
Response 200 — View published
{ "id":: "c9d0e1f2-a3b4-5678-9012-cdef01234567", "name":: "user_events", "version":: 1, "definition":: { "columns":: [ { "name":: "user_id", "type":: "VARCHAR", "path":: "$.userId", "required":: true }, { "name":: "event_type", "type":: "VARCHAR", "path":: "$.event" }, { "name":: "timestamp", "type":: "TIMESTAMP", "path":: "$.ts" } ] }, "format":: "yaml", "status":: "published", "description":: "Extract user event fields for analytics pipeline", "tags":: [ "analytics", "user-events" ], "created_by":: "admin@example.com", "created_at":: "2026-01-15T10:30:00.000Z", "published_at":: "2026-01-15T11:00:00.000Z" }
Errors
| Status | Description |
|---|---|
401 | Missing or invalid authentication token |
403 | Insufficient permissions |
404 | Resource not found |
422 | Request validation failed |
Example
curl -X POST https://api.edge.mq/v1/views/<id>/publish \ -H "Authorization: Bearer $TOKEN"
POST /v1/views/{id}/versions
Create a new version of a view
Create a new draft version of an existing view. The new version copies the definition from the specified source version (or the latest version by default). Use this to iterate on a published view without affecting live endpoints.
Path parameters
| Parameter | Type | Description |
|---|---|---|
id | string (uuid) | View ID of any existing version in the view lineage |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
copy_from_version | integer | No | Version number to copy the definition from. Defaults to the latest version. |
description | string | No | Description for the new version |
{ "copy_from_version":: 1, "description":: "Add session_id column for attribution" }
Response 201 — New version created in draft status
{ "id":: "d0e1f2a3-b4c5-6789-0123-456789abcdef", "name":: "user_events", "version":: 2, "definition":: { "columns":: [ { "name":: "user_id", "type":: "VARCHAR", "path":: "$.userId", "required":: true }, { "name":: "event_type", "type":: "VARCHAR", "path":: "$.event" }, { "name":: "timestamp", "type":: "TIMESTAMP", "path":: "$.ts" } ] }, "format":: "yaml", "status":: "draft", "description":: "Add session_id column for attribution", "tags":: [ "analytics", "user-events" ], "created_by":: "admin@example.com", "created_at":: "2026-01-16T09:00:00.000Z", "published_at":: null }
Errors
| Status | Description |
|---|---|
401 | Missing or invalid authentication token |
403 | Insufficient permissions |
404 | Resource not found |
422 | Request validation failed |
Example
curl -X POST https://api.edge.mq/v1/views/<id>/versions \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"copy_from_version":1,"description":"Add session_id column for attribution"}'
POST /v1/views/preview
Preview a view against sample data
Test a view definition against user-provided sample JSON payloads without saving anything. Returns extracted columns, null rates, compiled SQL, and any warnings. Use this for real-time feedback during view development.
Resource limits: max 100 samples, 64KB per sample, 100 columns, 10 second timeout.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
definition | object | Yes | |
samples | string[] | Yes | Array of raw JSON payload strings to test against (max 64KB each) |
{ "definition":: { "columns":: [ { "name":: "user_id", "type":: "VARCHAR", "path":: "$.userId" }, { "name":: "event_type", "type":: "VARCHAR", "path":: "$.event" }, { "name":: "timestamp", "type":: "TIMESTAMP", "path":: "$.ts" } ], "filters":: [ { "condition":: "event_type != 'heartbeat'" } ] }, "samples":: [ "{\"userId\": \"usr_abc123\", \"event\": \"page_view\", \"ts\": \"2026-01-15T10:30:00.000Z\"}", "{\"userId\": \"usr_def456\", \"event\": \"heartbeat\", \"ts\": \"2026-01-15T10:30:01.000Z\"}" ] }
Response 200 — Preview results
{ "success":: true, "rows":: [ { "user_id":: "usr_abc123", "event_type":: "page_view", "timestamp":: "2026-01-15T10:30:00.000Z" } ], "columns":: [ { "name":: "user_id", "type":: "VARCHAR", "nullCount":: 0, "totalCount":: 1, "nullRate":: 0, "sampleValues":: [ "usr_abc123" ] }, { "name":: "event_type", "type":: "VARCHAR", "nullCount":: 0, "totalCount":: 1, "nullRate":: 0, "sampleValues":: [ "page_view" ] }, { "name":: "timestamp", "type":: "TIMESTAMP", "nullCount":: 0, "totalCount":: 1, "nullRate":: 0, "sampleValues":: [ "2026-01-15T10:30:00.000Z" ] } ], "rowCount":: 1, "compiledSql":: "SELECT json_extract_string(raw, '$.userId') AS user_id, json_extract_string(raw, '$.event') AS event_type, CAST(json_extract_string(raw, '$.ts') AS TIMESTAMP) AS timestamp FROM source WHERE event_type != 'heartbeat'", "warnings":: [], "errors":: [], "executionTimeMs":: 12.4 }
Errors
| Status | Description |
|---|---|
401 | Missing or invalid authentication token |
422 | Request validation failed |
Example
curl -X POST https://api.edge.mq/v1/views/preview \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"definition":{"columns":[{"name":"user_id","type":"VARCHAR","path":"$.userId"},{"name":"event_type","type":"VARCHAR","path":"$.event"},{"name":"timestamp","type":"TIMESTAMP","path":"$.ts"}],"filters":[{"condition":"event_type != 'heartbeat'"}]},"samples":["{\"userId\": \"usr_abc123\", \"event\": \"page_view\", \"ts\": \"2026-01-15T10:30:00.000Z\"}","{\"userId\": \"usr_def456\", \"event\": \"heartbeat\", \"ts\": \"2026-01-15T10:30:01.000Z\"}"]}'
GET /v1/views
List view definitions
Returns a paginated list of view definitions. Filter by status, name, or tags. By default only published views are returned.
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
status | draft | published | archived |
name | string | No | Filter by exact view name. |
tag | string[] | No | Filter by tag (can specify multiple). |
limit | integer | No | Maximum number of items to return (1-200). Default: 50 |
offset | integer | No | Number of items to skip for pagination. Default: 0 |
Response 200 — Paginated list of views
{ "items":: [ { "id":: "c9d0e1f2-a3b4-5678-9012-cdef01234567", "name":: "user_events", "version":: 1, "definition":: { "columns":: [ { "name":: "user_id", "type":: "VARCHAR", "path":: "$.userId", "required":: true }, { "name":: "event_type", "type":: "VARCHAR", "path":: "$.event" }, { "name":: "timestamp", "type":: "TIMESTAMP", "path":: "$.ts" } ] }, "format":: "yaml", "status":: "published", "description":: "Extract user event fields for analytics pipeline", "tags":: [ "analytics", "user-events" ], "created_by":: "admin@example.com", "created_at":: "2026-01-15T10:30:00.000Z", "published_at":: "2026-01-15T11:00:00.000Z", "usage_count":: 2 } ], "total":: 1, "limit":: 50, "offset":: 0, "next_offset":: null }
Errors
| Status | Description |
|---|---|
401 | Missing or invalid authentication token |
422 | Request validation failed |
Example
curl -X GET https://api.edge.mq/v1/views \ -H "Authorization: Bearer $TOKEN"
GET /v1/views/{id}
Get a view definition
Retrieve the full details of a view definition including its version history and the list of endpoints it is attached to.
Path parameters
| Parameter | Type | Description |
|---|---|---|
id | string (uuid) | View ID |
Response 200 — View details with version history and endpoint bindings
{ "id":: "c9d0e1f2-a3b4-5678-9012-cdef01234567", "name":: "user_events", "version":: 1, "definition":: { "columns":: [ { "name":: "user_id", "type":: "VARCHAR", "path":: "$.userId", "required":: true }, { "name":: "event_type", "type":: "VARCHAR", "path":: "$.event" }, { "name":: "timestamp", "type":: "TIMESTAMP", "path":: "$.ts" } ], "filters":: [ { "condition":: "event_type != 'heartbeat'" } ] }, "format":: "yaml", "status":: "published", "description":: "Extract user event fields for analytics pipeline", "tags":: [ "analytics", "user-events" ], "created_by":: "admin@example.com", "created_at":: "2026-01-15T10:30:00.000Z", "published_at":: "2026-01-15T11:00:00.000Z", "versions":: [ { "id":: "c9d0e1f2-a3b4-5678-9012-cdef01234567", "version":: 1, "status":: "published", "published_at":: "2026-01-15T11:00:00.000Z", "created_by":: "admin@example.com" } ], "endpoints":: [ { "id":: "550e8400-e29b-41d4-a716-446655440000", "region":: "iad", "binding_id":: "d0e1f2a3-b4c5-6789-0123-ef0123456789", "is_required":: false, "activated_at":: "2026-01-16T09:00:00.000Z", "canary_start_ts":: null } ] }
Errors
| Status | Description |
|---|---|
401 | Missing or invalid authentication token |
403 | Insufficient permissions |
404 | Resource not found |
Example
curl -X GET https://api.edge.mq/v1/views/<id> \ -H "Authorization: Bearer $TOKEN"
PATCH /v1/views/{id}
Update a draft view
Update the description, definition, or tags of a view that is still in draft status. Published and archived views cannot be updated; create a new version instead.
Path parameters
| Parameter | Type | Description |
|---|---|---|
id | string (uuid) | View ID (must be in draft status) |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
description | string | No | Updated description |
definition | object | No | |
tags | string[] | No | Updated tags |
{ "description":: "Updated description for user events view", "definition":: { "columns":: [ { "name":: "user_id", "type":: "VARCHAR", "path":: "$.userId", "required":: true }, { "name":: "event_type", "type":: "VARCHAR", "path":: "$.event" }, { "name":: "timestamp", "type":: "TIMESTAMP", "path":: "$.ts" }, { "name":: "session_id", "type":: "VARCHAR", "path":: "$.sessionId" } ] }, "tags":: [ "analytics", "user-events", "sessions" ] }
Response 200 — View updated
Errors
| Status | Description |
|---|---|
401 | Missing or invalid authentication token |
403 | Insufficient permissions |
404 | Resource not found |
422 | Request validation failed |
Example
curl -X PATCH https://api.edge.mq/v1/views/<id> \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"description":"Updated description for user events view","definition":{"columns":[{"name":"user_id","type":"VARCHAR","path":"$.userId","required":true},{"name":"event_type","type":"VARCHAR","path":"$.event"},{"name":"timestamp","type":"TIMESTAMP","path":"$.ts"},{"name":"session_id","type":"VARCHAR","path":"$.sessionId"}]},"tags":["analytics","user-events","sessions"]}'
DELETE /v1/views/{id}
Delete a draft view
Permanently delete a view definition that is in draft status. Published and archived views cannot be deleted; archive them instead.
Path parameters
| Parameter | Type | Description |
|---|---|---|
id | string (uuid) | View ID (must be in draft status) |
Response 204 — View deleted
Errors
| Status | Description |
|---|---|
401 | Missing or invalid authentication token |
403 | Insufficient permissions |
404 | Resource not found |
422 | View is not in draft status |
Example
curl -X DELETE https://api.edge.mq/v1/views/<id> \ -H "Authorization: Bearer $TOKEN"
Bindings
View-to-endpoint bindings
POST /v1/endpoints/{endpoint_id}/views
Attach a view to an endpoint
Bind a published view definition to an ingest endpoint. Once attached, the view's schema transformation is applied to every sealed segment on this endpoint. Optionally set canary_start_ts for gradual rollout.
Path parameters
| Parameter | Type | Description |
|---|---|---|
endpoint_id | string (uuid) | Endpoint ID |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
view_id | string (uuid) | Yes | ID of the published view to attach |
is_required | boolean | No | If true, ingest fails when view extraction fails. If false, view output is optional. Default: false |
canary_start_ts | string (date-time) | No | Apply view only to segments sealed after this timestamp (for gradual rollout) |
{ "view_id":: "c9d0e1f2-a3b4-5678-9012-cdef01234567", "is_required":: false }
Response 201 — View attached to endpoint
{ "id":: "d0e1f2a3-b4c5-6789-0123-ef0123456789", "endpoint_id":: "550e8400-e29b-41d4-a716-446655440000", "view_id":: "c9d0e1f2-a3b4-5678-9012-cdef01234567", "view_name":: "user_events", "view_version":: 1, "is_required":: false, "activated_at":: "2026-01-16T09:00:00.000Z", "activated_by":: "admin@example.com", "deactivated_at":: null, "canary_start_ts":: null, "status":: "active" }
Errors
| Status | Description |
|---|---|
401 | Missing or invalid authentication token |
403 | Insufficient permissions |
404 | Resource not found |
409 | View is already attached to this endpoint |
422 | Request validation failed |
Example
curl -X POST https://api.edge.mq/v1/endpoints/<endpoint_id>/views \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"view_id":"c9d0e1f2-a3b4-5678-9012-cdef01234567","is_required":false}'
GET /v1/endpoints/{endpoint_id}/views
List view bindings for an endpoint
Returns all view definitions attached to an endpoint, including both active and inactive (detached) bindings.
Path parameters
| Parameter | Type | Description |
|---|---|---|
endpoint_id | string (uuid) | Endpoint ID |
Response 200 — List of view bindings
{ "items":: [ { "id":: "d0e1f2a3-b4c5-6789-0123-ef0123456789", "endpoint_id":: "550e8400-e29b-41d4-a716-446655440000", "view_id":: "c9d0e1f2-a3b4-5678-9012-cdef01234567", "view_name":: "user_events", "view_version":: 1, "is_required":: false, "activated_at":: "2026-01-16T09:00:00.000Z", "activated_by":: "admin@example.com", "deactivated_at":: null, "canary_start_ts":: null, "status":: "active" } ] }
Errors
| Status | Description |
|---|---|
401 | Missing or invalid authentication token |
404 | Resource not found |
Example
curl -X GET https://api.edge.mq/v1/endpoints/<endpoint_id>/views \ -H "Authorization: Bearer $TOKEN"
DELETE /v1/endpoints/{endpoint_id}/views/{binding_id}
Detach a view from an endpoint
Remove a view binding from an endpoint by soft-deleting it (setting deactivated_at). The view definition itself is not affected. Ingest nodes are notified via config epoch bump.
Path parameters
| Parameter | Type | Description |
|---|---|---|
endpoint_id | string (uuid) | Endpoint ID |
binding_id | string (uuid) | View binding ID |
Response 204 — View detached successfully
Errors
| Status | Description |
|---|---|
401 | Missing or invalid authentication token |
404 | Resource not found |
Example
curl -X DELETE https://api.edge.mq/v1/endpoints/<endpoint_id>/views/<binding_id> \ -H "Authorization: Bearer $TOKEN"
Observability
Delivery confirmation, data quality metrics, and dead letter queue
GET /v1/endpoints/{id}/commits
List sealed segments for an endpoint
Returns a cursor-paginated list of sealed segment commits for an endpoint. Each commit represents a WAL segment that has been uploaded to S3 with its output artifacts (raw segments, Parquet files, etc.). Use the before cursor for pagination.
Path parameters
| Parameter | Type | Description |
|---|---|---|
id | string (uuid) | Endpoint ID |
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
limit | integer | No | Maximum number of items to return (1-200). Default: 50 |
before | string (date-time) | No | Cursor for pagination: return commits uploaded before this ISO 8601 timestamp. |
Response 200 — List of segment commits
{ "items":: [ { "id":: "10042", "node_id":: "550e8400-e29b-41d4-a716-446655440000", "seq":: 17, "wal_bytes":: 2097152, "duration_ms":: 340, "uploaded_at":: "2026-01-15T10:30:00.000Z", "artifacts":: { "parquet":: { "key":: "s3://acme-data-lake/events/prod/seg-17.parquet", "bytes":: 1048576 } } }, { "id":: "10041", "node_id":: "550e8400-e29b-41d4-a716-446655440000", "seq":: 16, "wal_bytes":: 1835008, "duration_ms":: 290, "uploaded_at":: "2026-01-15T10:25:00.000Z", "artifacts":: { "parquet":: { "key":: "s3://acme-data-lake/events/prod/seg-16.parquet", "bytes":: 921600 } } } ], "next_cursor":: "2026-01-15T10:25:00.000Z" }
Errors
| Status | Description |
|---|---|
401 | Missing or invalid authentication token |
403 | Insufficient permissions |
404 | Resource not found |
422 | Request validation failed |
Example
curl -X GET https://api.edge.mq/v1/endpoints/<id>/commits \ -H "Authorization: Bearer $TOKEN"
GET /v1/views/{id}/dlq-files
List dead letter queue files for a view
Returns DLQ (dead letter queue) files for a view containing rows that failed validation or type casting. Each file includes a presigned S3 URL valid for 1 hour for downloading and inspecting rejected rows.
Path parameters
| Parameter | Type | Description |
|---|---|---|
id | string (uuid) | View ID |
Response 200 — DLQ files with presigned download URLs
{ "view_id":: "c9d0e1f2-a3b4-5678-9012-cdef01234567", "view_name":: "user_events", "view_version":: 1, "files":: [ { "endpoint_id":: "550e8400-e29b-41d4-a716-446655440000", "endpoint_name":: "prod-ingest", "segment_seq":: 17, "s3_key":: "dlq/user_events/seg-17.parquet", "s3_bucket":: "acme-data-lake", "region":: "us-east-1", "bytes":: 4096, "rows":: 42, "created_at":: "2026-01-15T10:30:00.000Z", "download_url":: "https://acme-data-lake.s3.amazonaws.com/dlq/user_events/seg-17.parquet?X-Amz-Signature=..." } ], "total":: 1 }
Errors
| Status | Description |
|---|---|
401 | Missing or invalid authentication token |
403 | Insufficient permissions |
404 | Resource not found |
Example
curl -X GET https://api.edge.mq/v1/views/<id>/dlq-files \ -H "Authorization: Bearer $TOKEN"
GET /v1/views/{id}/metrics
Get data quality metrics for a view
Returns aggregated data quality metrics for a view across all endpoints it is bound to. Includes 24-hour rolling windows and lifetime totals for rows processed, accepted, dropped, and sent to DLQ. Metrics are updated every 5 minutes.
Path parameters
| Parameter | Type | Description |
|---|---|---|
id | string (uuid) | View ID |
Response 200 — View metrics
{ "view_id":: "c9d0e1f2-a3b4-5678-9012-cdef01234567", "view_name":: "user_events", "view_version":: 1, "endpoints":: [ { "endpoint_id":: "550e8400-e29b-41d4-a716-446655440000", "endpoint_name":: "prod-ingest", "last_24h":: { "processed":: 15234, "accepted":: 14980, "dropped":: 212, "dlq":: 42 }, "all_time":: { "processed":: 1048576, "accepted":: 1031200, "dropped":: 14876, "dlq":: 2500 }, "error_rate_pct":: 1.67, "has_errors":: false, "error_count_24h":: 0, "total_error_count":: 0, "last_error_at":: null, "last_error_code":: null, "last_error_message":: null, "last_updated_at":: "2026-01-15T10:30:00.000Z" } ], "aggregated":: { "last_24h":: { "processed":: 15234, "accepted":: 14980, "dropped":: 212, "dlq":: 42 }, "all_time":: { "processed":: 1048576, "accepted":: 1031200, "dropped":: 14876, "dlq":: 2500 }, "error_rate_pct":: 1.67, "has_errors":: false, "total_error_count_24h":: 0 } }
Errors
| Status | Description |
|---|---|
401 | Missing or invalid authentication token |
403 | Insufficient permissions |
404 | Resource not found |
Example
curl -X GET https://api.edge.mq/v1/views/<id>/metrics \ -H "Authorization: Bearer $TOKEN"