Your first API integration
Read organization conversations from your own server.
Last updated · Oct 23, 2026
Prepare
Create a key with conversations:read in Settings → API keys. Copy the organization identifier shown there. Store your key as SUPPORTWHALE_API_KEY in a server secret manager. Replace the organization placeholder below with the actual identifier. The production base is https://api.supportwhale.com/v1; local development normally uses http://localhost:3000/v1.
Read and paginate
The response is a JSON array ordered by id ascending. The after cursor is exclusive; use the final id from the previous page. An empty or short page ends pagination. These examples read conversations only and do not send messages.
export SUPPORTWHALE_API_BASE="https://api.supportwhale.com/v1"
export SUPPORTWHALE_ORG_ID="your-organization-id"
# Load SUPPORTWHALE_API_KEY from your server's secret manager.
curl --fail-with-body \
-H "Authorization: Bearer $SUPPORTWHALE_API_KEY" \
"$SUPPORTWHALE_API_BASE/integrations/orgs/$SUPPORTWHALE_ORG_ID/conversations?limit=50"// Server-side TypeScript; never ship the secret to a browser.
const base = process.env.SUPPORTWHALE_API_BASE!;
const org = process.env.SUPPORTWHALE_ORG_ID!;
const key = process.env.SUPPORTWHALE_API_KEY!;
let after = '';
for (;;) {
const query = new URLSearchParams({ limit: '50' });
if (after) query.set('after', after);
const response = await fetch(
`${base}/integrations/orgs/${encodeURIComponent(org)}/conversations?${query}`,
{ headers: { Authorization: `Bearer ${key}` }, redirect: 'error' },
);
if (!response.ok) throw new Error(`SupportWhale HTTP ${response.status}`);
const page: { id: string; status: string; contactId: string }[] = await response.json();
// Process this page in your trusted server application.
if (page.length < 50) break;
after = page[page.length - 1]!.id;
}Send a message
Use the POST conversation-messages operation in the reference with conversations:write. Provide body and a unique clientMessageId. Retrying the same ID with the same key and conversation returns the original message. Set internal to true for a private team note. Message text is limited to 5000 characters; attachments are not supported by this endpoint. A separate read scope is needed to read messages. Internal notes are confidential and must not be forwarded to visitors.
Handle failures
Never log Authorization headers. 401 requires replacing or correcting the key; 403 requires checking its organization and scopes. For 429 wait the retryAfter number of seconds in the JSON response (currently 60). Use backoff for transient server failures. The examples deliberately fail on non-success responses so failures cannot look like empty results.