From dedf7b34bde08586f6dd8803a98e3ffea34e9863 Mon Sep 17 00:00:00 2001 From: Benita Volkmann Date: Thu, 2 Jul 2026 13:58:09 +0200 Subject: [PATCH 1/6] Document Usage APIs from the Dashboard --- maintenance-ops/usage-metrics-api.mdx | 188 ++++++++++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 maintenance-ops/usage-metrics-api.mdx diff --git a/maintenance-ops/usage-metrics-api.mdx b/maintenance-ops/usage-metrics-api.mdx new file mode 100644 index 00000000..4241a996 --- /dev/null +++ b/maintenance-ops/usage-metrics-api.mdx @@ -0,0 +1,188 @@ +--- +title: "Usage Metrics API" +description: Query usage metrics for your PowerSync Cloud instances programmatically, including storage size, concurrent connections, and replicated and synced data. +hidden: true +--- + + + This API is in early access and is not officially supported yet. Endpoints, request formats, and response formats may change without notice, and no guarantees or SLAs apply. If you rely on this API, [please let us know](/resources/contact-us). + + +The Usage Metrics API exposes the same instance metrics shown in the [Metrics view](/maintenance-ops/monitoring-and-alerting#usage-metrics) of the PowerSync Dashboard. There are two endpoints: + +* Granular usage: a time series of values for a single metric, bucketed by minute, hour, or day. +* Total usage: a single aggregate value for a metric over a time window. This is useful for "sum over period" figures. + +Both endpoints operate on one PowerSync instance per request. + +## Authentication + +Both endpoints require Bearer token authentication: + +``` +Authorization: Bearer +``` + +To generate a token, go to [user account settings → Access Tokens](https://dashboard.powersync.com/account/access-tokens) in the PowerSync Dashboard. + +The token must belong to a user with read access to the instance being queried. + +## Common Request Fields + +Both endpoints accept a JSON body via POST, with `Content-Type: application/json`. Every request includes these fields: + +| Parameter | Type | Description | Required | +| --------- | ---- | ----------- | -------- | +| `org_id` | string | PowerSync organization ID | Yes | +| `app_id` | string | PowerSync project ID | Yes | +| `instance_id` | string | PowerSync instance ID | Yes | + +You can get these IDs from the Dashboard URL while on an instance view. + +## Granular Usage + +Returns a time series of values for a single metric over the requested window. + +``` +POST https://powersync-usage.journeyapps.com/api/v1/usage/granular +``` + +### Request Body + +In addition to the [common fields](#common-request-fields): + +| Parameter | Type | Description | Required | +| --------- | ---- | ----------- | -------- | +| `metric` | string (enum) | Metric to query. See [Granular Metrics](#granular-metrics). | Yes | +| `granularity` | string (enum) | Bucket size: `minute`, `hour`, or `day`. See [Granularity and Limits](#granularity-and-limits). | Yes | +| `start` | string (ISO 8601) | Start of the window | Yes | +| `end` | string (ISO 8601) | End of the window | Yes | + +### Granular Metrics + +| `metric` | Unit | Description | Bucket value | +| -------- | ---- | ----------- | ------------ | +| `storage-size` | bytes | Total data stored for the instance | Peak in bucket | +| `concurrent-connections` | count | Concurrent client connections | Peak in bucket | +| `operations-replicated` | count | Rows replicated from the source database | Total in bucket | +| `operations-synced` | count | Operations synced to clients | Total in bucket | +| `data-replicated` | bytes | Data replicated from the source database | Total in bucket | +| `data-synced` | bytes | Data synced to clients | Total in bucket | +| `replication-lag` | seconds | Replication lag | Peak in bucket | + + + Query `replication-lag` at `minute` or `hour` granularity. At `day` granularity this metric does not currently return the daily peak, so the values are not meaningful. + + +### Granularity and Limits + +| `granularity` | Behavior | +| ------------- | -------- | +| `minute` | Live data only. The window (`end` − `start`) must be 24 hours or less, otherwise the request is rejected. | +| `hour` | Combines archived and live data to cover the full window. | +| `day` | Archived data only. Each point is one calendar day, aggregated in the instance region's timezone. | + +Buckets are aligned to whole hours and days and are not trimmed to your requested window. If your `start` or `end` falls inside a bucket, the edge buckets can include data from outside the window or omit the partial period. For example, an hourly request for 12:30 to 16:40 against archived data returns buckets ending 13:00 through 16:00: the first bucket covers 12:00 to 13:00, including data from before your requested start, and the period from 16:00 to 16:40 is not included. For predictable coverage, align `start` and `end` to bucket boundaries. + +### Example Request + +```bash +curl --location 'https://powersync-usage.journeyapps.com/api/v1/usage/granular' \ + --header 'Content-Type: application/json' \ + --header 'Authorization: Bearer ' \ + --data '{ + "org_id": "674f1a2b3c8d9e0012a45b67", + "app_id": "674f1a5c3c8d9e0012a45b89", + "instance_id": "6750c3d47e2f1a0013b56c9a", + "metric": "data-synced", + "granularity": "hour", + "start": "2025-12-01T00:00:00.000Z", + "end": "2025-12-02T00:00:00.000Z" + }' +``` + +### Response Body + +| Field | Type | Description | +| ----- | ---- | ----------- | +| `data.values` | array | Time-series data points | +| `data.values[].t` | string (ISO 8601) | Bucket timestamp. For hourly buckets this is the bucket end, so a value at `01:00` covers the hour from `00:00` to `01:00`. For daily buckets it is the day. | +| `data.values[].v` | number | Value for the bucket, in the metric's unit | + +### Example Response + +```json +{ + "data": { + "values": [ + { "t": "2025-12-01T01:00:00.000Z", "v": 524288 }, + { "t": "2025-12-01T02:00:00.000Z", "v": 1048576 }, + { "t": "2025-12-01T03:00:00.000Z", "v": 786432 } + ] + } +} +``` + +## Total Usage + +Returns a single aggregate value for a metric over the requested window. + +``` +POST https://powersync-usage.journeyapps.com/api/v1/usage/total +``` + +Totals are computed from archived data, which is updated hourly. Usage from roughly the last hour is not yet included in the result. + +### Request Body + +In addition to the [common fields](#common-request-fields): + +| Parameter | Type | Description | Required | +| --------- | ---- | ----------- | -------- | +| `metric` | string (enum) | Metric to query. See [Total Metrics](#total-metrics). | Yes | +| `start` | string (ISO 8601) | Start of the window | Yes | +| `end` | string (ISO 8601) | End of the window | Yes | + +### Total Metrics + +| `metric` | Unit | Description | +| -------- | ---- | ----------- | +| `data-processing` | bytes | Data replicated from the source database plus data synced to clients, over the period | +| `sync-operations` | count | Operations synced to clients over the period | +| `data-synced` | bytes | Data synced to clients over the period | + +### Example Request + +```bash +curl --location 'https://powersync-usage.journeyapps.com/api/v1/usage/total' \ + --header 'Content-Type: application/json' \ + --header 'Authorization: Bearer ' \ + --data '{ + "org_id": "674f1a2b3c8d9e0012a45b67", + "app_id": "674f1a5c3c8d9e0012a45b89", + "instance_id": "6750c3d47e2f1a0013b56c9a", + "metric": "data-synced", + "start": "2025-12-01T00:00:00.000Z", + "end": "2025-12-08T00:00:00.000Z" + }' +``` + +### Response Body + +| Field | Type | Description | +| ----- | ---- | ----------- | +| `data.value` | number | Aggregate value over the window, in the metric's unit | + +### Example Response + +```json +{ + "data": { + "value": 7340032 + } +} +``` + +## Self-Hosted Deployments + +The Usage Metrics API is a PowerSync Cloud service. Self-hosted deployments expose the same underlying instance metrics directly from the PowerSync Service via a Prometheus-compatible endpoint, which you can scrape with Prometheus or any compatible monitoring system. See [Monitoring a self-hosted PowerSync Service](/maintenance-ops/self-hosting/monitoring) for details. From 26dc61b5961d6efa0222fe2553a5bc7e3e13e71b Mon Sep 17 00:00:00 2001 From: Benita Volkmann Date: Thu, 2 Jul 2026 15:51:21 +0200 Subject: [PATCH 2/6] Avoid the confusing "bucket" wording --- maintenance-ops/usage-metrics-api.mdx | 28 +++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/maintenance-ops/usage-metrics-api.mdx b/maintenance-ops/usage-metrics-api.mdx index 4241a996..c8495c3f 100644 --- a/maintenance-ops/usage-metrics-api.mdx +++ b/maintenance-ops/usage-metrics-api.mdx @@ -10,7 +10,7 @@ hidden: true The Usage Metrics API exposes the same instance metrics shown in the [Metrics view](/maintenance-ops/monitoring-and-alerting#usage-metrics) of the PowerSync Dashboard. There are two endpoints: -* Granular usage: a time series of values for a single metric, bucketed by minute, hour, or day. +* Granular usage: a time series of values for a single metric, at minute, hour, or day granularity. * Total usage: a single aggregate value for a metric over a time window. This is useful for "sum over period" figures. Both endpoints operate on one PowerSync instance per request. @@ -54,21 +54,21 @@ In addition to the [common fields](#common-request-fields): | Parameter | Type | Description | Required | | --------- | ---- | ----------- | -------- | | `metric` | string (enum) | Metric to query. See [Granular Metrics](#granular-metrics). | Yes | -| `granularity` | string (enum) | Bucket size: `minute`, `hour`, or `day`. See [Granularity and Limits](#granularity-and-limits). | Yes | +| `granularity` | string (enum) | Timespan covered by each data point: `minute`, `hour`, or `day`. See [Granularity and Limits](#granularity-and-limits). | Yes | | `start` | string (ISO 8601) | Start of the window | Yes | | `end` | string (ISO 8601) | End of the window | Yes | ### Granular Metrics -| `metric` | Unit | Description | Bucket value | -| -------- | ---- | ----------- | ------------ | -| `storage-size` | bytes | Total data stored for the instance | Peak in bucket | -| `concurrent-connections` | count | Concurrent client connections | Peak in bucket | -| `operations-replicated` | count | Rows replicated from the source database | Total in bucket | -| `operations-synced` | count | Operations synced to clients | Total in bucket | -| `data-replicated` | bytes | Data replicated from the source database | Total in bucket | -| `data-synced` | bytes | Data synced to clients | Total in bucket | -| `replication-lag` | seconds | Replication lag | Peak in bucket | +| `metric` | Unit | Description | Value per timespan | +| -------- | ---- | ----------- | ------------------ | +| `storage-size` | bytes | Total data stored for the instance | Peak | +| `concurrent-connections` | count | Concurrent client connections | Peak | +| `operations-replicated` | count | Rows replicated from the source database | Total | +| `operations-synced` | count | Operations synced to clients | Total | +| `data-replicated` | bytes | Data replicated from the source database | Total | +| `data-synced` | bytes | Data synced to clients | Total | +| `replication-lag` | seconds | Replication lag | Peak | Query `replication-lag` at `minute` or `hour` granularity. At `day` granularity this metric does not currently return the daily peak, so the values are not meaningful. @@ -82,7 +82,7 @@ In addition to the [common fields](#common-request-fields): | `hour` | Combines archived and live data to cover the full window. | | `day` | Archived data only. Each point is one calendar day, aggregated in the instance region's timezone. | -Buckets are aligned to whole hours and days and are not trimmed to your requested window. If your `start` or `end` falls inside a bucket, the edge buckets can include data from outside the window or omit the partial period. For example, an hourly request for 12:30 to 16:40 against archived data returns buckets ending 13:00 through 16:00: the first bucket covers 12:00 to 13:00, including data from before your requested start, and the period from 16:00 to 16:40 is not included. For predictable coverage, align `start` and `end` to bucket boundaries. +Data points are aligned to whole hours and days and are not trimmed to your requested window. If your `start` or `end` falls inside a timespan, the data points at the edges of the window can include data from outside the window or omit the partial period. For example, an hourly request for 12:30 to 16:40 against archived data returns data points ending 13:00 through 16:00: the first covers 12:00 to 13:00, including data from before your requested start, and the period from 16:00 to 16:40 is not included. For predictable coverage, align `start` and `end` to whole hours or days. ### Example Request @@ -106,8 +106,8 @@ curl --location 'https://powersync-usage.journeyapps.com/api/v1/usage/granular' | Field | Type | Description | | ----- | ---- | ----------- | | `data.values` | array | Time-series data points | -| `data.values[].t` | string (ISO 8601) | Bucket timestamp. For hourly buckets this is the bucket end, so a value at `01:00` covers the hour from `00:00` to `01:00`. For daily buckets it is the day. | -| `data.values[].v` | number | Value for the bucket, in the metric's unit | +| `data.values[].t` | string (ISO 8601) | Timestamp of the data point. At `hour` granularity this is the end of the timespan, so a value at `01:00` covers the hour from `00:00` to `01:00`. At `day` granularity it is the day. | +| `data.values[].v` | number | Value over the timespan, in the metric's unit | ### Example Response From 00cc6ea6e0e5a03c12f36104b95e60fb7cdf27c4 Mon Sep 17 00:00:00 2001 From: Benita Volkmann Date: Thu, 2 Jul 2026 17:17:48 +0200 Subject: [PATCH 3/6] Less verbose auto-review --- .github/workflows/docs-review.yaml | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/.github/workflows/docs-review.yaml b/.github/workflows/docs-review.yaml index 40d6ed31..d3d3d31a 100644 --- a/.github/workflows/docs-review.yaml +++ b/.github/workflows/docs-review.yaml @@ -51,13 +51,16 @@ jobs: Reporting: - Post each specific issue as an inline comment on the relevant line using - mcp__github_inline_comment__create_inline_comment. Include the rule violated - and a suggested fix. - - Post one summary comment with `gh pr comment` giving the overall assessment - (Approve / Approve with minor fixes / Needs revision) and anything that does - not map to a single line. - - If there are no issues, post only the summary comment saying the changes pass - the writing standards review. + mcp__github_inline_comment__create_inline_comment. State the problem and a + suggested fix. Do not cite the rule or its source (no "CLAUDE.md says" or + quoting guideline text); the feedback is understood to come from the + writing standards. + - Do NOT post a summary comment. The inline comments are the complete output. + Do not restate the inline issues, list the checks that passed, give an + overall assessment, or add caveats about what you could not verify. + - Only use `gh pr comment` in two cases, and keep it to one or two sentences: + an issue that does not map to a specific line, or no issues at all (say the + changes pass the writing standards review). claude_args: | --model claude-sonnet-5 --allowedTools "mcp__github_inline_comment__create_inline_comment,Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr comment:*)" From 8e36796444329e112a361b02db4f6957c171a536 Mon Sep 17 00:00:00 2001 From: benitav Date: Thu, 2 Jul 2026 17:18:50 +0200 Subject: [PATCH 4/6] Apply suggestions from code review Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> --- maintenance-ops/usage-metrics-api.mdx | 9 --------- 1 file changed, 9 deletions(-) diff --git a/maintenance-ops/usage-metrics-api.mdx b/maintenance-ops/usage-metrics-api.mdx index c8495c3f..18870ecf 100644 --- a/maintenance-ops/usage-metrics-api.mdx +++ b/maintenance-ops/usage-metrics-api.mdx @@ -19,9 +19,6 @@ Both endpoints operate on one PowerSync instance per request. Both endpoints require Bearer token authentication: -``` -Authorization: Bearer -``` To generate a token, go to [user account settings → Access Tokens](https://dashboard.powersync.com/account/access-tokens) in the PowerSync Dashboard. @@ -43,9 +40,6 @@ You can get these IDs from the Dashboard URL while on an instance view. Returns a time series of values for a single metric over the requested window. -``` -POST https://powersync-usage.journeyapps.com/api/v1/usage/granular -``` ### Request Body @@ -127,9 +121,6 @@ curl --location 'https://powersync-usage.journeyapps.com/api/v1/usage/granular' Returns a single aggregate value for a metric over the requested window. -``` -POST https://powersync-usage.journeyapps.com/api/v1/usage/total -``` Totals are computed from archived data, which is updated hourly. Usage from roughly the last hour is not yet included in the result. From 78b368e6bf7d0e7c429abdccc93fb89d78397b15 Mon Sep 17 00:00:00 2001 From: Benita Volkmann Date: Thu, 2 Jul 2026 17:22:37 +0200 Subject: [PATCH 5/6] Add http snippets back properly --- maintenance-ops/usage-metrics-api.mdx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/maintenance-ops/usage-metrics-api.mdx b/maintenance-ops/usage-metrics-api.mdx index 18870ecf..24342297 100644 --- a/maintenance-ops/usage-metrics-api.mdx +++ b/maintenance-ops/usage-metrics-api.mdx @@ -19,6 +19,9 @@ Both endpoints operate on one PowerSync instance per request. Both endpoints require Bearer token authentication: +```http +Authorization: Bearer +``` To generate a token, go to [user account settings → Access Tokens](https://dashboard.powersync.com/account/access-tokens) in the PowerSync Dashboard. @@ -40,6 +43,9 @@ You can get these IDs from the Dashboard URL while on an instance view. Returns a time series of values for a single metric over the requested window. +```http +POST https://powersync-usage.journeyapps.com/api/v1/usage/granular +``` ### Request Body @@ -121,6 +127,9 @@ curl --location 'https://powersync-usage.journeyapps.com/api/v1/usage/granular' Returns a single aggregate value for a metric over the requested window. +```http +POST https://powersync-usage.journeyapps.com/api/v1/usage/total +``` Totals are computed from archived data, which is updated hourly. Usage from roughly the last hour is not yet included in the result. From 18bfcf294cac2f1fbbcf84782b4e11405f3d170b Mon Sep 17 00:00:00 2001 From: Benita Volkmann Date: Thu, 2 Jul 2026 17:27:27 +0200 Subject: [PATCH 6/6] Time span typo --- maintenance-ops/usage-metrics-api.mdx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/maintenance-ops/usage-metrics-api.mdx b/maintenance-ops/usage-metrics-api.mdx index 24342297..4c00d80f 100644 --- a/maintenance-ops/usage-metrics-api.mdx +++ b/maintenance-ops/usage-metrics-api.mdx @@ -54,13 +54,13 @@ In addition to the [common fields](#common-request-fields): | Parameter | Type | Description | Required | | --------- | ---- | ----------- | -------- | | `metric` | string (enum) | Metric to query. See [Granular Metrics](#granular-metrics). | Yes | -| `granularity` | string (enum) | Timespan covered by each data point: `minute`, `hour`, or `day`. See [Granularity and Limits](#granularity-and-limits). | Yes | +| `granularity` | string (enum) | Time span covered by each data point: `minute`, `hour`, or `day`. See [Granularity and Limits](#granularity-and-limits). | Yes | | `start` | string (ISO 8601) | Start of the window | Yes | | `end` | string (ISO 8601) | End of the window | Yes | ### Granular Metrics -| `metric` | Unit | Description | Value per timespan | +| `metric` | Unit | Description | Value per time span | | -------- | ---- | ----------- | ------------------ | | `storage-size` | bytes | Total data stored for the instance | Peak | | `concurrent-connections` | count | Concurrent client connections | Peak | @@ -82,7 +82,7 @@ In addition to the [common fields](#common-request-fields): | `hour` | Combines archived and live data to cover the full window. | | `day` | Archived data only. Each point is one calendar day, aggregated in the instance region's timezone. | -Data points are aligned to whole hours and days and are not trimmed to your requested window. If your `start` or `end` falls inside a timespan, the data points at the edges of the window can include data from outside the window or omit the partial period. For example, an hourly request for 12:30 to 16:40 against archived data returns data points ending 13:00 through 16:00: the first covers 12:00 to 13:00, including data from before your requested start, and the period from 16:00 to 16:40 is not included. For predictable coverage, align `start` and `end` to whole hours or days. +Data points are aligned to whole hours and days and are not trimmed to your requested window. If your `start` or `end` falls inside a time span, the data points at the edges of the window can include data from outside the window or omit the partial period. For example, an hourly request for 12:30 to 16:40 against archived data returns data points ending 13:00 through 16:00: the first covers 12:00 to 13:00, including data from before your requested start, and the period from 16:00 to 16:40 is not included. For predictable coverage, align `start` and `end` to whole hours or days. ### Example Request @@ -106,8 +106,8 @@ curl --location 'https://powersync-usage.journeyapps.com/api/v1/usage/granular' | Field | Type | Description | | ----- | ---- | ----------- | | `data.values` | array | Time-series data points | -| `data.values[].t` | string (ISO 8601) | Timestamp of the data point. At `hour` granularity this is the end of the timespan, so a value at `01:00` covers the hour from `00:00` to `01:00`. At `day` granularity it is the day. | -| `data.values[].v` | number | Value over the timespan, in the metric's unit | +| `data.values[].t` | string (ISO 8601) | Timestamp of the data point. At `hour` granularity this is the end of the time span, so a value at `01:00` covers the hour from `00:00` to `01:00`. At `day` granularity it is the day. | +| `data.values[].v` | number | Value over the time span, in the metric's unit | ### Example Response