Node.js SDK

A typed client for public reads and audited operations in TypeScript and JavaScript.

Scoped operations · ESM · v0.2.0 on npm

@inboxychat/sdk
npm i @inboxychat/sdk@0.2.0
On this page

Who it is for

Developers building a Node.js integration, report or back-office tool on top of Inboxy.

What it can do

  • This source version adds 80 audited operations across SDK, CLI and MCP. Installed npm versions and hosted enablement must be checked separately.
  • One typed method per public v1 route (19 methods): company, usage, contacts, conversations, messages, orders and products.
  • collectPages() walks cursor pages for you, up to a page cap.
  • Typed errors (InboxyError.kind) with redacted messages, timeouts and AbortSignal support.
  • resolveCredentials() reads the same key as the CLI: INBOXY_API_KEY, then the OS keychain, then the 0600 config file.

Install

Audited operations and actual coverage

This source version adds 80 audited operations across SDK, CLI and MCP. Installed npm versions and hosted enablement must be checked separately.

Coverage: contacts, tasks, tickets, inbox assignment/status/labels/internal notes and separate text sending; AI drafts/configuration/reviewed text knowledge/channels/tests/readiness/publish; manual orders/status/payment/fulfillment; products/categories; contact status/stage/assignment/tags/custom fields; automation inspection/inactive draft/dry simulation/pause/approved activation; campaign audience estimates/drafts/pause/cancel and approved send/resume/schedule. The 553-route inventory is discovery metadata, not executable full dashboard parity.

SDK: describeOperations(), prepareOperation(id, input, idempotencyKey), executeOperation(id, input, { idempotencyKey, confirmation }). CLI: operations list/inspect/preview/run with --input, --idempotency-key and --confirm. MCP: operations_list, operation_inspect, operation_preview, operation_execute; messages use message_send and activation uses lifecycle_activate; campaign delivery uses campaign_send or campaign_schedule. CLI sending uses messages send after previewing inbox.message.send.

Show the exact preview and obtain explicit user approval before a mutation. The confirmation hash binds normalized input and key; it does not prove human approval. Retain the same idempotency key for recovery. No automatic retries. Existing tenant, role, scope and plan gates apply. OAuth write scopes require new explicit consent and start unchecked; old grants do not gain permissions.

AI tests and knowledge processing may consume credits. Publishing and channel assignment can affect live replies. Sending requires approval of contactId, channelId/type and complete text; the server rechecks the target. Inbox media/template sends, entity deletion, arbitrary HTTP, billing and platform administration are not exposed. Campaign template delivery and scheduling require a separate approved frozen audience/content/sender/time snapshot. Order and contact tag changes may trigger configured automation; custom fields replace the entire map; payment updates do not charge a provider. Refunds/cancellation and full campaign/automation coverage remain excluded.

Needs Node.js >= 20.3. The package is ESM only (use import, not require) and ships its own TypeScript types.

npm
npm i @inboxychat/sdk
pnpm
pnpm add @inboxychat/sdk

Authentication

  1. Sign in to Inboxy as a company admin and open Developers → API keys in the dashboard (/developer-center/keys).
  2. Choose "Create an API key" and give the key a name you will recognise (for example "Claude on my laptop").
  3. Tick only the scopes you need. There is no default set: a key without scopes cannot be created. The read tools need the ":read" scopes (contacts:read, orders:read, ...).
  4. Pick an expiry: 30, 90 (default), 180 or 365 days, or never. The default is 90 days.
  5. Copy the key when it is shown. It starts with "inboxy_". Store it in a secret manager or the OS keychain, never in a repository.

Pass the key to the client yourself, from an environment variable or secret store. On a developer machine, resolveCredentials() can also read a key stored with inboxy auth login.

Same key as the CLI
import { InboxyClient, resolveCredentials } from '@inboxychat/sdk';

const creds = await resolveCredentials();
if (!creds.apiKey) throw new Error('Run inboxy auth login or set INBOXY_API_KEY');
const inboxy = new InboxyClient({ apiKey: creds.apiKey, baseUrl: creds.apiUrl });

Quickstart

Company and latest orders
import { InboxyClient } from '@inboxychat/sdk';

const inboxy = new InboxyClient({ apiKey: process.env.INBOXY_API_KEY! });

const { data: me } = await inboxy.getCompany();
console.log(me.company.name, me.token.scopes);

const orders = await inboxy.listOrders({ status: 'pending', limit: 5 });
for (const order of orders.data) console.log(order.orderNumber);

How-to guides

Read every page

collectPages
import { InboxyClient, collectPages } from '@inboxychat/sdk';

const inboxy = new InboxyClient({ apiKey: process.env.INBOXY_API_KEY! });
const { items, meta } = await collectPages(
  (q) => inboxy.listContacts(q),
  { lifecycleStage: 'customer', limit: 100 },
  20 // max pages
);
console.log(items.length, meta.hasMore ? 'more remain' : 'done');

Handle errors

InboxyError
import { InboxyError } from '@inboxychat/sdk';

try {
  await inboxy.getOrder('ord_123');
} catch (err) {
  if (err instanceof InboxyError) {
    if (err.kind === 'rate_limited') console.log('retry after', err.retryAfterSeconds, 's');
    else if (err.kind === 'forbidden') console.log('missing scope', err.details.requiredScope);
    else console.log(err.kind, err.code, err.message);
  } else throw err;
}

Cancel or time out a request

AbortSignal and timeoutMs
const inboxy = new InboxyClient({ apiKey: process.env.INBOXY_API_KEY!, timeoutMs: 5000 });
const controller = new AbortController();
setTimeout(() => controller.abort(), 1000);
await inboxy.listConversations({ status: 'open' }, { signal: controller.signal });

Reference

new InboxyClient(options)

OptionMeaning
apiKeyRequired. The inboxy_… key.
baseUrlAPI origin (default https://api.inboxy.chat).
timeoutMsPer-request timeout (default 20000, 100-120000).
fetchCustom fetch (tests).
userAgentUser-Agent header.

Methods

Every method returns the API envelope ({ success, data, meta? }) and accepts { signal } as its last argument.

MethodRouteScope
getCompany(options?)GET /api/v1/public/company—
getUsage(options?)GET /api/v1/public/usageanalytics:read
listContacts(query?, options?)GET /api/v1/public/contactscontacts:read
getContact(id, options?)GET /api/v1/public/contacts/:idcontacts:read
listConversations(query?, options?)GET /api/v1/public/conversationsconversations:read
getConversation(id, options?)GET /api/v1/public/conversations/:idconversations:read
listMessages(conversationId, query?, options?)GET /api/v1/public/conversations/:id/messagesmessages:read
listOrders(query?, options?)GET /api/v1/public/ordersorders:read
getOrder(id, options?)GET /api/v1/public/orders/:idorders:read
listProducts(query?, options?)GET /api/v1/public/productsproducts:read
getProduct(id, options?)GET /api/v1/public/products/:idproducts:read
listTickets(query?, options?)GET /api/v1/public/ticketstickets:read
getTicket(id, options?)GET /api/v1/public/tickets/:idtickets:read
listTasks(query?, options?)GET /api/v1/public/taskstasks:read
getTask(id, options?)GET /api/v1/public/tasks/:idtasks:read
listCampaigns(query?, options?)GET /api/v1/public/campaignscampaigns:read
getCampaign(id, options?)GET /api/v1/public/campaigns/:idcampaigns:read
listTemplates(query?, options?)GET /api/v1/public/templatestemplates:read
listAppointments(query?, options?)GET /api/v1/public/appointmentsmeetings:read

Error kinds

InboxyError has kind, status, code, details and retryAfterSeconds. kind is one of: auth, forbidden, not_found, rate_limited, invalid_request, server, timeout, cancelled, network, invalid_response, config.

Limits and safety

  • Writes use the audited operation adapter with explicit approval and idempotency. Text sending and campaign delivery require separate explicit recipient/content approval.
  • Server-side only. Never ship a key to a browser.
  • HTTPS only (http for localhost); redirects are refused; ids are validated and encoded as one path segment.
  • The REST API rate limits apply; a 429 becomes kind "rate_limited" with retryAfterSeconds.

Troubleshooting

  • ERR_REQUIRE_ESM: the package is ESM. Use import, or a dynamic import() from CommonJS.
  • AbortSignal.any is not a function: upgrade to Node.js 20.3 or newer.
  • kind "config" with INSECURE_API_URL: baseUrl must be https:// (http is accepted for localhost only).
  • kind "auth" or "forbidden": run inboxy doctor with the same key to see what is missing.

Create an API key

Keys are created by a company admin on the Developers page of the dashboard.