Developer · REST API

A REST API that does not lie about its semantics.

Every SabNode object — contact, conversation, flow, broadcast, order, file — is reachable through a typed REST surface. OpenAPI 3.1, real HTTP status codes, idempotency keys on every POST, cursor pagination and zero-downtime versioning. SDKs for JavaScript, Python and Go are generated from the same spec.

  • OpenAPI 3.1 spec, always current
  • Idempotency-Key header on every POST
  • Cursor pagination, opaque tokens
  • SDKs for JS, Python, Go
The problem

Most CRM APIs are toys in production

You have integrated five CRMs by now. One returned 200 for failed writes. Another paginated by integer offset and silently dropped rows when a contact was added mid-scan. A third had a "create or update" endpoint that swallowed validation errors. By the time you hit production scale, you have built a wrapper library, a retry queue and a deduplication layer just to make the official SDK usable.

The second pain is versioning. You shipped against v2, the vendor pushed v3 with a breaking change, and v2 is in a year-long sunset that nobody bothers to honor. Your integration breaks during a Black Friday window because someone at the vendor decided to "improve" the response shape.

The third pain is observability. You sent 12,000 webhook deliveries last night, the partner is complaining that "events are missing", and the vendor dashboard shows you nothing useful — no per-delivery status, no replay tool, no signing secret rotation. SabNode's REST API and webhook system were designed by engineers who lived inside those failure modes.

What it is

REST API, in depth.

The SabNode REST API is documented by a single OpenAPI 3.1 spec that drives every SDK, the in-app reference and our internal validation. Every endpoint uses real HTTP semantics: 200 for success, 201 for created, 204 for empty success, 400 for input errors, 401 for missing auth, 403 for scope errors, 404 for not found, 409 for idempotency conflicts, 422 for business-rule failures and 429 for rate limiting. There are no 200-with-error-in-body responses anywhere in the surface.

POST requests accept an Idempotency-Key header (UUID v4). A repeated call with the same key replays the original response — even hours later — so a retried network call from your worker never accidentally creates a second contact or a duplicate broadcast. List endpoints use opaque cursor pagination: the cursor encodes the sort key and the position, so adding or deleting rows mid-scan never drops or duplicates results.

SDKs for JavaScript (TypeScript-first), Python (mypy-typed) and Go are generated from the same OpenAPI spec on every release. The generated clients ship retry logic with exponential backoff, jitter, and Retry-After honoring, plus a structured error type per status. You install the SDK with one command, paste your scoped token, and call typed methods with full IDE autocomplete.

Versioning follows a date-header model: every request carries an Api-Version header. Adding fields is non-breaking, removing or renaming requires a new version that is supported for at least 24 months. Sunset announcements are written into the response headers so your dashboards can alert you long before the cutoff.

Capabilities

Everything you get with REST API.

7 capabilities
01

OpenAPI 3.1 spec

A machine-readable OpenAPI 3.1 spec drives the docs, the SDKs and our request validator. Import it into Postman or generate your own client if your stack is not in our official trio.

02

Idempotency keys

Every POST accepts Idempotency-Key. A 24-hour cache replays the original response on retry. Conflicting payloads under the same key return 409 with a structured diff explaining what changed.

03

Cursor pagination

List endpoints return an opaque next_cursor in the response and accept it as a query parameter. Cursors encode the sort key, the position and a tenant-id check, so they are stable under writes.

04

Predictable rate limits

Limits are per-token and per-endpoint family. Every response includes X-RateLimit-Remaining and X-RateLimit-Reset. 429 responses include Retry-After in seconds, and the SDKs honor it automatically.

05

Typed SDKs

JavaScript / TypeScript, Python and Go clients are generated from the spec. They expose typed methods, structured error classes per status, automatic retries and an SSE helper for streaming endpoints.

06

Versioning by header

Api-Version header pins your integration to a release. Additive changes are silent, breaking changes ship a new version supported 24+ months. Sunset notices land in response headers months in advance.

07

Bulk endpoints

Contacts, messages and tag operations have bulk variants accepting up to 1,000 items per call. Bulk endpoints return per-item status so partial failures are observable, not silent.

Use cases

Built for the way teams actually work.

SaaS
Case 01

Sync from data warehouse

A B2B SaaS pushes daily contact updates from Snowflake into SabNode via the bulk upsert endpoint. Idempotency keys derived from a hash of (warehouse_row_id, day) make the job rerunnable without dedup logic.

D2C
Case 02

Custom mobile app

A D2C brand's mobile app uses the REST API to fetch the user's order timeline, fire support tickets and trigger WhatsApp opt-in confirmations — without re-implementing any of the SabNode primitives.

Financial Services
Case 03

Outbound enrichment

A fintech enriches new leads with PAN and address verification through their own internal API, then writes the verified fields back to the SabNode contact via PATCH. Webhook on update fires the next flow.

E-commerce
Case 04

BI dashboard pipeline

A merchant pipes orders, messages and broadcast events from SabNode into BigQuery via a Cloud Run job that uses the cursor-paginated list endpoints. The job is rerunnable thanks to stable cursors.

Logistics
Case 05

Ops automation script

A logistics team runs a nightly Python script that finds contacts with a stuck shipment and patches a tag for the broadcast team. The script uses the typed Python SDK and runs in under 30 seconds for 50k contacts.

How it works

From signup to first send in minutes.

REST API is included on every SabNode workspace. No separate billing, no extra setup — flip it on from your workspace settings.

  1. 01

    Mint a token

    Create a scoped API key in Settings → Developer. Choose scopes (contacts:read, messages:write, etc) and an optional IP allowlist.

  2. 02

    Install the SDK

    npm i @sabnode/sdk, pip install sabnode, or go get github.com/sabnode/sabnode-go. All three are generated from the same spec.

  3. 03

    Make a typed call

    Instantiate the client with your token and Api-Version. Call sdk.contacts.create({ phone, name }) and get a typed Contact back.

  4. 04

    Handle errors

    Catch typed errors per status: ValidationError, RateLimitError, ConflictError. The SDK auto-retries on 429 and 5xx with backoff.

  5. 05

    Listen on webhooks

    Subscribe to events. Verify the HMAC signature, ack within 5 seconds, and the rest of your worker is yours to write.

Plays well with

Works with the tools you already ship on.

OpenAPI 3.1PostmanVercelAWS LambdaGitHub ActionsSnowflakeBigQueryCloud Run
Frequently asked

Questions about REST API.

Can't find what you're looking for? Talk to our team.

How do I retry safely without creating duplicates?
Send an Idempotency-Key header (UUID v4) on every POST. SabNode caches the original response for 24 hours and replays it on retry. If you send the same key with a different payload, the API returns 409 with a JSON diff so you can see exactly which field changed.
How are rate limits structured?
Limits are per-token and per-endpoint family — for example, messages:write has its own bucket from contacts:write. Every response carries X-RateLimit-Remaining and X-RateLimit-Reset, and a 429 includes Retry-After in seconds. The SDKs honour Retry-After automatically with jitter.
Will my integration break if you ship v3?
No, not unless you opt in. Your client pins to an Api-Version header. Additive changes flow silently into your pinned version, breaking changes require explicit version bump. Each version is supported for at least 24 months after release and sunset is announced through response headers months in advance.
Can I use the API from the browser?
Read-only public endpoints (status, configured templates) can be called with a publishable key from the browser. Write endpoints require a server-side scoped token and CORS is locked down accordingly. Most integrations live in a Vercel Edge Function, an AWS Lambda or a worker behind your own API.
How is pagination stable?
List endpoints return opaque cursors that encode sort key, position and a tenant-id check. Inserting or deleting a row in the middle of a scan does not duplicate or drop other rows. Sorts default to created_at desc, and you can request updated_at desc for incremental syncs.
What about webhooks vs polling?
Both are first-class. Webhooks deliver events in near-real-time with HMAC-SHA256 signing and a dead-letter queue. Polling endpoints (with cursor pagination and updated_since filters) are available for environments that cannot accept inbound traffic, like behind a corporate firewall.
Is the API GDPR and DPDP compliant?
Yes. Personal data fields are returned only when scopes allow, deletion requests are processed via a documented PII purge endpoint that propagates to backups within 90 days, and audit logs record every read of PII when audit logging is enabled. Regional data residency is available on enterprise plans.
Developer · REST API

Ship rest api into production this week.

No credit card. No sales call required. Spin up a workspace, plug in a number, and your team is live in under an hour.