Skip to content

Developer Portal ​

At a glance ​

LocationSidebar → Developer Portal (Code2 icon)
PlanAll plans, including the free tier
Related features2

Build and publish your own extensions for the Spun marketplace. Access API documentation and developer tools. The contacts API accepts the same contact details as the contact card (company, job title, department, address, website, notes, extra phone numbers and emails, and custom fields); a value you send wins and one you omit is left alone. API keys and Connected AI apps (claude.ai, ChatGPT or Gemini app connections signed in with Spun) are managed under Settings: connections can be disconnected at any time, and an org manager can enable or disable autonomous sending per connected app (typed confirmation; re-connecting from the AI app resets it). The access level of an already-connected app can also be changed in place from the same panel, between Read-only analyst, Assistant (no sends) and Assistant with sends, without disconnecting and reconnecting: the change takes effect immediately for the app. Raising an app to a send-capable level requires a typed confirmation because it grants more than was approved when the app was connected, the panel keeps showing which level was originally consented to, changing the level always turns autonomous sending back off, and lowering the level cancels any AI sends from that app that are still waiting for approval. REST API keys can be locked to an IP allowlist (single IPs or CIDR ranges, IPv4 and IPv6, set per key in Settings): requests from any other IP are rejected, and an empty list means the key works from anywhere. The allowlist applies only to REST keys - it does not apply to AI/MCP connections, whose traffic comes from shared AI-provider IPs. A wrongly configured list never locks you out of managing keys, since Settings uses your Spun login rather than the key. The REST Actions API (/api/integrations, Bearer wap_ keys) covers text sends, media sends (image, video, audio, voice note, or document, from a URL or a base64 upload, with captions - POST /send-media with the send_message scope), contact and label management, phone checks, webhook subscriptions, and polling lists: GET /messages (read_messages scope) and GET /contacts (read_contacts scope) return cursor-paginated pages (since + limit, max 100 per page) so automation tools like n8n can poll for new activity. Each listed message includes the other party's phone (peer_phone_e164), the group flag (is_group) and, for media messages, a signed download link (media_url) valid for 24 hours and fetchable without a Spun login, together with media_mime, media_filename, media_size and the caption; the link is null when Spun holds no copy of the file, and requesting the message again returns a fresh link. Chats whose number WhatsApp hides behind a privacy ID work too: GET /messages lists them with peer_lid (the privacy ID digits, not a phone number) and identity_state (phone, lid_linked or lid_unlinked), and send-message accepts their @lid chat_id as to, so a helpdesk reply reaches the customer even when no phone number is known. If the WhatsApp channel is offline, text sends are queued for delivery on reconnect, but media sends are not queued - the API returns a clear channel-offline error and the caller retries later. The whole REST Actions API is also described by a public OpenAPI 3.1 document at https://api.spun.com/api/integrations/openapi.json, which needs no API key to read: it lists every endpoint, the scope each one requires, request and response shapes, the error codes, and the webhook delivery envelope with its HMAC-SHA256 signature scheme, so automation tools and developers can generate a client or import the API directly. AI/MCP connections (API keys and Connected AI apps) can be limited to toolset bundles: an org manager picks All tools, a Support, Sales or Reporting toolset, or individual bundles (messaging reads, outbound sends, chat management, contact reads, contact writes, workspace, groups, status and newsletters, presence and profile, commerce, AI compute, analytics, digests) per key or per connected app in Settings, and the AI then only sees and can call the tools in those bundles; existing keys keep every tool until narrowed. MCP tools can also create contacts and update contact details (a dedicated Create and Update Contacts scope; a duplicate phone number is reported instead of creating a second contact, and contact notes are append-only so the AI can never delete what a person wrote), create labels, read per-day message volume and response-rate statistics for a date range, and check their own remaining AI budget, rate-limit usage, toolset and Connected AI read allowance (get_usage_summary reports reads used this period, the plan's allowance, the state - allowance, grace, paused, included or addon - the grace end and the reset date). Connected AI reads never use AI credit: Starter includes 2,000 reads per billing period, Pro and Max include Connected AI with no cap, the trial includes 300; after a one-time 7-day grace period a Starter organization that reaches its allowance gets plan_limit_reached (naming the $25 a month Connected AI add-on and the reset date) on every counted read until the period resets or the add-on is added, while permissions, usage, business overview and delivery-status calls keep working. Org managers can see which MCP tools each key calls and how often they fail (per-tool usage, last 7, 30 or 90 days) in Settings and in the admin MCP control page. Helpdesk and CRM tools can close and reopen conversations through the REST API: an API key holding the Close & Reopen Conversations scope (manage_conversations, ticked in the API key panel) can call POST /api/integrations/conversations/close and POST /api/integrations/conversations/reopen with the contact's phone (E.164) or the chat_id, an optional reason (up to 200 characters, stored on the webhook event) and an optional idempotency_key. The response returns the chat_id and the new state; an unknown number answers 404, a conversation already in that state answers 409 with its current state (so a retry is safe), and the call answers 503 without changing anything if WhatsApp refuses the change. Closing fires conversation.closed and reopening fires conversation.reopened. Limits and cost of the REST API: 60 requests per minute per API key across all endpoints (never quote another number), list endpoints return up to 100 rows per page with cursor pagination (GET /api/integrations/messages returns every stored message, direct and group, oldest first, within the plan's message history), and REST calls draw 1 AI token per 10 calls with no other fee; each outbound webhook delivery draws 1 AI token. Group messages on the REST messages endpoint carry the group's id and subject, and when the API key also holds the read_contacts scope each inbound group message carries the member who wrote it, the same fields the MCP list_messages tool returns: sender_phone (E.164, null when WhatsApp hides the number or when the account AI privacy level is Full), sender_contact_name (the matching Spun contact's name, never the WhatsApp profile name; it is customer-authored text), sender_hidden (true when WhatsApp hides the number) and, for hidden senders, sender_key (a stable per-account id for grouping one member's messages, not a phone number). A key without read_contacts gets none of these fields, there is no read_groups scope on the REST API, and outbound and direct-chat messages never carry them, nor does a group message whose sender Spun never recorded, such as imported history. A poller can therefore read up to 100 messages per page at up to 60 requests per minute per key. Plan requirement for credentials: REST API credentials (wap_ keys with integration scopes such as send_message, read_messages, read_contacts or manage_conversations) require the Pro or Max plan; on Starter the API key panel answers a plan-limit notice with an Upgrade path, and an existing REST key on a Starter plan answers 402 plan_limit_reached on every call. Connected AI apps and MCP keys (claude.ai, ChatGPT, Gemini connections) are on every paid plan including Starter. Customers on a legacy plan from before the current lineup keep their REST API credentials working.

How to use ​

  1. Open Developer Portal from the sidebar.
  2. Create a new extension project.
  3. Follow the SDK documentation.
  4. Submit for review.

FAQ ​

  • How do I build an extension?
  • Where is the developer portal?
  • Is there an API?
Was this page helpful?

Spun Docs - the documentation for Spun, the WhatsApp team inbox by Spun Life LLC.