REST API Reference
The Signalpad REST API lets you create updates, retrieve adoption analytics, and manage segments from your backend. Base URL: https://signalpad.app/api/v1
Authentication
All API requests require an API key sent in the x-api-key header. Generate keys in Dashboard → Settings → API keys. Keys are prefixed with sk_live_.
GET /api/v1/updates HTTP/1.1 Host: signalpad.app x-api-key: sk_live_YOUR_API_KEY Content-Type: application/json
pk_live_) which is safe for frontend use.Updates
Returns a paginated list of updates across all projects in your workspace, or filtered to a specific project.
| Query param | Type | Description |
|---|---|---|
| project_idoptional | string (UUID) | Filter to a single project. Omit to return all projects. |
| statusoptional | draft · live · scheduled · archived | Filter by publish status. |
| limitoptional | number (max 100) | Number of results per page. Defaults to 50. |
| offsetoptional | number | Pagination offset. Defaults to 0. |
{
"updates": [
{
"id": "upd_abc123",
"title": "New Voice Notes feature",
"short_desc": "Record and send audio messages directly in chat.",
"body": "...",
"tag": "feature",
"release_type": "minor",
"status": "live",
"targeting": { "type": "all" },
"published_at": "2024-12-01T10:00:00Z",
"created_at": "2024-11-29T14:22:00Z"
}
],
"total": 42,
"limit": 50,
"offset": 0
}Creates a new update in draft state (or live if status: "live" is passed). Useful for publishing updates from CI/CD pipelines or deployment hooks.
| Body field | Type | Description |
|---|---|---|
| project_idrequired | string | UUID of the project this update belongs to. |
| titlerequired | string (max 120) | Headline shown in the widget and changelog. |
| short_descrequired | string (max 200) | Preview text shown under the title in the panel. |
| bodyoptional | string | Full markdown content for the public changelog. |
| tagoptional | feature · improvement · fix | Defaults to feature. |
| release_typeoptional | major · minor · patch | Defaults to minor. |
| statusoptional | draft · live · scheduled | Defaults to draft. Pass live to publish immediately (published_at set automatically). Pass scheduled to queue the update for publishing via the dashboard scheduler. |
| targetingoptional | object | Targeting rule. Defaults to { "type": "all" }. See Targeting below. |
const res = await fetch("https://signalpad.app/api/v1/updates", {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": process.env.SIGNALPAD_API_KEY,
},
body: JSON.stringify({
project_id: "proj_xyz789",
title: "Bulk export is now 10x faster",
short_desc: "Large datasets now export in seconds, not minutes.",
tag: "improvement",
release_type: "minor",
status: "live",
targeting: { type: "all" },
}),
});
const { update } = await res.json(); // 201 CreatedReturns a single update by ID along with its funnel stats.
{
"update": { "id": "upd_abc123", "title": "...", ... },
"stats": {
"reached": 1240,
"clicked": 814,
"flow_started": 633,
"flow_completed": 487,
"feature_used": 391,
"reactions_positive": 158,
"reactions_negative": 24
}
}stats is null if the update has never been seen by any user.
Partially updates an existing update. Pass the update’s UUID as the id query parameter. Only the fields you include are changed.
| Body field | Type | Description |
|---|---|---|
| title | string | New headline (max 120 chars). |
| short_desc | string | New preview text (max 200 chars). |
| body | string | New markdown body. |
| tag | feature · improvement · fix | |
| release_type | major · minor · patch | |
| targeting | object | Replace the targeting rule entirely. |
| status | see below | Status transitions are constrained — see the table below. |
| Current status | Allowed transitions |
|---|---|
| draft | live · scheduled |
| live | archived |
| scheduled | (managed by scheduler) |
| archived | (no further transitions) |
// Publish a draft
await fetch("https://signalpad.app/api/v1/updates?id=upd_abc123", {
method: "PATCH",
headers: { "Content-Type": "application/json", "x-api-key": process.env.SIGNALPAD_API_KEY },
body: JSON.stringify({ status: "live" }),
});
// Archive a live update
await fetch("https://signalpad.app/api/v1/updates?id=upd_abc123", {
method: "PATCH",
headers: { "Content-Type": "application/json", "x-api-key": process.env.SIGNALPAD_API_KEY },
body: JSON.stringify({ status: "archived" }),
});Archives an update (soft delete). Pass the UUID as the id query parameter. Archived updates are hidden from the widget but remain accessible in the dashboard and via the API.
DELETE /api/v1/updates?id=upd_abc123 HTTP/1.1 x-api-key: sk_live_YOUR_API_KEY
{ "success": true }Analytics
Returns adoption funnel stats per update. Each record represents the aggregated lifecycle of one update — from delivery to feature adoption.
| Query param | Type | Description |
|---|---|---|
| update_idoptional | string | Returns stats for a single update only. |
| project_idoptional | string | Filter to a specific project. |
{
"analytics": [
{
"update_id": "upd_abc123",
"project_id": "proj_xyz789",
"reached": 1240,
"clicked": 814,
"dismissed": 182,
"flow_started": 633,
"flow_completed": 487,
"feature_used": 391,
"reactions_positive": 158,
"reactions_negative": 24,
"published_at": "2024-12-01T10:00:00Z"
}
]
}| Field | Description |
|---|---|
| reached | Users who had the update rendered in their widget. |
| clicked | Users who tapped the update card to read more. |
| dismissed | Users who closed the panel without engaging further. |
| flow_started | Users who began the attached guided walkthrough. |
| flow_completed | Users who completed all steps of the guided flow. |
| feature_used | Users who fired the matching track() event after seeing the update. This is your adoption metric. |
Segments
Lists all user segments for a project.
| Query param | Type | Description |
|---|---|---|
| project_idoptional | string | Filter segments to a project. |
Creates a user segment with targeting rules. Segments can then be referenced in update targeting.
await fetch("https://signalpad.app/api/v1/segments", {
method: "POST",
headers: { "x-api-key": process.env.SIGNALPAD_API_KEY },
body: JSON.stringify({
project_id: "proj_xyz789",
name: "Pro users — US",
description: "Paid Pro plan, country = US",
rules: [
{ field: "plan", op: "eq", value: "pro" },
{ field: "country", op: "eq", value: "US" },
],
}),
});| Rule field | Operators | Notes |
|---|---|---|
| plan | eq · neq | Matches the plan attribute from identify(). |
| role | eq · neq | Matches the role attribute. |
| created_at | lt · gt · lte · gte | ISO 8601 date. Use to target new or long-standing users. |
| Any custom attr | eq · neq · contains | Any attribute passed to identify() can be used as a rule field. |
Error handling
All errors return a JSON body with a single error field.
{ "error": "project_id not found in this workspace" }| Status | Meaning |
|---|---|
| 400 | Bad request — missing required field or invalid value. |
| 401 | Unauthorised — invalid or missing API key. |
| 404 | Not found — the referenced resource (project, update) doesn't exist in your workspace. |
| 429 | Rate limited — max 200 requests per minute per API key. |
| 500 | Server error — try again. If persistent, contact support@signalpad.app. |