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_.

http
GET /api/v1/updates HTTP/1.1
Host: signalpad.app
x-api-key: sk_live_YOUR_API_KEY
Content-Type: application/json
Keep keys secret. Never expose your API key in client-side code or public repositories. Use environment variables on your server. The widget SDK uses a separate project key (pk_live_) which is safe for frontend use.

Updates

GET/api/v1/updates

Returns a paginated list of updates across all projects in your workspace, or filtered to a specific project.

Query paramTypeDescription
project_idoptionalstring (UUID)Filter to a single project. Omit to return all projects.
statusoptionaldraft · live · scheduled · archivedFilter by publish status.
limitoptionalnumber (max 100)Number of results per page. Defaults to 50.
offsetoptionalnumberPagination offset. Defaults to 0.
response — 200
{
  "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
}
POST/api/v1/updates

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 fieldTypeDescription
project_idrequiredstringUUID of the project this update belongs to.
titlerequiredstring (max 120)Headline shown in the widget and changelog.
short_descrequiredstring (max 200)Preview text shown under the title in the panel.
bodyoptionalstringFull markdown content for the public changelog.
tagoptionalfeature · improvement · fixDefaults to feature.
release_typeoptionalmajor · minor · patchDefaults to minor.
statusoptionaldraft · live · scheduledDefaults to draft. Pass live to publish immediately (published_at set automatically). Pass scheduled to queue the update for publishing via the dashboard scheduler.
targetingoptionalobjectTargeting rule. Defaults to { "type": "all" }. See Targeting below.
javascript — fetch
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 Created
GET/api/v1/updates/:id

Returns a single update by ID along with its funnel stats.

response — 200
{
  "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.

PATCH/api/v1/updates

Partially updates an existing update. Pass the update’s UUID as the id query parameter. Only the fields you include are changed.

Body fieldTypeDescription
titlestringNew headline (max 120 chars).
short_descstringNew preview text (max 200 chars).
bodystringNew markdown body.
tagfeature · improvement · fix
release_typemajor · minor · patch
targetingobjectReplace the targeting rule entirely.
statussee belowStatus transitions are constrained — see the table below.
Current statusAllowed transitions
draftlive · scheduled
livearchived
scheduled(managed by scheduler)
archived(no further transitions)
javascript — fetch
// 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" }),
});
DELETE/api/v1/updates

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.

http
DELETE /api/v1/updates?id=upd_abc123 HTTP/1.1
x-api-key: sk_live_YOUR_API_KEY
response — 200
{ "success": true }

Analytics

GET/api/v1/analytics

Returns adoption funnel stats per update. Each record represents the aggregated lifecycle of one update — from delivery to feature adoption.

Query paramTypeDescription
update_idoptionalstringReturns stats for a single update only.
project_idoptionalstringFilter to a specific project.
response — 200
{
  "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"
    }
  ]
}
FieldDescription
reachedUsers who had the update rendered in their widget.
clickedUsers who tapped the update card to read more.
dismissedUsers who closed the panel without engaging further.
flow_startedUsers who began the attached guided walkthrough.
flow_completedUsers who completed all steps of the guided flow.
feature_usedUsers who fired the matching track() event after seeing the update. This is your adoption metric.

Segments

GET/api/v1/segments

Lists all user segments for a project.

Query paramTypeDescription
project_idoptionalstringFilter segments to a project.
POST/api/v1/segments

Creates a user segment with targeting rules. Segments can then be referenced in update targeting.

javascript
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 fieldOperatorsNotes
planeq · neqMatches the plan attribute from identify().
roleeq · neqMatches the role attribute.
created_atlt · gt · lte · gteISO 8601 date. Use to target new or long-standing users.
Any custom attreq · neq · containsAny attribute passed to identify() can be used as a rule field.

Error handling

All errors return a JSON body with a single error field.

json
{ "error": "project_id not found in this workspace" }
StatusMeaning
400Bad request — missing required field or invalid value.
401Unauthorised — invalid or missing API key.
404Not found — the referenced resource (project, update) doesn't exist in your workspace.
429Rate limited — max 200 requests per minute per API key.
500Server error — try again. If persistent, contact support@signalpad.app.