Integration API
Pulse exposes an integration API so another system — an HR tool, a calendar sync, a badge reader, a WMS — can set members' presence and manage their TODOs, and can receive webhooks when things change.
This is separate from the app's own session-authenticated API (which the Pulse web app uses). The integration API uses long-lived bearer tokens and is the supported surface for external systems.
Base URL & auth
https://api.pulse.intrasys.ai/api/v1/external/orgs/<org-slug>/
Authenticate with an integration token (an org admin provisions one for your org):
Authorization: Bearer pulse_int_<token>
Each token is scoped. Available scopes: status:read, status:write, members:read,
statuses:read, projects:read, todos:read, todos:write. Requests are rate-limited to 600
per minute per token.
There is no published OpenAPI document today. This page is the reference; treat these shapes as the contract. Tokens are issued by an org admin (contact Intrasys if the in-app issuance UI isn't available for your org yet).
Conventions
- JSON, camelCase; timestamps are ISO-8601.
- Members are addressed by email or by your own
external_ref(map it once, then refer to people by your identifier). - TODO creates are idempotent on
(integration, external_ref)— retrying the sameexternal_refwon't create a duplicate. - Optimistic concurrency via
ETag/If-Matchon updates.
Endpoints
| Method & path | Scope | Purpose |
|---|---|---|
GET …/statuses | statuses:read | The org's status vocabulary. |
GET …/members | members:read | Members (with your external_ref mapping). |
GET …/projects | projects:read | Projects. |
GET …/members/{email}/status | status:read | A member's current status. |
POST …/members/{email}/status | status:write | Set a member's status. |
DELETE …/members/{email}/status | status:write | Clear back to default. |
GET …/members/{email}/todos | todos:read | A member's TODOs. |
POST …/members/{email}/todos | todos:write | Create a TODO (idempotent on external_ref). |
GET …/todos/by-external-ref/{system}/{ref} | todos:read | Look up a TODO you created. |
PATCH …/todos/{id} | todos:write | Update a TODO. |
POST …/todos/{id}/complete · /uncomplete | todos:write | Toggle done. |
DELETE …/todos/{id} | todos:write | Delete a TODO. |
Set a member's status
- Request
- Response
curl -X POST \
https://api.pulse.intrasys.ai/api/v1/external/orgs/acme/members/[email protected]/status \
-H 'Authorization: Bearer pulse_int_...' \
-H 'Content-Type: application/json' \
-d '{ "status": "external_meeting", "expiresAt": "2026-07-16T17:00:00Z" }'
{ "status": "external_meeting", "statusSource": "integration",
"statusExpiresAt": "2026-07-16T17:00:00Z", "statusUpdatedAt": "2026-07-16T09:00:00Z" }
Create a TODO
- Request
- Response
curl -X POST \
https://api.pulse.intrasys.ai/api/v1/external/orgs/acme/members/[email protected]/todos \
-H 'Authorization: Bearer pulse_int_...' \
-H 'Content-Type: application/json' \
-d '{ "text": "Review PO-1042", "externalSystem": "wms", "externalRef": "PO-1042",
"externalUrl": "https://wms.acme.com/po/1042" }'
{ "id": "td_...", "text": "Review PO-1042", "done": false, "externalRef": "PO-1042" }
Webhooks
Subscribe to events and Pulse will POST them to your endpoint, HMAC-SHA256 signed in an
X-Pulse-Signature header. Each event has a ULID id and a per-org monotonic sequence. Delivery
retries with backoff (roughly 1m, 5m, 30m, 2h, 6h, 12h, 24h).
Event types:
todo.created · todo.updated · todo.completed · todo.uncompleted · todo.archived ·
todo.deleted · todo.reordered · member.status.changed · member.joined · member.left ·
project.created · project.updated · project.archived · share_link.accessed · webhook.test
Verify the signature over the raw request body with your subscription's signing secret before trusting a payload.