Pulse CRM API
Welcome to the Pulse API reference. Every endpoint here is authenticated — your first job is to get a session token and pass it as a Bearer token on every subsequent request.
There are two ways to obtain a session token. Pick the one that matches your use case:
- API key + secret — recommended for server-to-server integrations, automation, and background jobs.
- Username + password — for interactive users (e.g. a frontend signing in on behalf of a person).
Both paths exchange credentials for the same token value, and from that point forward every request to the API works identically regardless of how you logged in.
Auto-fill: When you log in via the Try it panel on any
POST /auth/loginpage, this site automatically captures the returnedtokenandprimaryAccount.accountIdand injects them into theBearerAuthandX-Account-IDfields of every other operation. You only need to log in once per session.
Option A — API key authentication (server-to-server)
Step 1. Create an API key (one-time)
API keys live on a single account and carry a fixed permission set. Have an account admin create one in the Pulse UI under Settings → API Keys, or call POST /apikeys with an existing session token.
The response includes both apiKey and apiSecret. The apiSecret value is only returned this one time — store it somewhere safe (a password manager, a secret store, environment variables). If you lose it, you'll have to rotate the key.
Step 2. Exchange the key + secret for a session token
Open POST /auth/login and click Try it, then send a body shaped like:
{
"apiKey": "apiKey-xxxxxxxxxxxx",
"apiSecret": "xxxxxxxxxxxxxxx"
}
The response includes a token field — that's your session token. The auto-fill picks it up.
Step 3. Make your first authenticated request
Open GET /auth/session and click Try it. The Authorization and X-Account-ID headers are already filled in — just send. You should get back the same payload as /auth/login, which confirms the token is live and shows you which account / role / permissions it grants.
Tip: For quick one-off scripts you can skip the session exchange entirely and pass
x-api-key: apiKey-xxxxxxxxxxxx+x-api-secret: xxxxxxxxxxxxxxxdirectly on each request. Don't do this in production — it sends your long-lived credential on every call and bypasses the token's short lifetime. Use session tokens unless you have a specific reason not to.
Option B — Username + password authentication (interactive users)
Step 1. Log in with email + password
Open POST /auth/login and Try it with:
{
"email": "user@example.com",
"password": "your-password"
}
Step 2. Verify
Open GET /auth/session and Try it — the auto-filled headers should round-trip your session back to you.
Common conventions
Account scoping — X-Account-ID
Many endpoints operate on a specific account (a tenant). The auto-fill sets this header to your primary account (the primaryAccount.accountId from your login response). If you belong to multiple accounts and want to act on a non-primary one, change the value of the X-Account-ID field on the Try-It panel. Omitting the header falls back to the primary account on the server side.
Authentication
Two security schemes are available — pick one in the Authentication dropdown at the top of any operation:
| Scheme | Headers | Use when |
|---|---|---|
BearerAuth |
Authorization: Bearer <token> |
After exchanging credentials at /auth/login. Preferred. |
ApiKey + ApiSecret |
x-api-key: <key> + x-api-secret: <secret> |
One-off scripts or short test calls only. |
/auth/login itself is public — it never requires auth (it's how you get auth).
Error envelope
Errors come back as JSON with an HTTP status that matches the error class. Common shape:
{
"error": "Not authorized",
"message": "readTickets permission is required"
}
Status codes:
400— bad request body (validation failure)401— missing or expired session token403— authenticated, but caller lacks the required permission404— resource not found, or the caller doesn't have access to it409— conflict (duplicate, version mismatch)429— rate limit hit5xx— server error; safe to retry idempotent calls with exponential backoff
Pagination
List endpoints accept page and limit query parameters (1-indexed page, default page size varies by resource). Responses include total and pageCount so you can iterate until you've drained the list.
Custom headers
| Header | Purpose |
|---|---|
X-Account-ID |
Account scoping (see above). |
x-pulse-id |
Optional client-generated request ID; echoed back for tracing. |
Authorization |
Bearer session token. |
x-api-key / x-api-secret |
Direct API-key auth (one-off scripts only). |
Token lifetime
Session tokens are valid for one hour by default and extend automatically while in active use. There is no explicit refresh endpoint — when a token expires, log in again to get a new one. For long-running server processes, exchange your API key/secret for a fresh token at the start of each work batch rather than caching tokens indefinitely.
Servers
- Production —
https://api.pulsecrm.com - Development —
https://api.dev.pulsecrm.com
The server selector at the top of every Try-It panel switches between environments. The same auth flow applies to both; credentials are scoped per environment.