API reference
Every option, collection, handle, method and property of an Outbound instance on one page, each linked to the page that documents it.
createOutbound(options) returns one instance. Everything below hangs off it. The types are exported from outbound-sdk under the names in code font.
import { createOutbound } from "outbound-sdk";
import { instantly } from "outbound-sdk/instantly";
import { demoData, memory } from "outbound-sdk/memory";
const outbound = createOutbound({
adapter: memory({ data: demoData(), workspaceId: "acme" }),
// Defaults for every call. Any call can set its own.
deadline: 60_000,
maxRequests: 200,
retries: 4,
timeout: 30_000,
});
// Properties. Reading them makes no request.
console.log(outbound.provider, outbound.workspaceId, outbound.maturity);
console.log("caveats:", outbound.caveats.length);
console.log("sequence:", outbound.capabilities.sequence);
// Collections, handles and stats.
const campaigns = await outbound.campaigns.list();
const sequence = await outbound.campaign("cmp_founders").sequence();
const stats = await outbound.stats({ from: "2026-10-01", to: "2026-10-31" });
console.log(
campaigns.items.length,
"campaigns,",
sequence.steps.length,
"steps,",
stats.rows[0]?.sent,
"sent"
);
// The same instance scoped to one workspace label.
console.log(outbound.workspace("acme") === outbound);
// `estimate` and `limits` read what the adapter declares. Neither sends a
// request, so this Instantly instance is never called.
const vendor = createOutbound({ adapter: instantly() });
console.log(vendor.estimate({ action: "leads.list", records: 2500 }));
console.log(vendor.estimate({ action: "leads.list" }));
const [limits] = await vendor.limits();
console.log(limits?.provider, "share", limits?.share);
for (const window of limits?.windows ?? []) {
console.log(
`${window.lane}: ${window.used} of ${window.requests} per ${window.perMs} ms`
);
}
memory acme stable
caveats: 0
sequence: true
2 campaigns, 2 steps, 150 sent
true
{
basis: '25 page(s) of 100 at 1 request(s) each, plus 0 per record',
requests: 25
}
{ basis: '1 request(s) per page', requests: null }
instantly share 0.5
default: 0 of 50 per 1000 ms
default: 0 of 3000 per 60000 ms
emails: 0 of 10 per 60000 ms
labelPrediction: 0 of 250 per 2592000000 ms
localBusinessFilters: 0 of 50 per 86400000 ms
localBusinessSearch: 0 of 100 per 86400000 ms
Constructor options
OutboundOptions. Only adapter is required.
| Option | Type | Default | What it does |
|---|---|---|---|
adapter |
Adapter |
required | The vendor behind the instance. See adapters. |
plugins |
OutboundPlugin[] |
none | Layers around every read. plugins[0] is the outermost. See plugins. |
hooks |
OutboundHooks |
none | Functions that observe calls and HTTP requests. See hooks. |
timeout |
number |
30000 |
Milliseconds allowed for each attempt. See retries. |
retries |
number or a policy |
4 |
Retries after the first attempt. See retries. |
deadline |
number |
none | Total milliseconds for one call, across retries and waits. |
maxRequests |
number |
none | The most vendor requests one call may send. |
signal |
AbortSignal |
none | Cancels calls. |
share |
number |
0.5 |
The fraction of the vendor’s published rate limit to use. Greater than 0, at most 1. See rate limits. |
rateLimitStore |
RateLimitStore |
this process’s memory | Where the rate budget is counted. See rate limits. |
allowWrites |
boolean |
false |
Lets raw send requests that are not reads. |
fetch |
typeof fetch |
the global fetch |
A replacement for fetch. |
runtime |
Partial<Runtime> |
the real clock | Replaces the clock, timers and randomness. Meant for tests. |
timeout, retries, deadline, maxRequests and signal are OperationOptions. Set on the constructor they are defaults. Every method that reads also takes them, and a value passed to one call wins for that call.
Collections
Each has list for one page and listAll for every page. Three also have get, exists and getMany. See collections.
| Collection | Record | Filters | get, exists, getMany |
|---|---|---|---|
outbound.campaigns |
Campaign |
status |
yes |
outbound.senders |
Sender |
campaignId |
yes |
outbound.leads |
Lead |
campaignId, listId, email, linkedinUrl, since, until |
yes |
outbound.messages |
Message |
campaignId, leadId, threadId, since, until, include |
no |
outbound.replies |
Reply |
campaignId, category, since, until, include |
no |
outbound.lists |
LeadList |
none | no |
outbound.tags |
Tag |
none | no |
outbound.blocklist |
BlockEntry |
none | no |
outbound.webhooks |
WebhookSubscription |
campaignId |
no |
outbound.workspaces |
Workspace |
none | no |
Handles
A handle is one record and what hangs off it. Making one sends nothing. See handles.
| Handle | Methods | Collections under it |
|---|---|---|
outbound.campaign(id) |
get, sequence, settings, stats |
senders, leads, messages, replies, subsequences, webhooks |
outbound.sender(id) |
get, stats, warmup, health |
none |
outbound.lead(id) |
get, timeline |
none |
outbound.list(id) |
none | leads |
outbound.thread(id) |
messages |
none |
Methods
| Method | Returns | What it does |
|---|---|---|
outbound.stats(options?) |
Promise<StatsResult> |
Counts for the workspace, a campaign, a campaign’s steps or a sender. See stats. |
outbound.limits() |
Promise<LimitsSnapshot[]> |
The rate budget for this credential: each window, its size after share, and how much is used. One entry per adapter behind the instance. It sends no request. See rate limits. |
outbound.estimate(query) |
Estimate |
How many vendor requests a read would cost, from what the adapter declares. It sends no request. |
outbound.workspace(id) |
the same instance type | The instance scoped to one workspace label, with the same plugins. See combine. |
estimate takes action (an operation name such as leads.list), records (how many you expect to read) and limit (a page size). It returns requests and a basis sentence. requests is null when the adapter declares no cost for the action or when you did not say how many records. The output above shows both cases on the Instantly adapter.
On a combined instance, id is a workspace label, or provider:workspace to name one adapter when several share a label. workspace(id) throws NotFound when nothing on the instance matches. On an instance with one adapter, its own label returns the instance itself.
Properties
Reading a property sends no request.
| Property | Type | What it holds |
|---|---|---|
outbound.provider |
string |
The adapter’s name, for example instantly. combined on a combined instance. |
outbound.workspaceId |
string |
Your label for this credential’s client or workspace. It is part of every ref. See records. |
outbound.capabilities |
Capabilities |
What this instance can read, after plugins narrowed it. See capabilities. |
outbound.maturity |
"stable", "beta" or "unverified" |
How far the adapter has been checked against the live API. See what is verified. |
outbound.caveats |
string[] |
What the adapter assumes and has not confirmed. |
outbound.plugins |
OutboundPlugin[] |
The plugins on the instance, outermost first. |
outbound.raw |
RawClient |
The vendor’s own API by path. See raw. |
outbound.native |
NativeClient |
The vendor’s own reads by name. See native reads. |
What every result shares
- Every result carries
meta. See results. - Every listing pages the same way. See pagination.
- Every failure is an
OutboundErrorwith acode. See errors.