The Pulse REST API and the sample SDKs built on top of it.
Pulse exposes a plain HTTP API. Everything in this repository is downstream of that: the
reference below documents the endpoints, and the js/ and python/ folders
hold sample SDKs — one client library per language, wrapping those same endpoints, plus
menu-driven apps that exercise them. You can use the API directly, use a sample SDK, or generate
your own client for whatever language you work in.
Important
The documentation and examples are not yet final and may be subject to change from time to time. At this stage, they primarily reflect the APIs currently being used by Pulse for this release version. Should there be any updates or changes, we will communicate them accordingly.
| Path | Contents |
|---|---|
rest-api-public.md |
The API reference. Pure HTTP — call it from curl, requests, Invoke-RestMethod, anything. |
pulse-rest-api-public.postman_collection.json |
Runnable Postman version of that reference — 65 requests, bodies pre-filled. |
js/ |
JavaScript sample SDK + apps (Node.js 18+). See js/README.md. |
python/ |
Python sample SDK + apps (3.7+, stdlib only). See python/README.md. |
Start with rest-api-public.md. It covers the session/CSRF handshake, the
response conventions that explain most surprises, then one section per namespace:
| Reference section | Endpoints |
|---|---|
| Authentication & session | /api/login, CSRF token |
systemGroups — security groups |
/api/system/group |
systemUsers — Pulse users |
/api/system/user |
system — environments & instances |
/api/system/*, /api/instance |
settings — alerts & notification groups |
/api/system/alert*, /api/notification/group, /api/pulse/alert |
packages — migration |
/api/packages, /api/package/* |
Four conventions are worth knowing before your first call:
- Pulse is session-based — authenticate once (API key, or username/password) and every subsequent call rides the session cookie. Mutating calls also carry a CSRF token.
- Action endpoints return an envelope,
{"Success":true,"Failed":false}— often with HTTP 200 even on failure, so inspect the body, not just the status code. - An in-progress async job returns
{"Running":true}— poll it, don't treat it as an error. - Unknown JSON fields are dropped silently. A "successful" save that changed nothing is usually a misspelt or wrongly-cased field.
Import pulse-rest-api-public.postman_collection.json,
set the baseUrl and apiKey collection variables, run Fetch CSRF token (its test script
stores the token), then Log in. The six folders mirror the reference sections above.
Each language folder holds a client library plus sample apps that drive it — a worked example of what a Pulse SDK looks like over the endpoints above:
JavaScript (js/) |
Python (python/) |
|
|---|---|---|
| Client library | pulse.api.js — the browser bundle that ships with Pulse, loaded under Node.js via a vm sandbox + cookie jar |
pulse_api.py — a dependency-free client written directly against the REST endpoints |
| Namespaces | PulseApi.system.getSystemServers() |
client.system.get_system_servers() |
| Errors | PulseApiError (.message/.status/.body) |
PulseApiError (.message/.status/.body) |
| Requires | Node.js 18+ (built-in global fetch) |
Python 3.7+, standard library only |
The two are kept at feature parity: same endpoints, same query keys, same CSRF/session handling,
same envelope semantics — only the naming convention changes (camelCase → snake_case).
Payload keys are the server's own JSON, so they stay camelCase in both. Treat either as a
starting point for a client in your own language: the reference is the contract, the SDKs are one
way to wrap it.
Run from inside a language folder; each sample resolves its config and siblings relative to its own directory.
# JavaScript
cd js
node pulse.sample.app.js
# Python
cd python
python3 pulse_sample_app.pyThe js/ samples additionally need pulse.api.js in that folder: it ships with Pulse rather
than with this repo, so copy the bundle from your Pulse Server next to the scripts.
Both languages read the same four settings from a local config file — js/pulse.config.js or
python/pulse_config.py — and environment variables always override the file values, so you
can keep secrets out of it:
| Setting | Environment variable | Purpose |
|---|---|---|
url / URL |
PULSE_URL |
Pulse Server base URL (default http://localhost:8099). |
apiKey / API_KEY |
PULSE_API_KEY |
Personal API key — mint one in the Pulse UI under API Keys. |
user / USER |
PULSE_USER |
Username (if no API key). |
password / PASSWORD |
PULSE_PASSWORD |
Password (if no API key). |
Authentication precedence: the API key is used if set; otherwise username/password; otherwise the call is attempted unauthenticated.
PULSE_URL=https://pulse.example.com PULSE_API_KEY=pulse_xxxxx node pulse.sample.app.jsNeither config file is committed — each is scaffolded with empty credential values on first
run (pulse.config.init.js / pulse_config_init.py), so a fresh clone creates the file instead
of crashing on a missing module. Fill it in, or set the env vars, and run again. An existing
config file is never overwritten.
Every app exists in both languages and maps onto one API namespace. Each is menu-driven: blank
input cancels a prompt, 0 (or q / Ctrl-D) quits, and every app logs out on exit.
| Namespace / topic | JavaScript (js/) |
Python (python/) |
|---|---|---|
| Environments listing (minimal example) | pulse.sample.app.js |
pulse_sample_app.py |
| Security groups | pulse.interactive.groups.js |
pulse_interactive_groups.py |
| System users | pulse.interactive.users.js |
pulse_interactive_users.py |
| Environments / TM1 servers | pulse.interactive.environments.js |
pulse_interactive_environments.py |
| Instance settings | pulse.interactive.instances.js |
pulse_interactive_instances.py |
| System alerts | pulse.interactive.alerts.js |
pulse_interactive_alerts.py |
| Migration packages (view / import / recreate) | pulse.interactive.packages.js |
pulse_interactive_packages.py |
| Create package wizard | pulse.interactive.package-create.js |
pulse_interactive_package_create.py |
| Execute package ⚠ mutates the target TM1 | pulse.interactive.package-execute.js |
pulse_interactive_package_execute.py |
| Migration approvals | pulse.interactive.approvals.js |
pulse_interactive_approvals.py |
Shared plumbing (load the API, log in, read the console) lives in js/pulse.harness.js and
python/pulse_harness.py; the interactive apps import it rather than run it directly.
The alerts and instances apps target a specific environment; they default to the first environment Pulse reports and let you switch from the menu. Executing a package mutates the target TM1 instance, so the execute app gates every run behind an explicit confirmation — test against a disposable environment.