Developer Overview

Mulabbe gives developers two ways to build on top of the platform:

  • The REST API (v1) — read and write conversations, contacts, products, orders and usage from your own backend.
  • Webhooks — receive signed HTTP notifications when something happens in your workspace, such as a new message or a new order.

There is also an embeddable website chat widget that adds the assistant to any web page with one script tag. See the widget guide for that.

Base URL

All REST API requests go to:

https://api.<your-domain>/api/v1

Every path in this documentation is relative to this base URL. For example, "List conversations" is:

GET https://api.<your-domain>/api/v1/conversations

Authentication

Every request must carry an API key in the Authorization header:

curl https://api.<your-domain>/api/v1/conversations \
  -H "Authorization: Bearer wk_live_..."

Keys are created in the dashboard under Settings → Developers. There are two kinds:

  • wk_live_... — a live key. It acts on your real channels and data.
  • wk_test_... — a test key. It can read everything, but it may only write to conversations on sandbox channels. Writing to a live channel with a test key returns 403 with the code test_key_live_channel.

Each key carries a list of scopes, and each route requires exactly one scope. See API keys for details.

Versioning

  • The API version is part of the path: /api/v1. Breaking changes will only ever appear under a new version prefix.
  • Webhook payloads carry their own shape version in the apiVersion field (currently 2026-10-01).

Requests and responses

  • Requests and responses are JSON (application/json), encoded as UTF-8.
  • Request bodies are validated strictly: unknown fields are rejected with a 400 validation error.
  • Errors are returned as application/problem+json documents. See Errors.
  • List endpoints use cursor pagination and return { "items": [...], "nextCursor": "..." }. See Pagination.
  • Money is always an integer amount in minor units (for example 12550 for 125.50 SAR) together with an ISO currency code. The API never uses floating-point money.

Rate limits

Each API key has its own token bucket (by default 10 requests per second with a burst of 50; both are configurable per key). Every response — including refusals — carries these headers:

HeaderMeaning
RateLimit-LimitThe bucket size (burst capacity).
RateLimit-RemainingTokens left right now.
RateLimit-ResetSeconds until the bucket is full again.
RateLimit-PolicyThe policy as <burst>;w=<window seconds>.

When the bucket is empty the API answers 429 with the code rate_limited, a retry_after field (in seconds) and a Retry-After header. Back off and retry after that delay.

Idempotent writes

POST and PATCH endpoints accept an optional Idempotency-Key header (1–255 visible ASCII characters). When you retry a request with the same key:

  • The first successful response is stored for 24 hours.
  • A retry with the same key and the same request returns the stored response again, with the header Idempotent-Replayed: true, without running the operation twice.
  • The same key with a different request is rejected with 422 and the code idempotency_key_reused.
  • Failed requests are not stored, so a retry after an error runs normally.

Use a fresh random value (for example a UUID) per logical operation, and reuse it only for retries of that operation.

OpenAPI document

A machine-readable OpenAPI 3.1 description of the whole API is public at:

GET https://api.<your-domain>/api/v1/openapi.json

The same reference is rendered inside the dashboard under Settings → Developers. You can import the document into tools such as Postman or use it to generate a client.

Where to go next

  1. API keys — create a key, pick scopes, rotate safely.
  2. API reference — every endpoint with its method, path and required scope.
  3. Webhooks — subscribe to events and verify signatures.
  4. Errors — the error format and common error codes.
  5. Pagination — how cursors work.
  6. Website chat widget — embed the assistant on your site.