From f1dbd220a7972770b90146aa73a7dbab85750c0f Mon Sep 17 00:00:00 2001
From: LaNinja06 <87137526+LaNinja06@users.noreply.github.com>
Date: Fri, 23 Oct 2026 18:47:00 +0000
Subject: [PATCH 1/2] docs: sync API reference with countly-platform
---
docs-drift-ignore.txt | 3 +
docs/api/core/system/index.md | 1 +
docs/api/core/system/o-system-usersync.md | 106 ++++++++++++
docs/api/heatmaps/index.md | 2 +
docs/api/heatmaps/o-heatmaps-metrics.md | 72 ++++++++
docs/api/heatmaps/o-heatmaps-views.md | 101 +++++++++++
docs/api/hooks/index.md | 1 +
docs/api/hooks/o-hooks.md | 63 +++++++
docs/api/journey_engine/index.md | 4 +
.../journey-engine-approval-queue.md | 120 +++++++++++++
.../journey_engine/journey-engine-settings.md | 68 ++++++++
.../journey-engine-stats-content.md | 131 ++++++++++++++
.../journey-engine-user-content.md | 128 ++++++++++++++
docs/api/push/app-config.md | 102 +++++++++++
docs/api/push/index.md | 2 +
docs/api/push/vapid-keys.md | 94 ++++++++++
docs/api/sdk/index.md | 1 +
docs/api/sdk/o-sdk-test.md | 162 ++++++++++++++++++
18 files changed, 1161 insertions(+)
create mode 100644 docs/api/core/system/o-system-usersync.md
create mode 100644 docs/api/heatmaps/o-heatmaps-metrics.md
create mode 100644 docs/api/heatmaps/o-heatmaps-views.md
create mode 100644 docs/api/hooks/o-hooks.md
create mode 100644 docs/api/journey_engine/journey-engine-approval-queue.md
create mode 100644 docs/api/journey_engine/journey-engine-settings.md
create mode 100644 docs/api/journey_engine/journey-engine-stats-content.md
create mode 100644 docs/api/journey_engine/journey-engine-user-content.md
create mode 100644 docs/api/push/app-config.md
create mode 100644 docs/api/push/vapid-keys.md
create mode 100644 docs/api/sdk/o-sdk-test.md
diff --git a/docs-drift-ignore.txt b/docs-drift-ignore.txt
index 0d9fb8c..d2f7b60 100644
--- a/docs-drift-ignore.txt
+++ b/docs-drift-ignore.txt
@@ -106,3 +106,6 @@
# Internal helper for the Data Manager dashboard view: lists metadata of the internal view event only.
/o/data-manager/events/internal
+
+# Dev-only debug endpoint (the code comment says so): returns the raw journey graph, block logs and pending waits of one user for a debug visualization.
+/o/journey-engine/user-status
diff --git a/docs/api/core/system/index.md b/docs/api/core/system/index.md
index 80aa5cb..fcc1a9d 100644
--- a/docs/api/core/system/index.md
+++ b/docs/api/core/system/index.md
@@ -20,6 +20,7 @@ System endpoints expose operational runtime information for Countly, including v
- [Kafka Events List](./o-system-kafka-events.md) - `/o/system/kafka/events`
- [Kafka Events Meta Read](./o-system-kafka-events-meta.md) - `/o/system/kafka/events/meta`
- [Observability Read](./o-system-observability.md) - `/o/system/observability`
+- [User Sync History Read](./o-system-usersync.md) - `/o/system/usersync`
## Configuration & Settings
diff --git a/docs/api/core/system/o-system-usersync.md b/docs/api/core/system/o-system-usersync.md
new file mode 100644
index 0000000..bca728d
--- /dev/null
+++ b/docs/api/core/system/o-system-usersync.md
@@ -0,0 +1,106 @@
+---
+sidebar_label: "User Sync History"
+keywords:
+ - "/o/system/usersync"
+ - "usersync"
+ - "system"
+last_update:
+ date: "2026-10-23"
+---
+
+# System - User Sync History Read
+
+## Endpoint
+
+```plaintext
+/o/system/usersync
+```
+
+## Overview
+
+Returns the recent user sync history of an app, or of all apps together. Each record shows how long the user sync lagged at one run, and how many users it processed.
+
+## Authentication
+
+Pass `api_key` or `auth_token` as a query parameter, or send `countly-token` as a header. See [Authentication](../../index.md#authentication).
+
+## Permissions
+
+- Requires authenticated dashboard user access to management-read endpoints.
+
+## Request Parameters
+
+| Parameter | Type | Required | Description |
+|---|---|---|---|
+| `api_key` | String | Yes (or use `auth_token`) | Dashboard API key. |
+| `auth_token` | String | Yes (or use `api_key`) | Dashboard auth token. |
+| `app` | String | No | App id. Defaults to `all`, which returns the records of all apps combined. |
+
+## Examples
+
+### Read the combined history of all apps
+
+```plaintext
+/o/system/usersync?api_key=YOUR_API_KEY
+```
+
+### Read the history of one app
+
+```plaintext
+/o/system/usersync?api_key=YOUR_API_KEY&app=6991c75b024cb89cdc04efd2
+```
+
+## Response
+
+### Success Response
+
+```json
+{
+ "data": [
+ {
+ "a": "all",
+ "ts": 1771326000000,
+ "avg": 12.5,
+ "max": 40,
+ "median": 10,
+ "u": 1500
+ }
+ ],
+ "app": "all"
+}
+```
+
+### Response Fields
+
+| Field | Type | Description |
+|---|---|---|
+| `data` | Array | History records of the requested app. |
+| `data[].a` | String | App id, or `all` for the combined record. |
+| `data[].ts` | Number or Date | Time of the sync run. |
+| `data[].lag` | Number or Null | Sync lag of the run. Present in app records. |
+| `data[].avg` | Number or Null | Average lag across apps. Present in `all` records. |
+| `data[].max` | Number or Null | Maximum lag across apps. Present in `all` records. |
+| `data[].median` | Number or Null | Median lag across apps. Present in `all` records. |
+| `data[].u` | Number | Number of users processed in the run. |
+| `app` | String | The requested app id, or `all`. |
+
+## Behavior
+
+- `data` is empty when no records exist for the requested `app`.
+- Records are removed automatically after 24 hours.
+
+## Related Endpoints
+
+- [Kafka Status Read](./o-system-kafka.md)
+- [Aggregator Status Read](./o-system-aggregator.md)
+
+
+Implementation details
+
+**Database Collections**
+
+| Collection | Used for | Data touched by this endpoint |
+|---|---|---|
+| `countly.app_users_sync_history` | Source for user sync history records. | Reads records of the requested app. |
+
+
diff --git a/docs/api/heatmaps/index.md b/docs/api/heatmaps/index.md
index 29746a7..4fc1287 100644
--- a/docs/api/heatmaps/index.md
+++ b/docs/api/heatmaps/index.md
@@ -14,3 +14,5 @@ The Heatmaps feature shows where users click on the pages of your web app.
## Endpoints
- [Heatmaps - Domains Read](./o-heatmaps-domains.md) - `/o/heatmaps/domains`
+- [Heatmaps - Metrics Read](./o-heatmaps-metrics.md) - `/o/heatmaps/metrics`
+- [Heatmaps - Views Read](./o-heatmaps-views.md) - `/o/heatmaps/views`
diff --git a/docs/api/heatmaps/o-heatmaps-metrics.md b/docs/api/heatmaps/o-heatmaps-metrics.md
new file mode 100644
index 0000000..c4f41a7
--- /dev/null
+++ b/docs/api/heatmaps/o-heatmaps-metrics.md
@@ -0,0 +1,72 @@
+---
+sidebar_label: "Metrics Read"
+keywords:
+ - "/o/heatmaps/metrics"
+ - "heatmaps"
+ - "metrics"
+last_update:
+ date: "2026-10-23"
+---
+
+# Heatmaps - Metrics Read
+
+## Endpoint
+
+```plaintext
+/o/heatmaps/metrics
+```
+
+## Overview
+
+Returns the total number of clicks (`t`) and the total scrolling value (`scr`) recorded by heatmaps in an app for a period.
+
+## Authentication
+
+Pass `api_key` or `auth_token` as a query parameter, or send `countly-token` as a header. See [Authentication](../index.md#authentication).
+
+## Permissions
+
+Requires `heatmaps` `Read` permission.
+
+## Request Parameters
+
+| Parameter | Type | Required | Description |
+|---|---|---|---|
+| `api_key` | String | Conditional | Required if `auth_token` is not provided. |
+| `auth_token` | String | Conditional | Required if `api_key` is not provided. |
+| `app_id` | String | Yes | App id. |
+| `period` | String | No | Period to read, for example `30days`, `7days` or a JSON array of two timestamps. Defaults to `30days`. |
+| `segment` | String | No | View segment name. Defaults to no segment. |
+| `segmentVal` | String | No | Value of the view segment. |
+
+## Examples
+
+### Read the metrics of an app
+
+```plaintext
+/o/heatmaps/metrics?api_key=YOUR_API_KEY&app_id=6991c75b024cb89cdc04efd2&period=30days
+```
+
+## Response
+
+### Success Response
+
+```json
+{
+ "_id": null,
+ "t": 120,
+ "scr": 45
+}
+```
+
+### Response Fields
+
+| Field | Type | Description |
+|---|---|---|
+| `_id` | Null | Always `null`. |
+| `t` | Number | Sum of the `t` values for the period. |
+| `scr` | Number | Sum of the `scr` values for the period. |
+
+## Behavior
+
+- When there is no data for the period, `t` and `scr` are `0`.
diff --git a/docs/api/heatmaps/o-heatmaps-views.md b/docs/api/heatmaps/o-heatmaps-views.md
new file mode 100644
index 0000000..4d78e1a
--- /dev/null
+++ b/docs/api/heatmaps/o-heatmaps-views.md
@@ -0,0 +1,101 @@
+---
+sidebar_label: "Views Read"
+keywords:
+ - "/o/heatmaps/views"
+ - "heatmaps"
+ - "views"
+last_update:
+ date: "2026-10-23"
+---
+
+# Heatmaps - Views Read
+
+## Endpoint
+
+```plaintext
+/o/heatmaps/views
+```
+
+## Overview
+
+Returns the views of an app that have at least one recorded click, with their click (`t`) and scrolling (`scr`) values for a period. The response is in the table format used by the dashboard.
+
+## Authentication
+
+Pass `api_key` or `auth_token` as a query parameter, or send `countly-token` as a header. See [Authentication](../index.md#authentication).
+
+## Permissions
+
+Requires `heatmaps` `Read` permission.
+
+## Request Parameters
+
+| Parameter | Type | Required | Description |
+|---|---|---|---|
+| `api_key` | String | Conditional | Required if `auth_token` is not provided. |
+| `auth_token` | String | Conditional | Required if `api_key` is not provided. |
+| `app_id` | String | Yes | App id. |
+| `period` | String | No | Period to read, for example `30days`, `7days` or a JSON array of two timestamps. Defaults to `30days`. |
+| `segment` | String | No | View segment name. Defaults to no segment. |
+| `segmentVal` | String | No | Value of the view segment. |
+| `iSortCol_0` | Number | No | Index of the column to sort by: `0` for name, `1` for `scr`, `2` for `t`. Used together with `sSortDir_0`. Without both, rows are sorted by `t` in descending order. |
+| `sSortDir_0` | String | No | Sort direction, `asc` or `desc`. |
+| `iDisplayStart` | Number | No | Number of rows to skip. |
+| `iDisplayLength` | Number | No | Number of rows to return. When not set or `-1`, all rows are returned. |
+| `sSearch` | String | No | Case-insensitive search text matched against the view name. |
+| `sEcho` | String | No | Value returned unchanged as `sEcho` in the response. |
+
+## Examples
+
+### Read the views of an app
+
+```plaintext
+/o/heatmaps/views?api_key=YOUR_API_KEY&app_id=6991c75b024cb89cdc04efd2&period=30days&iDisplayStart=0&iDisplayLength=10
+```
+
+## Response
+
+### Success Response
+
+```json
+{
+ "sEcho": "1",
+ "iTotalRecords": 1,
+ "iTotalDisplayRecords": 1,
+ "aaData": [
+ {
+ "_id": "6991c75b024cb89cdc04efd3",
+ "t": 120,
+ "scr": 45,
+ "view": "/home",
+ "url": "https://example.com/home",
+ "display": "/home"
+ }
+ ]
+}
+```
+
+### Response Fields
+
+| Field | Type | Description |
+|---|---|---|
+| `sEcho` | String | The `sEcho` value from the request. |
+| `iTotalRecords` | Number | Total number of rows. |
+| `iTotalDisplayRecords` | Number | Total number of rows. |
+| `aaData` | Array | Rows, one per view. |
+
+Each row in `aaData` contains:
+
+| Field | Type | Description |
+|---|---|---|
+| `_id` | String | View id. |
+| `t` | Number | Click value for the period. |
+| `scr` | Number | Scrolling value for the period. |
+| `view` | String | View name, when known. |
+| `url` | String | View URL, when known. |
+| `display` | String | Display name of the view, when known. |
+
+## Behavior
+
+- Only views with `t` greater than `0` are returned.
+- When there is no data, `aaData` is an empty array.
diff --git a/docs/api/hooks/index.md b/docs/api/hooks/index.md
index ca0ba47..17f92a0 100644
--- a/docs/api/hooks/index.md
+++ b/docs/api/hooks/index.md
@@ -18,6 +18,7 @@ The Hooks feature lets you automate actions when Countly events or schedules mat
- [Hooks - Update Status](./i-hook-status.md)
- [Hooks - Delete](./i-hook-delete.md)
- [Hooks - Test](./i-hook-test.md)
+- [Hooks - API Endpoint Trigger](./o-hooks.md)
## Key Capabilities
diff --git a/docs/api/hooks/o-hooks.md b/docs/api/hooks/o-hooks.md
new file mode 100644
index 0000000..2ca1902
--- /dev/null
+++ b/docs/api/hooks/o-hooks.md
@@ -0,0 +1,63 @@
+---
+sidebar_label: "API Endpoint Trigger"
+keywords:
+ - "/o/hooks"
+ - "hooks"
+ - "api endpoint trigger"
+last_update:
+ date: "2026-10-23"
+---
+
+# Hooks - API Endpoint Trigger
+
+## Endpoint
+
+```text
+/o/hooks/{path}
+```
+
+## Overview
+
+Runs a hook that uses the API endpoint trigger. `{path}` is the path configured in the hook's trigger. Every query parameter of the request is passed to the hook's effects.
+
+## Authentication
+
+The handler does not check `api_key` or `auth_token`; the hook is selected by `{path}` only.
+
+## Permissions
+
+The handler does not validate a permission.
+
+## Request Parameters
+
+| Parameter | Type | Required | Description |
+|---|---|---|---|
+| `{path}` | String | Yes | Path segment after `/o/hooks/`, matching the `path` of the hook's API endpoint trigger. |
+| any other query parameter | Any | No | Passed to the hook's effects as request data. |
+
+## Examples
+
+### Trigger a hook
+
+```text
+/o/hooks/my-hook-path?user=john
+```
+
+## Response
+
+### Success Response
+
+```json
+"ok"
+```
+
+## Behavior
+
+- The response is `"ok"` whether or not a hook matches `{path}`.
+- If no enabled hook uses `{path}`, nothing is run.
+- If several hooks use the same path, only the oldest hook is run.
+
+## Related Endpoints
+
+- [Hooks - Save](i-hook-save.md)
+- [Hooks - Test](i-hook-test.md)
diff --git a/docs/api/journey_engine/index.md b/docs/api/journey_engine/index.md
index 7a8d825..190b2c6 100644
--- a/docs/api/journey_engine/index.md
+++ b/docs/api/journey_engine/index.md
@@ -34,6 +34,7 @@ The feature uses config stored in the `plugins` document:
- [Pause Journey](journey-engine-journeys-pause.md) - `/i/journey-engine/journeys/pause`
- [Resume Journey](journey-engine-journeys-resume.md) - `/i/journey-engine/journeys/resume`
- [Approve Journey](journey-engine-approve.md) - `/i/journey-engine/approve`
+- [Approval Queue](journey-engine-approval-queue.md) - `/o/journey-engine/approval-queue`
### Versions
- [List Versions](journey-engine-versions-list.md) - `/o/journey-engine/versions/list`
@@ -50,6 +51,7 @@ The feature uses config stored in the `plugins` document:
- [Performance Over Time](journey-engine-stats-performance.md) - `/o/journey-engine/stats/performance`
- [Active Users](journey-engine-stats-active-users.md) - `/o/journey-engine/stats/active-users`
- [Active Users Detail](journey-engine-stats-active-users-detail.md) - `/o/journey-engine/stats/active-users/detail`
+- [Content Interaction Stats](journey-engine-stats-content.md) - `/o/journey-engine/stats/content`
### Logs & Instances
- [Journey Instances](journey-engine-journey-instances-list.md) - `/o/journey-engine/journey-instances/list`
@@ -57,6 +59,8 @@ The feature uses config stored in the `plugins` document:
- [Journey Block Logs](journey-engine-journey-block-logs-list.md) - `/o/journey-engine/journey-block-logs/list`
### Utilities
+- [Settings](journey-engine-settings.md) - `/o/journey-engine/settings`
+- [User Content](journey-engine-user-content.md) - `/o/journey-engine/user-content`
- [Create Custom Event](journey-engine-event-create.md) - `/i/journey-engine/event`
- [Debug Journey (Admin)](journey-engine-debug.md) - `/o/journey-engine/debug`
diff --git a/docs/api/journey_engine/journey-engine-approval-queue.md b/docs/api/journey_engine/journey-engine-approval-queue.md
new file mode 100644
index 0000000..5a6d682
--- /dev/null
+++ b/docs/api/journey_engine/journey-engine-approval-queue.md
@@ -0,0 +1,120 @@
+---
+sidebar_label: "Approval Queue Read"
+keywords:
+ - "/o/journey-engine/approval-queue"
+ - "GET /o/journey-engine/approval-queue"
+ - "approval-queue"
+ - "journey-engine"
+last_update:
+ date: "2026-10-23"
+---
+
+# Journey Engine - Approval Queue
+
+:::note Enterprise
+This endpoint is part of [Countly Enterprise](https://count.ly/enterprise). To get access, [contact sales](https://count.ly/demo) or [compare versions](https://countly.com/pricing). Existing customers can reach the [support portal](https://support.countly.com/hc/en-us/requests/new) with questions.
+:::
+
+## Endpoint
+
+```
+/o/journey-engine/approval-queue
+```
+
+## Overview
+
+Return the journeys of an app that are waiting for approval. Approvers and global admins see every pending journey. Other members see only the journeys they submitted themselves.
+
+## Authentication
+
+Pass `api_key` or `auth_token` as a query parameter, or send `countly-token` as a header. See [Authentication](../index.md#authentication).
+
+## Permissions
+
+- **Required permission**: `Read` on the `journey_engine` feature
+
+## Request Parameters
+
+- `app_id` (required): App ID
+
+## Examples
+
+```
+GET /o/journey-engine/approval-queue?app_id=6991c75b024cb89cdc04efd2
+```
+
+## Response
+
+### Success Response
+
+```json
+{
+ "result": [
+ {
+ "_id": "67164f4a1f1bd90d6354430a",
+ "name": "Onboarding Journey",
+ "appId": "6991c75b024cb89cdc04efd2",
+ "status": "pending_approval",
+ "created": 1700000000000,
+ "approval": {},
+ "version": {
+ "_id": "67164f4a1f1bd90d6354430b",
+ "status": "draft",
+ "version": 2,
+ "blockCount": 5
+ }
+ }
+ ],
+ "canApprove": true
+}
+```
+
+### Response Fields
+
+| Field | Type | Description |
+|---|---|---|
+| `result` | Array | Journeys pending approval, oldest submission first. |
+| `result[]._id` | String | Journey definition ID. |
+| `result[].name` | String | Journey name. |
+| `result[].appId` | String | App ID. |
+| `result[].status` | String | Journey status. |
+| `result[].created` | Number | Creation timestamp. |
+| `result[].approval` | Object | Approval details of the submission. |
+| `result[].version` | Object | The submitted version, with `_id`, `status`, `version` and `blockCount` (number of blocks). |
+| `canApprove` | Boolean | `true` when the member is an approver or a global admin. |
+
+### Error Responses
+
+- **HTTP 403**
+```json
+{
+ "result": "You do not have permission to view the approval queue"
+}
+```
+- **HTTP 500**
+```json
+{
+ "result": "Failed to fetch approval queue"
+}
+```
+
+## Behavior
+
+- Returns only journeys of the given app with the pending approval status.
+- Members who are neither approvers nor global admins get only the journeys they submitted.
+
+## Related Endpoints
+
+- [Approve Journey](journey-engine-approve.md)
+
+
+Implementation details
+
+**Database Collections**
+
+| Collection | Used for | Data touched by this endpoint |
+|---|---|---|
+| `countly.journey_definition` | Endpoint data source | Reads pending journeys. |
+| `countly.journey_versions` | Submitted version lookup | Reads the submitted version of each journey. |
+
+
diff --git a/docs/api/journey_engine/journey-engine-settings.md b/docs/api/journey_engine/journey-engine-settings.md
new file mode 100644
index 0000000..cfea25b
--- /dev/null
+++ b/docs/api/journey_engine/journey-engine-settings.md
@@ -0,0 +1,68 @@
+---
+sidebar_label: "Settings Read"
+keywords:
+ - "/o/journey-engine/settings"
+ - "GET /o/journey-engine/settings"
+ - "settings"
+ - "journey-engine"
+last_update:
+ date: "2026-10-23"
+---
+
+# Journey Engine - Settings
+
+:::note Enterprise
+This endpoint is part of [Countly Enterprise](https://count.ly/enterprise). To get access, [contact sales](https://count.ly/demo) or [compare versions](https://countly.com/pricing). Existing customers can reach the [support portal](https://support.countly.com/hc/en-us/requests/new) with questions.
+:::
+
+## Endpoint
+
+```
+/o/journey-engine/settings
+```
+
+## Overview
+
+Return the Journey Engine cooldown setting, in hours.
+
+## Authentication
+
+Pass `api_key` or `auth_token` as a query parameter, or send `countly-token` as a header. See [Authentication](../index.md#authentication).
+
+## Permissions
+
+- **Required permission**: `Read` on the `journey_engine` feature
+
+## Request Parameters
+
+- `app_id` (required for non-global-admin users): App ID
+
+## Examples
+
+```
+GET /o/journey-engine/settings?app_id=6991c75b024cb89cdc04efd2
+```
+
+## Response
+
+### Success Response
+
+```json
+{
+ "cooldown": 24
+}
+```
+
+### Response Fields
+
+| Field | Type | Description |
+|---|---|---|
+| `cooldown` | Number | Cooldown between content deliveries, in hours. `24` when not configured. |
+
+## Behavior
+
+- Returns the global `journey_engine.cooldown` setting.
+
+## Related Endpoints
+
+- [User Content](journey-engine-user-content.md)
diff --git a/docs/api/journey_engine/journey-engine-stats-content.md b/docs/api/journey_engine/journey-engine-stats-content.md
new file mode 100644
index 0000000..ce242fa
--- /dev/null
+++ b/docs/api/journey_engine/journey-engine-stats-content.md
@@ -0,0 +1,131 @@
+---
+sidebar_label: "Stats Content Read"
+keywords:
+ - "/o/journey-engine/stats/content"
+ - "GET /o/journey-engine/stats/content"
+ - "content"
+ - "journey-engine"
+ - "stats"
+last_update:
+ date: "2026-10-23"
+---
+
+# Journey Engine - Stats Content
+
+:::note Enterprise
+This endpoint is part of [Countly Enterprise](https://count.ly/enterprise). To get access, [contact sales](https://count.ly/demo) or [compare versions](https://countly.com/pricing). Existing customers can reach the [support portal](https://support.countly.com/hc/en-us/requests/new) with questions.
+:::
+
+## Endpoint
+
+```
+/o/journey-engine/stats/content
+```
+
+## Overview
+
+Return interaction stats for each in-app content block used in a journey: how many times it was shown, how many times users interacted with it, and the clicks per button.
+
+## Authentication
+
+Pass `api_key` or `auth_token` as a query parameter, or send `countly-token` as a header. See [Authentication](../index.md#authentication).
+
+## Permissions
+
+- **Required permission**: `Read` on the `journey_engine` feature
+
+## Request Parameters
+
+- `app_id` (required for non-global-admin users): App ID
+- `journeyDefinitionId` (required): Journey definition ID, a 24-character hexadecimal string
+- `journeyVersionId` (optional): Filter by journey version
+- `period` (optional): Time period (e.g., "7days", "30days"). Use "0days" or omit for all-time
+
+## Examples
+
+```
+GET /o/journey-engine/stats/content?app_id=6991c75b024cb89cdc04efd2&journeyDefinitionId=67164f4a1f1bd90d6354430a&period=30days
+```
+
+## Response
+
+### Success Response
+
+```json
+{
+ "content": [
+ {
+ "contentId": "67164f4a1f1bd90d6354430c",
+ "contentName": "Welcome message",
+ "shown": 900,
+ "interacted": 320,
+ "buttons": [
+ { "id": "Get started", "clicks": 250 },
+ { "id": "Later", "clicks": 70 }
+ ]
+ }
+ ]
+}
+```
+
+### Response Fields
+
+| Field | Type | Description |
+|---|---|---|
+| `content` | Array | One entry per content block, most shown first. |
+| `content[].contentId` | String | Content block ID. |
+| `content[].contentName` | String | Content block title. Empty when not found. |
+| `content[].shown` | Number | Number of times the content was shown. |
+| `content[].interacted` | Number | Number of interactions. |
+| `content[].buttons` | Array | Clicks per button, sorted by button identifier. |
+| `content[].buttons[].id` | String | Button label, or its identifier when it has no label. |
+| `content[].buttons[].clicks` | Number | Number of clicks. |
+
+### Error Responses
+
+- **HTTP 400**
+```json
+{
+ "result": "Error: Missing journeyDefinitionId"
+}
+```
+- **HTTP 400**
+```json
+{
+ "result": "Error: Invalid journeyDefinitionId"
+}
+```
+- **HTTP 403**
+```json
+{
+ "result": "Error: Journey does not belong to this app"
+}
+```
+- **HTTP 500**
+```json
+{
+ "result": "Error: Failed to retrieve content stats"
+}
+```
+
+## Behavior
+
+- The journey must belong to the given app.
+- Daily stats are added up into one entry per content block.
+
+## Related Endpoints
+
+- [Summary Metrics](journey-engine-stats-summary.md)
+
+
+Implementation details
+
+**Database Collections**
+
+| Collection | Used for | Data touched by this endpoint |
+|---|---|---|
+| `countly.journey_definition` | Ownership check | Reads the journey to confirm it belongs to the app. |
+| `countly.journey_content_stats` | Endpoint data source | Reads daily content stats. |
+| `countly.content_blocks` | Content titles | Reads content block titles. |
+
+
diff --git a/docs/api/journey_engine/journey-engine-user-content.md b/docs/api/journey_engine/journey-engine-user-content.md
new file mode 100644
index 0000000..590d114
--- /dev/null
+++ b/docs/api/journey_engine/journey-engine-user-content.md
@@ -0,0 +1,128 @@
+---
+sidebar_label: "User Content Read"
+keywords:
+ - "/o/journey-engine/user-content"
+ - "GET /o/journey-engine/user-content"
+ - "user-content"
+ - "journey-engine"
+last_update:
+ date: "2026-10-23"
+---
+
+# Journey Engine - User Content
+
+:::note Enterprise
+This endpoint is part of [Countly Enterprise](https://count.ly/enterprise). To get access, [contact sales](https://count.ly/demo) or [compare versions](https://countly.com/pricing). Existing customers can reach the [support portal](https://support.countly.com/hc/en-us/requests/new) with questions.
+:::
+
+## Endpoint
+
+```
+/o/journey-engine/user-content
+```
+
+## Overview
+
+Return the content cooldown state of a user and the content waiting in the user's queue.
+
+## Authentication
+
+Pass `api_key` or `auth_token` as a query parameter, or send `countly-token` as a header. See [Authentication](../index.md#authentication).
+
+## Permissions
+
+- **Required permission**: `Read` on the `journey_engine` feature
+
+## Request Parameters
+
+- `app_id` (required): App ID
+- `uid` (required): User ID
+
+## Examples
+
+```
+GET /o/journey-engine/user-content?app_id=6991c75b024cb89cdc04efd2&uid=1
+```
+
+## Response
+
+### Success Response
+
+```json
+{
+ "cooldown_hours": 24,
+ "cooldown_total_ms": 86400000,
+ "cooldown_remaining_ms": 3600000,
+ "last_view_ts": 1700000000000,
+ "queue": [
+ {
+ "content_id": "67164f4a1f1bd90d6354430c",
+ "name": "Welcome message",
+ "type": "content",
+ "source": "content",
+ "priority": 1,
+ "category": null,
+ "created_ts": 1700000000000,
+ "expiry_ts": 1700086400000,
+ "journey_id": "67164f4a1f1bd90d6354430a"
+ }
+ ]
+}
+```
+
+### Response Fields
+
+| Field | Type | Description |
+|---|---|---|
+| `cooldown_hours` | Number | Cooldown in hours: the app's setting, otherwise the global setting, otherwise `24`. |
+| `cooldown_total_ms` | Number | Cooldown in milliseconds. |
+| `cooldown_remaining_ms` | Number | Milliseconds until the user can see content again. `0` when the cooldown is over or set to `0`. |
+| `last_view_ts` | Number | Timestamp of the last content view of the user. `0` when there is none. |
+| `queue` | Array | Queued content that has not expired, highest priority first. |
+| `queue[].content_id` | String | Content ID. |
+| `queue[].name` | String | Content name. Empty when not found. |
+| `queue[].type` | String | Content type. |
+| `queue[].source` | String | `content` or `survey`. Empty when not found. |
+| `queue[].priority` | Number | Queue priority. |
+| `queue[].category` | String or Null | Content category. |
+| `queue[].created_ts` | Number | Timestamp when the item was queued. |
+| `queue[].expiry_ts` | Number | Timestamp when the item expires. |
+| `queue[].journey_id` | String or Null | Journey that queued the item. |
+
+### Error Responses
+
+- **HTTP 400**
+```json
+{
+ "result": "app_id and uid are required"
+}
+```
+- **HTTP 500**
+```json
+{
+ "result": "Error: "
+}
+```
+
+## Behavior
+
+- Queue items are ordered by priority, then by newest first.
+
+## Related Endpoints
+
+- [Settings](journey-engine-settings.md)
+
+
+Implementation details
+
+**Database Collections**
+
+| Collection | Used for | Data touched by this endpoint |
+|---|---|---|
+| `countly.apps` | App cooldown setting | Reads the app's `journey_engine` setting. |
+| `countly.app_users{appId}` | Last content view | Reads the user's last view time. |
+| `countly.content_queue` | Queue | Reads the user's queued content. |
+| `countly.content_blocks` | Content names | Reads content block details. |
+| `countly.feedback_widgets` | Survey names | Reads survey widgets. |
+
+
diff --git a/docs/api/push/app-config.md b/docs/api/push/app-config.md
new file mode 100644
index 0000000..eee76a4
--- /dev/null
+++ b/docs/api/push/app-config.md
@@ -0,0 +1,102 @@
+---
+sidebar_label: "Read App Config"
+keywords:
+ - "/o/push/app-config"
+ - "app-config"
+ - "push"
+last_update:
+ date: "2026-10-23"
+---
+
+# /o/push/app-config
+
+## Endpoint
+
+```plaintext
+/o/push/app-config
+```
+
+Ⓔ Enterprise Only
+
+## Overview
+
+Returns which push platforms have credentials configured for an app, and the app's push test configuration. No credential details are returned.
+
+## Authentication
+
+Pass `api_key` or `auth_token` as a query parameter, or send `countly-token` as a header. See [Authentication](../index.md#authentication).
+
+## Permissions
+
+Requires `Read` permission for Push Notifications.
+
+## Request Parameters
+
+| Parameter | Type | Required | Description |
+|---|---|---|---|
+| `api_key` | String | Yes* | API key authentication |
+| `auth_token` | String | Yes* | Session token authentication |
+| `app_id` | ObjectID | Yes | App ID |
+
+`*` Provide either `api_key` or `auth_token`.
+
+## Examples
+
+### Read the push configuration of an app
+
+```plaintext
+https://your-server.com/o/push/app-config
+ ?api_key=YOUR_API_KEY
+ &app_id=6991c75b024cb89cdc04efd2
+```
+
+## Response
+
+### Success Response
+
+```json
+{
+ "a": {"_id": "67cab1234d1e2a001f3b4501"},
+ "i": {"_id": "67cab1234d1e2a001f3b4502"},
+ "test": {
+ "uids": "user_1,user_2",
+ "cohorts": ["67cab1234d1e2a001f3b4503"]
+ }
+}
+```
+
+### Response Fields
+
+| Field | Type | Description |
+|---|---|---|
+| `a` | Object | Android credentials, present only when configured. Contains the credential `_id`. |
+| `i` | Object | iOS credentials, present only when configured. Contains the credential `_id`. |
+| `h` | Object | Huawei credentials, present only when configured. Contains the credential `_id`. |
+| `w` | Object | Web credentials, present only when configured. Contains the credential `_id`. |
+| `test` | Object | Test configuration of the app with `uids` and `cohorts`. Present only when set. |
+
+## Behavior
+
+1. Reads the push settings of the app.
+2. Lists a platform only if its credential still exists.
+3. Returns `{}` when no platform is configured and no test configuration is set.
+
+### Impact on Other Data
+
+This endpoint is read-only and does not modify data.
+
+## Related Endpoints
+
+- [Push Notifications - Message Test](./message-test.md)
+- [Push Notifications - Read Dashboard](./dashboard.md)
+
+
+Implementation details
+
+**Database Collections**
+
+| Collection | Purpose | Key Fields |
+|---|---|---|
+| `countly.creds` | Checks that the credential of each platform exists | `_id` |
+
+
diff --git a/docs/api/push/index.md b/docs/api/push/index.md
index c493784..4633b26 100644
--- a/docs/api/push/index.md
+++ b/docs/api/push/index.md
@@ -27,6 +27,8 @@ Push Notifications supports campaign creation, targeting, scheduling, API-trigge
- [User History](./user.md)
- [MIME Info](./mime.md)
- [Read Dashboard](./dashboard.md)
+- [Read App Config](./app-config.md)
+- [Generate VAPID Keys](./vapid-keys.md)
## Configuration & Settings
diff --git a/docs/api/push/vapid-keys.md b/docs/api/push/vapid-keys.md
new file mode 100644
index 0000000..b6ce84d
--- /dev/null
+++ b/docs/api/push/vapid-keys.md
@@ -0,0 +1,94 @@
+---
+sidebar_label: "Generate VAPID Keys"
+keywords:
+ - "/o/push/vapid_keys"
+ - "vapid_keys"
+ - "push"
+last_update:
+ date: "2026-10-23"
+---
+
+# /o/push/vapid_keys
+
+## Endpoint
+
+```plaintext
+/o/push/vapid_keys
+```
+
+Ⓔ Enterprise Only
+
+## Overview
+
+Generates a new VAPID public and private key pair for web push credentials. The keys are only returned, not saved. They are stored only when you save them as the app's push credentials.
+
+## Authentication
+
+Pass `api_key` or `auth_token` as a query parameter, or send `countly-token` as a header. See [Authentication](../index.md#authentication).
+
+## Permissions
+
+Requires `Read` permission for Push Notifications.
+
+## Request Parameters
+
+| Parameter | Type | Required | Description |
+|---|---|---|---|
+| `api_key` | String | Yes* | API key authentication |
+| `auth_token` | String | Yes* | Session token authentication |
+| `app_id` | ObjectID | Yes | App ID |
+
+`*` Provide either `api_key` or `auth_token`.
+
+## Examples
+
+### Generate a key pair
+
+```plaintext
+https://your-server.com/o/push/vapid_keys
+ ?api_key=YOUR_API_KEY
+ &app_id=6991c75b024cb89cdc04efd2
+```
+
+## Response
+
+### Success Response
+
+```json
+{
+ "publicKey": "BPublicKeyBase64Url",
+ "privateKey": "PrivateKeyBase64Url"
+}
+```
+
+### Response Fields
+
+| Field | Type | Description |
+|---|---|---|
+| `publicKey` | String | VAPID public key, base64-url encoded. |
+| `privateKey` | String | VAPID private key, base64-url encoded. |
+
+### Error Responses
+
+`500 Internal Server Error`
+
+```json
+{
+ "result": {
+ "errors": ["Failed to generate VAPID keypair"]
+ }
+}
+```
+
+## Behavior
+
+1. Generates a new key pair on every call.
+2. Does not save the keys.
+
+### Impact on Other Data
+
+This endpoint does not modify data.
+
+## Related Endpoints
+
+- [Push Notifications - Read App Config](./app-config.md)
diff --git a/docs/api/sdk/index.md b/docs/api/sdk/index.md
index 523b12f..27e1e94 100644
--- a/docs/api/sdk/index.md
+++ b/docs/api/sdk/index.md
@@ -25,6 +25,7 @@ SDK feature manages runtime SDK configuration, enforcement overrides, and SDK me
- [SDK - SDK Logs Stop](i-sdk-logs-stop.md) - `/i/sdk_logs/stop`
- [SDK - SDK Logs Delete](i-sdk-logs-delete.md) - `/i/sdk_logs/delete`
- [SDK - Connection Test Arm/Disarm](i-sdk-test.md) - `/i/sdk-test`
+- [SDK - Connection Test Status/History](o-sdk-test.md) - `/o/sdk-test`
### Configuration & Enforcement
diff --git a/docs/api/sdk/o-sdk-test.md b/docs/api/sdk/o-sdk-test.md
new file mode 100644
index 0000000..620b871
--- /dev/null
+++ b/docs/api/sdk/o-sdk-test.md
@@ -0,0 +1,162 @@
+---
+sidebar_label: "SDK Test Status/History"
+keywords:
+ - "/o/sdk-test"
+ - "status"
+ - "history"
+ - "sdk-test"
+last_update:
+ date: "2026-10-23"
+---
+
+# SDK - SDK Connection Test Status/History
+
+## Endpoint
+
+```plaintext
+/o/sdk-test/{status|history}
+```
+
+## Overview
+
+Reads SDK connection tests. `status` returns the armed test and the recent test runs of one app user. `history` returns the recent test runs of the whole app. Any other sub-path is not handled by this endpoint.
+
+## Authentication
+
+Pass `api_key` or `auth_token` as a query parameter, or send `countly-token` as a header. See [Authentication](../index.md#authentication).
+
+## Permissions
+
+Requires `sdk` `Read` permission.
+
+## Request Parameters
+
+| Parameter | Type | Required | Description |
+|---|---|---|---|
+| `api_key` | String | Conditional | Required if `auth_token` is not provided. |
+| `auth_token` | String | Conditional | Required if `api_key` is not provided. |
+| `app_id` | String | Yes | App id. |
+| `uid` | String | Conditional | Countly internal user ID. For `status` only. Required if `device_id` is not provided. |
+| `device_id` | String | Conditional | Device ID of the user. For `status` only. Required if `uid` is not provided. |
+| `limit` | Number | No | Number of runs to return. For `history` only. Defaults to `50`, with a minimum of `1` and a maximum of `200`. |
+
+## Examples
+
+### Read the status of a user
+
+```plaintext
+/o/sdk-test/status?api_key=YOUR_API_KEY&app_id=6991c75b024cb89cdc04efd2&device_id=device_123
+```
+
+### Read the history of an app
+
+```plaintext
+/o/sdk-test/history?api_key=YOUR_API_KEY&app_id=6991c75b024cb89cdc04efd2&limit=20
+```
+
+## Response
+
+### Success Response
+
+For `status`:
+
+```json
+{
+ "flag": {
+ "id": "ct_lk2x9a1_f3k9zq",
+ "ts": 1682328445330,
+ "exp": 1682332045330,
+ "by": "6991c75b024cb89cdc04efd1"
+ },
+ "runs": [
+ {
+ "app_id": "6991c75b024cb89cdc04efd2",
+ "uid": "1",
+ "did": "device_123",
+ "tid": "ct_lk2x9a1_f3k9zq",
+ "status": "armed",
+ "armed": {
+ "ts": 1682328445330,
+ "by": "6991c75b024cb89cdc04efd1",
+ "by_name": "Jane Doe",
+ "exp": 1682332045330
+ }
+ }
+ ],
+ "plugins": {
+ "remote-config": true,
+ "ab-testing": false,
+ "surveys": true,
+ "star-rating": true,
+ "content": false
+ }
+}
+```
+
+For `history`:
+
+```json
+{
+ "tests": [
+ {
+ "app_id": "6991c75b024cb89cdc04efd2",
+ "uid": "1",
+ "did": "device_123",
+ "tid": "ct_lk2x9a1_f3k9zq",
+ "status": "armed",
+ "armed": {
+ "ts": 1682328445330,
+ "by": "6991c75b024cb89cdc04efd1",
+ "by_name": "Jane Doe",
+ "exp": 1682332045330
+ }
+ }
+ ]
+}
+```
+
+### Response Fields
+
+| Field | Type | Description |
+|---|---|---|
+| `flag` | Object or Null | The armed test of the user: `id`, `ts` (armed time), `exp` (expiry time) and `by` (member who armed it). `null` when no test is armed or it has expired. (`status` only.) |
+| `runs` | Array | The 5 most recent test runs of the user, newest first. (`status` only.) |
+| `plugins` | Object | Whether each of `remote-config`, `ab-testing`, `surveys`, `star-rating` and `content` is enabled. (`status` only.) |
+| `tests` | Array | Test runs of the app, newest first. (`history` only.) |
+
+Each run contains `app_id`, `uid`, `did`, `tid` (test ID), `status` and `armed` (`ts`, `by`, `by_name`, `exp`), and may contain further fields recorded for the run.
+
+### Error Responses
+
+- `400`
+
+```json
+{
+ "result": "Missing parameter \"uid\" or \"device_id\""
+}
+```
+
+- `400`
+
+```json
+{
+ "result": "User not found"
+}
+```
+
+- `500`
+
+```json
+{
+ "result": "Server error"
+}
+```
+
+## Behavior
+
+- `status` returns an error when the user is not found.
+- `history` does not need `uid` or `device_id`.
+
+## Related Endpoints
+
+- [SDK - Connection Test Arm/Disarm](i-sdk-test.md)
From ee002d9113997b2fb1400e34673bb6e605c7a4db Mon Sep 17 00:00:00 2001
From: GC <87137526+LaNinja06@users.noreply.github.com>
Date: Fri, 23 Oct 2026 13:13:47 -0600
Subject: [PATCH 2/2] Update security note for hook path in documentation
Clarify that the hook path should be treated as a secret due to lack of authentication checks.
---
docs/api/hooks/o-hooks.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/api/hooks/o-hooks.md b/docs/api/hooks/o-hooks.md
index 2ca1902..4f8f17d 100644
--- a/docs/api/hooks/o-hooks.md
+++ b/docs/api/hooks/o-hooks.md
@@ -22,7 +22,7 @@ Runs a hook that uses the API endpoint trigger. `{path}` is the path configured
## Authentication
-The handler does not check `api_key` or `auth_token`; the hook is selected by `{path}` only.
+The handler does not check `api_key` or `auth_token`; the hook is selected by `{path}` only. Anyone who knows the path can call it, so treat the path as a secret.
## Permissions