Skip to content

Clients & SDKs ​

There are four ways for a tool to talk to Pulse. They all end up as the same events in the same EVENTS stream.

WayCredentialReachGood for
NATS with an SDK or the CLIthe client's .credstls://r.events.example.com:4222, directlong-running tools, bots and agents; replay and durable consumers; request/reply; large payloads as blobs
WebSocket /wsthe client's .credswss://events.example.com/ws, via Cloudflarebrowser apps (the TypeScript SDK's browser bundle)
HTTP API /api/v1an HTTP tokenhttps://events.example.com/api/v1, via Cloudflareshell scripts, cron jobs, serverless functions, anything that can only make HTTP requests
Inbound webhooks /hooks/<name>the sender's signaturehttps://events.example.com/hooks/<name>GitHub, Stripe and other services that send webhooks

And one way out: outbound webhooks push matching events to your own HTTP endpoints.

Which one to pick ​

  • Prefer NATS. It is the native protocol: publishes are acknowledged by JetStream, subscriptions replay from a time or sequence and then keep following, durable consumers survive restarts, and connections reconnect on their own. The SDKs handle the envelope and stay inside the client's grants.
  • Use the HTTP API when a NATS client is impractical. It publishes (one event or a batch of up to 100), bridges requests, replays pages of events and offers an SSE live tail. There are no durable consumers over HTTP.
  • Use inbound webhooks for third-party senders, so they need no Pulse credential at all.
  • Use outbound webhooks for services that should receive events without running a NATS client.

Libraries ​

InstallPage
Gogo get github.com/aurimasniekis/go-pulse/pkg/pulseGo SDK
Python ≥ 3.10 (asyncio)pip install "git+https://github.com/aurimasniekis/go-pulse#subdirectory=sdk/python"Python SDK
TypeScript (node ≥ 22, browsers)pnpm add "github:aurimasniekis/go-pulse#path:/sdk/ts"TypeScript SDK
CLIgo install github.com/aurimasniekis/go-pulse/cmd/pulse@latestpulse CLI

The SDKs are not published to package registries; install them from the repository. All three are tested against the same conformance vectors for the envelope, and against each other over a real server (Go publishes; Python, TypeScript over TCP and WebSocket, and a real browser replay the same events).

Every SDK has the same shape:

  • connect with a .creds file; the client ID in the credentials sets the inbox prefix _INBOX_<client-id>;
  • publish(subject, type, data) and wait for the JetStream acknowledgement;
  • subscribe(filter, since / seq / new / durable): ordered replay then live, or a durable consumer with ack, nak and term;
  • request for request/reply services;
  • put blob / get blob for payloads above 1 MiB.

Plain NATS clients ​

Any NATS client works with a Pulse .creds file, with two rules:

  1. Use the client's inbox prefix. Replies and JetStream acknowledgements are only allowed on _INBOX_<client-id>.>. With the nats CLI: --inbox-prefix _INBOX_<client-id>. The ID is on the client's page.
  2. Create filtered consumers. Clients may only create consumers through the filtered create subject ($JS.API.CONSUMER.CREATE.<stream>.<name>.<filter>) with a filter inside their grants. Library helpers that use other API subjects fail with permission violations.
sh
nats --server tls://r.events.example.com:4222 --creds ./door-bot.creds --inbox-prefix _INBOX_<client-id> \
  pub evt.home.door.opened '{"door":"front"}' -H ce-type:home.door.opened.v1

Events published without the envelope headers are still stored, and shown as untyped. The envelope is described in Subjects and the envelope.

Permission errors ​

NATS reports permission violations asynchronously. A publish or subscribe outside the grants usually shows up as a timeout (5 seconds by default) in the SDK, plus a Permissions Violation error on the connection. If something times out, check the client's grants first.

Released under the Apache-2.0 license.