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/documentsBearer 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.