Skip to main content
docsapipush-api

Push custom data into Pulse.

Any system without a native connector can pump documents into Pulse via a single POST. The doc lands in search, Decision Memory extraction, commitment extraction, and the F4 sensitivity scanner without any extra wiring.

Endpoint

POST /api/v1/documents

Bearer token from /app/admin/api-keys with thewrite scope. Demo workspaces reject pushed docs with a 403.

Request body

  • titlerequired, string, max 280 chars
  • bodyrequired, string, max 200,000 chars
  • url?canonical URL of the source doc
  • authorName?human-readable author name
  • externalId?stable id from your source system; defaults to a UUID
  • idempotencyKey?client-supplied key. Retrying with the same key is safe (see Idempotency)
  • metadata?freeform JSON, stored alongside the doc for downstream filtering
  • visibility?"tenant" (default) or "private"

Examples

cURL
curl -X POST https://pulsehq.tech/api/v1/documents \
  -H "Authorization: Bearer pk_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Q3 OKRs",
    "body": "Our Q3 priorities...",
    "url": "https://internal.pulsehq.tech/okrs/q3",
    "authorName": "Therese Linden",
    "idempotencyKey": "okrs-q3-v1"
  }'
python
import requests, os

resp = requests.post(
    "https://pulsehq.tech/api/v1/documents",
    headers={"Authorization": f"Bearer {os.environ['PULSE_API_KEY']}"},
    json={
        "title": "Q3 OKRs",
        "body": open("okrs-q3.md").read(),
        "url": "https://internal.pulsehq.tech/okrs/q3",
        "idempotencyKey": "okrs-q3-v1",
    },
    timeout=30,
)
resp.raise_for_status()
print(resp.json())  # { "data": { "id": "doc_abc...", "status": "queued" } }

Idempotency

  • 200Retrying with the same idempotencyKey and the same body returns the original id with "status": "duplicate".
  • 409Same idempotencyKey with a different body fails with idempotency_conflict. Use a new key.
  • Without an idempotency key, every retry creates a new doc. Strongly recommended for production integrations.

What happens after the 200

Pulse runs the doc through the same pipeline as native connectors:

  • Embedchunked + vectorized for hybrid retrieval (~10-30s).
  • Summarize1-line summary surfaces in Ask citation chips and the doc list.
  • Decision extractionif the doc records a decision, it lands in Decision Memory.
  • Commitment extractionany “X will do Y by Z” gets surfaced as a commitment.
  • Sensitivity classificationregex + Haiku classifier flags credentials, NDA-marked content, revenue forecasts before the daily cron.
  • Custom-entity extractionper-type extraction for any workspace entity types you’ve defined (no-ops when there are none).

Visibility & permissions

By default pushed docs are visible to the entire tenant (matching how a Notion page or Google Doc would behave on a typical connector). Set"visibility": "private"to scope the doc to the user who owns the API key · the doc is ACL-restricted to that user only and won’t surface in others’ Ask answers.

Limits

  • Body field: 200,000 characters (≈40,000 words).
  • Request body total: 256 KB.
  • Per-key push cap: 5,000 docs per day (separate from the 100/min · 10,000/day shared key limit).
  • 429 responses include a Retry-After header.

Error codes

  • 401unauthorized · missing or invalid bearer.
  • 403insufficient_scope · key lacks the write scope.
  • 403demo_disabled · workspace is a demo tenant.
  • 409idempotency_conflict · same key, different body.
  • 413payload_too_large · request body over 256 KB.
  • 422validation_failed / invalid_json.
  • 429rate_limited / ingest_quota_exceeded.