Skip to main content
rest · v1 · bearer + scopes · stable

The HTTP API.
Plain REST, for when that’s all you want.

Most integrations are happiest on the MCP server, which is typed and permission-scoped. But sometimes you just want a curl. The HTTP API covers the same ground in a flatter, more familiar shape: REST resources, JSON bodies, bearer tokens, no gRPC, no surprises.

Base URL · https://pulsehq.tech/api/v1Auth · bearer + scopesRate limit · ~100 rpm / 10k per day (soft)
a retrieve call, live
POST/v1/map/retrieve200
curl https://pulsehq.tech/api/v1/map/retrieve \
  -H "Authorization: Bearer $PULSE_TOKEN" \
  -d '{ "query": "Q1 ARR breakdown", "k": 8, "sources": ["NOTION"] }'
response
NOTIONnotion://board-q1#arr0.91

“Q1 ARR closed at $4.2M…”

clusters 3conflicts 0

One ranked source with its relevance score, plus how many clusters the answer spans and whether any sources conflict. Pass sources to scope which connectors it draws from.

POST/v1/map/retrievescope · read

Retrieve from the map graph

Search everything Pulse knows with a natural-language query. Returns ranked source passages, each with where it came from and a relevance score, plus cluster and conflict counts so you can see how the answer hangs together. The most-used endpoint in the API.

Body parameters
querystringrequired
Natural-language query.
kint
Max results to return. Default 8, cap 32.
sinceRFC3339
Only retrieve sources updated after this time.
sourcesstring[]
Limit to specific source types (SLACK, NOTION, GITHUB…).
requestcurl
curl https://pulsehq.tech/api/v1/map/retrieve \
  -H "Authorization: Bearer $PULSE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "Q1 ARR breakdown",
    "k": 8,
    "sources": ["NOTION"]
  }'
response · 200json
{
  "data": {
    "sources": [
      { "id": "chk_8a4...",
        "document_id": "doc_2f1...",
        "source": "NOTION",
        "title": "Q1 board pack",
        "url": "notion://board-q1#arr",
        "score": 0.91,
        "snippet": "Q1 ARR closed at $4.2M...",
        "updated": "2026-04-12T09:14:00Z" }
    ],
    "clusters": 3,
    "conflicts": 0
  }
}
POST/v1/askscope · read

Ask a question, get an answer with citations

The most direct way to ask Pulse something. Runs retrieval over everything the key’s user can see, then writes one grounded answer with a citation list, a verdict (confident · uncertain · conflicting), and a confidence score. Synchronous, with no streaming: the answer comes back in one response. Counts against your ask quota.

Body parameters
querystringrequired
The question to ask (3–4000 chars).
modeenum
quick · deep · counter · brainstorm. Default: quick. deep and brainstorm pull more sources.
as_ofRFC3339
Answer as of this point in time (time-travel the graph).
sourcesstring[]
Limit retrieval to specific source types (SLACK, NOTION, GITHUB…).
requestcurl
curl https://pulsehq.tech/api/v1/ask \
  -H "Authorization: Bearer $PULSE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "query": "How did Q1 ARR close?", "mode": "quick" }'
response · 200json
{
  "data": {
    "answer": "Q1 ARR closed at $4.2M [1], up from $3.6M in Q4 [2].",
    "verdict": "confident",
    "confidence": 86,
    "citations": [
      { "source": "notion",
        "title": "Q1 board pack",
        "url": "notion://board-q1#arr",
        "timestamp": "2026-04-12T09:14:00Z" }
    ],
    "conflicts": []
  }
}
POST/v1/synth/draftscope · read

Write an answer, with a source on every sentence

Draft a written answer to a question, with a citation on every sentence. Each sentence carries source_indices pointing back into the sources array, so every claim traces to where it came from.

Body parameters
querystringrequired
The question to answer.
styleenum
terse · balanced · thorough. Default: balanced.
kint
Sources to ground the answer in. Default 8, cap 20.
response · 200json
{
  "data": {
    "answer": "Q1 ARR closed at $4.2M [1]. Three new logos came in via partner referral [2].",
    "sentences": [
      { "text": "Q1 ARR closed at $4.2M [1].",
        "source_indices": [1] },
      { "text": "Three new logos came in via partner referral [2].",
        "source_indices": [2] }
    ],
    "sources": [
      { "index": 1,
        "document_id": "doc_8a4...",
        "chunk_id": "chk_2f1...",
        "title": "Q1 board pack",
        "source": "NOTION",
        "url": "notion://board-q1#arr",
        "score": 0.91 }
    ]
  }
}
GET/v1/map/entity/:idscope · read

Look up a decision, feature, skill, or document

Fetch a single map entity by its ID. The handler resolves Decision, Feature, Skill, or Document (tenant-scoped, ACL-gated for documents) and returns the one that matches. The kind field tells you which one came back.

Path parameters
idstringrequired
The entity’s ID, e.g. dec_4f29.
response · 200json
{
  "data": {
    "kind": "decision",
    "id": "dec_4f29",
    "title": "Move Q1 board pack to Notion",
    "body": "...",
    "rationale": "...",
    "category": "process",
    "decided_at": "2026-04-29T14:02:11Z",
    "decided_by_id": "usr_8a4f",
    "confidence": 0.82
  }
}
POST/v1/skills/:id/runscope · write

Execute an installed Skill

Run an active Skill in your workspace. Any side effects it drafts land as proposed_actions in the PROPOSED state: they still need admin approval before they fire in Slack, Linear, or anywhere else. Requires a write-scoped key whose user is MEMBER or higher.

Body parameters
user_contextstringrequired
The context the Skill runs against (1–8000 chars).
response · 200json
{
  "data": {
    "invocation_id": "inv_9e2f..",
    "status": "completed",
    "explanation": "Drafted a Q1 update and a follow-up task.",
    "proposed_actions": [
      { "agent_action_id": "act_4a1c..",
        "kind": "doc.create_from_plan",
        "title": "Draft Q1 update",
        "rationale": "Summarizes the close from the retrieved sources." }
    ],
    "dropped_actions": [],
    "reason": null
  }
}
POST/v1/actionsscope · write

Propose an agent action

File a draft action (a Slack post, a Linear issue, a Salesforce update, any of the 98 public kinds) into the workspace's approval inbox. Nothing executes until a human approves it at /app/actions; approve and reject endpoints exist for building your own review surface. Idempotency keys make retries safe.

Body parameters
kindstring
One of the 98 public action kinds, e.g. “slack.channel_message” or “linear.create_issue”.
titlestring
Human-readable label shown in the approval inbox.
payloadobject
Kind-specific payload; validated against the kind's schema where one exists.
idempotency_keystring
Optional. Re-POSTing the same key returns the original proposal instead of a duplicate.
response · 200json
{
  "data": {
    "id": "act_7c2...",
    "idempotency_key": "k_5f81...",
    "status": "PROPOSED"
  }
}
GET/v1/auditscope · read

Read the audit log

Page the full audit log for your workspace, every actor, not just the calling key. The key's bound user must be an admin or owner; a member's read-scoped key (including the mobile token) gets a 403. Records can't be changed. It's pageable and exportable; real-time SIEM streaming (Splunk, Datadog, Elastic) is on the roadmap.

Query parameters
actionstring
Prefix match on the action, e.g. “auth.” or “api.map”.
actorstring
Filter to a single user ID.
sinceRFC3339
Only records at or after this time.
untilRFC3339
Only records at or before this time.
response · 200json
{
  "data": [
    { "id": "aud_9b1...",
      "action": "api.map.retrieve",
      "actor_id": "usr_4f29",
      "resource_id": null,
      "metadata": { "k": 8, "hits": 6 },
      "at": "2026-05-01T12:14:08Z" }
  ],
  "meta": {
    "total": 1,
    "perPage": 25,
    "nextCursor": "eyJ2IjoiMjAyNi0wNS0wMVQxMjoxNDowOFoiLCJpZCI6ImF1ZF85YjEifQ"
  }
}

Authentication, boring on purpose

Long-lived bearer tokens with declared scopes. No OAuth dance, no session exchange, every call carries the same Authorization: Bearer header. Workspace keys (pk_live_*) are owner-issued from Settings → API keys; per-user capture tokens (pulse_mcp_*) any member can mint from Settings → Integrations → MCP tokens. Scopes are read, write, and mcp:capture; tokens are revocable in one click.

Workspace key · for backends & cron

Issued by an OWNER from Settings → API keys. Carries read and/or write scope across the whole workspace. Bcrypt-hashed at rest; revocable in one click. Write-scoped calls additionally check that the key's user is a MEMBER or higher.

Authorization: Bearer pk_live_3a4f...

Capture token · for AI tools & MCP

Any MEMBER+ can mint one from Settings → Integrations → MCP tokens (/app/settings/integrations/mcp-tokens); it carries the mcp:capture scope only. Scoped to the user who created it, it's how AI clients push conversations, snippets, and decisions into Pulse over the MCP server.

Authorization: Bearer pulse_mcp_8b2e...

One token. Every endpoint.

One bearer token covers every endpoint. It's plain REST over JSON, bring any HTTP client and curl your way in.