Vai al contenuto principale
Demo pubblica Pulse è in modalità demo. Apri la demo
Pulse HR
Inizia gratis

Docs

REST API v1

Bearer auth, cursor pagination, webhooks on every event, maintained SDKs.

Base URL

https://api.pulsehr.it/v1

Self-host override

$ export PULSE_API_BASE=https://pulse.internal/v1

Authentication

All requests authenticate with a Bearer token. Mint keys in /developers inside the app. Keys carry a scope (read:*, write:leave, …) and an environment (pk_live_* or pk_test_*).

$ curl https://api.pulsehr.it/v1/employees \
    -H "Authorization: Bearer pk_live_a9f3…" \
    -H "Accept: application/json"

Pagination

Every list endpoint returns cursor pagination. Pass ?limit=50&cursor=…. Responses include next_cursor (null if there are no more pages) and total_count.

{
  "data": [ /* 50 employees */ ],
  "next_cursor": "eyJpZCI6ImVtcF8xOTgifQ==",
  "total_count": 312
}

Rate limits

1,000 requests per minute per API key on Standard. Self-host has no limit (your Postgres will be the bottleneck before this is). Every response carries three headers:

  • X-RateLimit-Limit: 1000
  • X-RateLimit-Remaining: 873
  • X-RateLimit-Reset: 2026-04-20T12:05:00Z

Error format

Every error returns the same envelope — an HTTP status, a stable code string, a human message, and (when relevant) a fields array pinpointing what's wrong.

HTTP/1.1 422 Unprocessable Entity
{
  "error": {
    "code": "unprocessable_entity",
    "message": "end_date must be after start_date",
    "fields": ["end_date"],
    "request_id": "req_01HR3…"
  }
}
HTTP code Meaning
400 invalid_request Payload failed schema validation. Response body lists the failing fields.
401 unauthenticated Missing or malformed Bearer token. Check the Authorization header.
403 permission_denied Authenticated, but the API key scope doesn't allow this operation.
404 not_found Resource ID unknown, or scoped to another tenant.
409 conflict Version mismatch on optimistic lock, or duplicate idempotency key.
422 unprocessable_entity Semantically invalid — e.g. end_date before start_date.
429 rate_limited 1,000 req/min exceeded. Retry-After header tells you when to try again.
500 internal_error Our bug. Every 5xx is paged and we'll email you with the incident ID within 24 h.

Resources

Partial list — the full spec is published as OpenAPI 3.1 at api.pulsehr.it/v1/openapi.json. Generated clients for TS / Python / Go drop on every merge.

/v1/employees

Active and former people in the workspace.

Key fields

  • id
  • email
  • full_name
  • role
  • department
  • manager_id
  • start_date
  • end_date
  • location
  • custom_fields

Methods

  • GET /v1/employees
  • GET /v1/employees/{id}
  • POST /v1/employees
  • PATCH /v1/employees/{id}
  • DELETE /v1/employees/{id}

Webhook events

  • employee.created
  • employee.updated
  • employee.offboarded
/v1/status_log

Async-standup entries. Three lines per person per day.

Key fields

  • id
  • employee_id
  • date
  • lines[]
  • topic
  • created_at

Methods

  • GET /v1/status-log
  • GET /v1/status-log/{id}
  • POST /v1/status-log

Webhook events

  • status_log.posted
/v1/kudos

Peer recognition. Feeds the Employee Score Recognition factor.

Key fields

  • id
  • from_employee_id
  • to_employee_id
  • coins
  • tag
  • note
  • created_at

Methods

  • GET /v1/kudos
  • POST /v1/kudos

Webhook events

  • kudos.awarded
/v1/workload_checkins

Weekly self-reported load — light, balanced, heavy, overloaded.

Key fields

  • id
  • employee_id
  • week_start
  • level
  • created_at

Methods

  • GET /v1/workload-checkins
  • POST /v1/workload-checkins

Webhook events

  • workload.recorded
/v1/leave

Personal leave journal. The IC logs their own days off.

Key fields

  • id
  • employee_id
  • kind
  • start_date
  • end_date
  • days
  • note

Methods

  • GET /v1/leave
  • GET /v1/leave/balance/{employee_id}
  • POST /v1/leave
  • DELETE /v1/leave/{id}

Webhook events

  • leave.logged
  • leave.cancelled

Webhooks

Configure endpoints in /developers → webhooks. Every delivery is HMAC-SHA256 signed with your endpoint's signing secret — verify via the X-Pulse-Signature header. Failed deliveries retry with exponential backoff for 72 hours; replay any event from the dashboard. See the full event catalogue on /ecosystem.

POST https://your.app/pulse/hook
Content-Type: application/json
X-Pulse-Event: leave.approved
X-Pulse-Signature: t=1745148720,v1=9f8a…
X-Pulse-Delivery: del_01HR3…

{
  "id": "evt_01HR3…",
  "type": "leave.approved",
  "created_at": "2026-04-20T10:12:03Z",
  "data": { /* full leave payload */ }
}

SDKs

TypeScript

@pulsehr/sdk

bun add @pulsehr/sdk

Python

pulsehr

pip install pulsehr

Go

pulsehr-go

go get github.com/pulsehr/pulsehr-go

Quick start — TypeScript

import { Pulse } from "@pulsehr/sdk";

const pulse = new Pulse({ apiKey: process.env.PULSE_API_KEY! });

// Post a status-log entry on behalf of an authenticated user
const entry = await pulse.statusLog.create({
  employee_id: "emp_01HR3…",
  lines: [
    "Shipped the OG localiser. Three locales live.",
    "Hit a CLS regression on /product; fix in 1742.",
    "Pairing with Niccolò on the workload trend curve.",
  ],
});

// Send a kudos
await pulse.kudos.create({
  to_employee_id: "emp_01HR4…",
  coins: 10,
  tag: "craft",
  note: "Picked up the failing migration without anyone asking.",
});