API reference
Every endpoint a workspace key can reach
19 operations across 18 paths, generated from the server’s own route table: signals, accounts, listeners, pipeline, collections and exports. Each one carries the permission it needs and a request you can paste into a terminal.
Authenticate every request with Authorization: Bearer op_live_…. Mint a key in workspace settings and tick only the permissions it needs: a key always acts as a member, so a leaked one can read signals and move deals but can never create a listener, change billing, or mint another key.
Each example is the smallest request the document describes, with the real host and a placeholder secret. Replace anything in SHOUT_CASE and the braced segments of a path, and the call is one you can run.
6 of them are marked body not documented: those operations may take a JSON body that /openapi.json does not describe yet, so their example sends none and says so rather than presenting a command that may answer 400.
Operations are listed by path. A route the server mounts without a scope is absent from this page, because no key can call it — those are session-only, and documenting them would describe an interface you cannot reach.
GET /v1/accounts
List accounts
Requires accounts:read
Companies Openpulse has found signals about, cursor-paginated. One row per company rather than per post, which is usually the shape a sales question wants.
Requires a plan that includes account intelligence; a workspace without it gets a 403 naming the plan rather than an empty list.
| Parameter | In | Description |
|---|---|---|
limit | query | Page size, 1-100. |
cursor | query | nextCursor from the previous page. |
owner | query | Only accounts assigned to this member. |
region | query | Only accounts in this region. |
curl -X GET 'https://api.openpulse.cloud/v1/accounts' \
-H 'Authorization: Bearer op_live_YOUR_KEY'GET /v1/accounts/{key}
Get one account
Requires accounts:read
Everything known about one company: its signals, its owner and its region.
| Parameter | In | Description |
|---|---|---|
keyrequired | path | The namespaced account key, e.g. d:acme.com for a domain. Percent-encode it: the : is part of the key, not a separator. |
curl -X GET 'https://api.openpulse.cloud/v1/accounts/{key}' \
-H 'Authorization: Bearer op_live_YOUR_KEY'POST /v1/collections
Create a list
Requires collections:write
A named list to save signals into, shared across the workspace.
curl -X POST 'https://api.openpulse.cloud/v1/collections' \
-H 'Authorization: Bearer op_live_YOUR_KEY'The document declares no request body for this operation, so the example sends none. If the handler requires one, the call answers 400 until /openapi.json describes the shape.
GET /v1/content/ideas/{id}/export.zip
Download an idea's content as a zip
Requires export:read
Every piece written for one content idea, plus its assets, as a zip archive.
| Parameter | In | Description |
|---|---|---|
idrequired | path | The id of the resource. |
curl -X GET 'https://api.openpulse.cloud/v1/content/ideas/{id}/export.zip' \
-H 'Authorization: Bearer op_live_YOUR_KEY'GET /v1/exports/accounts.csv
Export accounts as CSV
Requires export:read
Streams the accounts matching the filters. A key's export is always filtered to what it may read: there is no unscoped dump, because a key is never an admin.
| Parameter | In | Description |
|---|---|---|
owner | query | Only accounts assigned to this member. |
region | query | Only accounts in this region. |
curl -X GET 'https://api.openpulse.cloud/v1/exports/accounts.csv' \
-H 'Authorization: Bearer op_live_YOUR_KEY'GET /v1/exports/pipeline.csv
Export the pipeline as CSV
Requires export:read
Streams the deals matching the filters, with their stages and values.
| Parameter | In | Description |
|---|---|---|
stage | query | Only deals in this stage. |
open | query | true for open stages only. |
curl -X GET 'https://api.openpulse.cloud/v1/exports/pipeline.csv' \
-H 'Authorization: Bearer op_live_YOUR_KEY'GET /v1/exports/signals.csv
Export signals as CSV
Requires export:read
Streams the signals matching the filters. Counts against the workspace's export quota; the response is a stream, so read it rather than buffering it whole.
| Parameter | In | Description |
|---|---|---|
listenerId | query | Only this listener's signals. |
classification | query | Intent label; valid values depend on the listener's mode. |
maxAgeDays | query | Only signals seen within this many days. |
source | query | Platform the signal came from. |
theme | query | Only signals carrying this theme. |
q | query | Free-text search over the signal's title and summary. Matches whole words, with stemming: report finds reporting, repo does not. Truncated past 120 characters. |
curl -X GET 'https://api.openpulse.cloud/v1/exports/signals.csv' \
-H 'Authorization: Bearer op_live_YOUR_KEY'GET /v1/listeners
List listeners
Requires listeners:read
Every listener in the workspace, newest first, cursor-paginated. Each item carries its mode, its objective, its schedule and a count of the signals it has kept.
A key can read listeners and never change one: creating, editing and deleting a listener spends money on a recurring basis and stays with workspace admins.
| Parameter | In | Description |
|---|---|---|
limit | query | Page size, 1-100. |
cursor | query | nextCursor from the previous page. |
curl -X GET 'https://api.openpulse.cloud/v1/listeners' \
-H 'Authorization: Bearer op_live_YOUR_KEY'GET /v1/listeners/{id}
Get one listener
Requires listeners:read
One listener with its full configuration — keywords, exclusions, per-source queries, sensitivity and schedule — plus its current scheduler state.
An id belonging to another workspace is indistinguishable from one that does not exist: both answer 404.
| Parameter | In | Description |
|---|---|---|
idrequired | path | The id of the resource. |
curl -X GET 'https://api.openpulse.cloud/v1/listeners/{id}' \
-H 'Authorization: Bearer op_live_YOUR_KEY'POST /v1/listeners/analyse-website
Derive a listener plan from a website
Requires listeners:analyse
Crawls a website and returns a complete listener plan: keywords, exclusions, per-source queries, and a mode-specific profile — target roles, rival names and pain vocabulary, or place categories. Everything is editable before it runs.
This is the step every competing product replaces with an empty keyword box.
Rate limited to 5 calls an hour per key, and counted against the workspace's monthly allowance. An unreadable website answers 422 with website_unreadable rather than an error: the caller is asked to describe the business instead. Nothing is counted against the allowance unless the analysis succeeded.
To recover from a website_unreadable 422, resend the same request with description filled in and acceptLimited: true: the plan is then generated from the description instead of a crawl.
curl -X POST 'https://api.openpulse.cloud/v1/listeners/analyse-website' \
-H 'Authorization: Bearer op_live_YOUR_KEY' \
-H 'Content-Type: application/json' \
-d '{
"companyName": "YOUR_COMPANY_NAME",
"website": "https://example.com",
"objective": "find_customers",
"sources": [
"x"
]
}'POST /v1/notes
Write a note
Requires collections:write
Attaches a note to a signal, an account or a deal.
curl -X POST 'https://api.openpulse.cloud/v1/notes' \
-H 'Authorization: Bearer op_live_YOUR_KEY'The document declares no request body for this operation, so the example sends none. If the handler requires one, the call answers 400 until /openapi.json describes the shape.
GET /v1/pipeline
List deals
Requires pipeline:read
Every deal in the workspace's pipeline with its stage, cursor-paginated. The board shows all columns at once by fetching pages until they are exhausted; do the same rather than assuming one response is the whole pipeline.
| Parameter | In | Description |
|---|---|---|
limit | query | Page size, 1-100. |
cursor | query | nextCursor from the previous page. |
curl -X GET 'https://api.openpulse.cloud/v1/pipeline' \
-H 'Authorization: Bearer op_live_YOUR_KEY'POST /v1/pipeline
Add a deal
Requires pipeline:write
Creates one deal, optionally from the signal that prompted it.
curl -X POST 'https://api.openpulse.cloud/v1/pipeline' \
-H 'Authorization: Bearer op_live_YOUR_KEY'The document declares no request body for this operation, so the example sends none. If the handler requires one, the call answers 400 until /openapi.json describes the shape.
PATCH /v1/pipeline/{id}
Update a deal
Requires pipeline:write
Moves a deal between stages, or edits its value, owner or notes. Partial: only the fields present are changed.
| Parameter | In | Description |
|---|---|---|
idrequired | path | The id of the resource. |
curl -X PATCH 'https://api.openpulse.cloud/v1/pipeline/{id}' \
-H 'Authorization: Bearer op_live_YOUR_KEY'The document declares no request body for this operation, so the example sends none. If the handler requires one, the call answers 400 until /openapi.json describes the shape.
POST /v1/pipeline/bulk
Add several deals at once
Requires pipeline:write
One request rather than a loop, which is what an agent working from a list of signals should reach for: the per-deal writes are applied together and the response reports each outcome.
curl -X POST 'https://api.openpulse.cloud/v1/pipeline/bulk' \
-H 'Authorization: Bearer op_live_YOUR_KEY'The document declares no request body for this operation, so the example sends none. If the handler requires one, the call answers 400 until /openapi.json describes the shape.
GET /v1/pipeline/roi
Pipeline return over a window
Requires pipeline:read
What the pipeline sourced from Openpulse signals is worth over the window: deals opened, deals won, and value. The answer to 'is this paying for itself'.
| Parameter | In | Description |
|---|---|---|
days | query | Window length in days. |
curl -X GET 'https://api.openpulse.cloud/v1/pipeline/roi' \
-H 'Authorization: Bearer op_live_YOUR_KEY'GET /v1/results
List signals
Requires signals:read
Kept signals across the workspace, newest first, cursor-paginated. A signal is one public post, job posting or review that a listener judged relevant, with its score and the reasoning behind it.
classification values differ per listener mode: filtering by one from the wrong mode returns an empty page rather than an error, which reads as 'nothing found' and is not. Pass listenerId to scope the filter to a listener whose mode you know.
| Parameter | In | Description |
|---|---|---|
listenerId | query | Only signals from this listener. |
limit | query | Page size, 1-100. |
cursor | query | nextCursor from the previous page. |
maxAgeDays | query | Only signals seen within this many days. |
classification | query | Intent label. Valid values depend on the listener's mode. |
source | query | Platform the signal came from. |
theme | query | Only signals carrying this theme. |
q | query | Free-text search over the signal's title and summary. Matches whole words, with stemming: report finds reporting, repo does not. Truncated past 120 characters. |
curl -X GET 'https://api.openpulse.cloud/v1/results' \
-H 'Authorization: Bearer op_live_YOUR_KEY'GET /v1/results/stats
Count signals in a window
Requires signals:read
Totals for the window, counted in the database rather than over a page, so the figures describe every signal rather than the ones that fit in one response. Use this instead of paging through /v1/results to answer 'how many'.
| Parameter | In | Description |
|---|---|---|
listenerId | query | Only count this listener's signals. |
maxAgeDays | query | Window in days. Defaults to the workspace's retention. |
source | query | Platform the signal came from. |
theme | query | Only signals carrying this theme. |
q | query | Free-text search over the signal's title and summary. Matches whole words, with stemming: report finds reporting, repo does not. Truncated past 120 characters. |
curl -X GET 'https://api.openpulse.cloud/v1/results/stats' \
-H 'Authorization: Bearer op_live_YOUR_KEY'POST /v1/signals/{id}/save
Save a signal to a list
Requires collections:write
Adds one signal to a list. Idempotent: saving a signal already in the list is not an error and does not duplicate it.
| Parameter | In | Description |
|---|---|---|
idrequired | path | The id of the resource. |
curl -X POST 'https://api.openpulse.cloud/v1/signals/{id}/save' \
-H 'Authorization: Bearer op_live_YOUR_KEY'The document declares no request body for this operation, so the example sends none. If the handler requires one, the call answers 400 until /openapi.json describes the shape.
Two rate limits, reported two ways. The burst limit on website analysis is per key and answers 429 with a Retry-After header. The monthly analysis allowance is per workspace and answers 429 with readyAt, used and allowed in the body, no header. Something unclear or wrong? Email support@openpulse.cloud.