npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

overblast

v0.1.0

Published

Overblast SDK + CLI — manage workspaces, social posts, DMs, webchat, email, phone calls, todos, contact memory, and webhooks.

Readme

overblast

A unified SDK + CLI for the Overblast platform: workspaces, social posts/DMs, webchat, email, phone calls, conversation memory, todos, and webhooks.

Works as a Node.js CLI or as an ESM library you import from your own code.

npm install overblast

Quick start

Use it as a Node.js library

import { Overblast } from 'overblast';

const ob = new Overblast({ apiKey: process.env.OVERBLAST_API_KEY! });

// List all conversations across a workspace's social inbox
const { conversations } = await ob.conversations.list(profileSetId);

// Reply to a webchat conversation
await ob.webchat.reply(computerId, {
  conversationId: 'webchat_abc123',
  content: 'Hi! Yes, we are open until 6pm today.',
});

// Place a call
const { callId } = await ob.calls.create({
  computerId,
  phoneE164: '+15551234567',
  fromPhoneE164: '+15557654321',
  goal: 'Confirm Tuesday\'s 3pm appointment.',
});

// Subscribe to incoming messages in real time
await ob.webhooks.create(computerId, {
  eventType: 'message.received',
  url: 'https://my-app.example.com/inbound',
});

Use it as a CLI

export OVERBLAST_API_KEY=ob_live_...

overblast profile-sets list
overblast conv list <profileSetId>
overblast webchat reply <computerId> webchat_abc123 "Yes, we're open until 6pm."
overblast email send <computerId> [email protected] "Re: your enquiry" "Thanks for…" --domain 0-0.chat
overblast call <computerId> +15551234567 "Confirm Tuesday's 3pm" --from +15557654321
overblast webhook create <computerId> --event message.received --url https://my-app.example.com/inbound

overblast --help prints the full command reference.


Authentication

The SDK and CLI both authenticate with a workspace API key. Pass it three ways (in priority order):

  1. --api-key ob_live_... flag (CLI only)
  2. OVERBLAST_API_KEY environment variable
  3. new Overblast({ apiKey: '...' }) constructor (library)

API keys are scoped to a single computer (workspace). Mint and rotate keys with:

overblast api-keys list
overblast api-keys create --name "claude-code" --computer <cid> \
  --scopes dm:send,todo:read,todo:create
overblast api-keys revoke <keyId>

The default base URL is https://brain.deployd.network/social. Override via --base-url (CLI) or baseUrl (library) when targeting staging/preview.


What you can do

The SDK exposes every conversational channel the platform serves, plus the admin and bookkeeping primitives around them.

| Channel | Read messages | Send / reply | Real-time | Notes | |---|---|---|---|---| | Social DMs (Twitter, IG, FB, etc.) | conversations.list / conversations.messages | conversations.sendDm | message.received webhook | Per profile set | | Webchat (website widget) | webchat.info (settings) | webchat.reply | message.received webhook | Conversation IDs are webchat_<deviceId> | | Email (ticketed threads) | n/a — surfaced via webhooks | email.createThread / email.reply | message.received webhook | Inbound goes to {cid}.agent@{domain} | | Phone calls (Twilio + voice agent) | calls.list / calls.conversation / calls.transcriptPdfUrl / calls.recordingUrl | calls.create | call.started / call.ended webhooks | LiveKit-powered voice agent runs the call | | Comments / reviews | passthrough.call (raw Zernio routes) | same | comment.received webhook | Listed under "raw API" below |

Cross-cutting:

| Capability | Method | |---|---| | Workspace todo list (active by default) | todos.list(cid) | | Conversation-scoped todos | todos.list(cid, { conversationId }) | | Archived/all todos | todos.list(cid, { status: 'all' }) | | Contact memory (markdown) | contacts.memory(profileSetId, contactId) | | Bundled conversation context | context.forConversation(...) | | Real-time event push | webhooks.create / list / delete |


Library reference

Constructor

new Overblast({
  apiKey: string,        // required
  baseUrl?: string,      // default https://brain.deployd.network/social
})

All methods return parsed JSON. Errors throw OverblastError with status/body for inspection:

import { OverblastError } from 'overblast';

try {
  await ob.calls.create({ … });
} catch (e) {
  if (e instanceof OverblastError && e.status === 402) {
    console.warn('Out of credits:', e.body);
  } else throw e;
}

conversations — social inbox (DMs across platforms)

| Method | Endpoint | |---|---| | conversations.list(profileSetId, { limit?, cursor?, archived? }) | GET /z/:psid/conversations | | conversations.messages(profileSetId, conversationId, { limit?, before? }) | GET /z/:psid/conversations/:id/messages | | conversations.sendDm(profileSetId, conversationId, { text, attachmentUrl?, attachmentType?, tmpKey? }) | POST /z/:psid/dm/:id | | conversations.start(profileSetId, body) | POST /z/:psid/conversations | | conversations.update(profileSetId, conversationId, body) | PUT /z/:psid/conversations/:id | | conversations.deleteMessage(profileSetId, conversationId, messageId) | DELETE /z/:psid/dm/:id/messages/:mid | | conversations.editMessage(profileSetId, conversationId, messageId, { text }) | PATCH /z/:psid/dm/:id/messages/:mid |

webchat — live website chat

| Method | Endpoint | |---|---| | webchat.info(computerId) | GET /webchat/:cid/info | | webchat.reply(computerId, { conversationId, content?, attachmentUrl?, attachmentType?, tmpKey? }) | POST /webchat/:cid/reply | | webchat.getSettings(computerId) / webchat.updateSettings(cid, settings) | GET / PUT /webchat/settings/:cid | | webchat.createInviteToken(computerId) | POST /webchat/settings/:cid/token |

conversationId is always webchat_<deviceId>.

email — ticketed email threads

| Method | Endpoint | |---|---| | email.createThread({ computerId?, toAddr, toName?, receivedOnDomain, subject, body, attachments?, tmpKey? }) | POST /email/threads | | email.reply(threadId, { body, attachments?, tmpKey? }) | POST /email/threads/:id/reply | | email.quota(computerId?) | GET /email/quota |

receivedOnDomain is one of '0-0.chat' | 'deploydstudio.com' | 'overblast.com' — the From address on outbound is {computerId}.agent@{receivedOnDomain}.

Attachment items reference R2-stored objects:

{ key: 'kb://my-folder/spec.pdf', filename: 'spec.pdf', contentType: 'application/pdf' }

Inbound mail is delivered by Cloudflare Email Routing to the agent address and fired as a message.received webhook event — there is no polling read API.

calls — phone calls + voice agent

| Method | Endpoint | |---|---| | calls.create({ computerId?, phoneE164, fromPhoneE164, goal, scheduleAt?, contactName?, taskInstructions?, taskTemplateIds?, voice?, language?, skillId? }) | POST /calls/ | | calls.list({ computerId?, status?, direction?, limit?, offset? }) | GET /calls/ | | calls.listConversations({ computerId?, limit? }) | GET /calls/conversations | | calls.conversation(conversationId) | GET /calls/conversations/:id | | calls.get(callId) | GET /calls/:id | | calls.recordingUrl(callId) | GET /calls/:id/recording-url | | calls.transcriptPdfUrl(callId) | GET /calls/:id/transcript-pdf | | calls.reschedule(callId, scheduleAt) | PATCH /calls/:id/schedule | | calls.setGoal(callId, goal) | PATCH /calls/:id/goal | | calls.cancel(callId) | POST /calls/:id/cancel | | calls.sharedNumbers() | GET /calls/shared-numbers |

Notes:

  • fromPhoneE164 must be one of the workspace's shared-numbers.
  • The platform refuses calls when balance < CALL_MIN_CHARGE_CENTS. Catch OverblastError with status === 402 to surface this.
  • goal is the system prompt the agent runs with. taskInstructions adds free-form "how to do it" guidance separate from the goal.

todos — workspace + per-conversation tasks

| Method | Endpoint | |---|---| | todos.list(computerId, opts) | GET /todos | | todos.create(computerId, opts) | POST /todos | | todos.update(computerId, todoId, patch) | PATCH /todos/:id | | todos.delete(computerId, todoId) | DELETE /todos/:id | | todos.recordPayment(computerId, todoId, { deltaAmount, currency, note?, source? }) | POST /todos/:id/payments |

todos.list defaults to active only (status: 'open'). Useful filters:

// All workspace open todos
await ob.todos.list(cid);

// Including archived/completed
await ob.todos.list(cid, { status: 'all' });

// Open todos linked to a specific conversation
await ob.todos.list(cid, { conversationId });

// All todos (incl. archived) for a contact across threads
await ob.todos.list(cid, { contactId, status: 'all' });

contacts — directory + per-contact memory

| Method | Endpoint | |---|---| | contacts.list(profileSetId, { limit?, page?, q? }) | GET /z/:psid/contacts | | contacts.memory(profileSetId, contactId) | GET /z/:psid/contacts/:cid/memory |

contacts.memory returns { content: string } — a markdown document the auto-reply agent maintains about the contact (preferences, prior asks, etc.).

context — bundled conversation context

const ctx = await ob.context.forConversation({
  computerId,
  conversationId,
  contactId,           // optional — needed for memory + cross-thread todos
  profileSetId,        // optional — needed for memory + recent messages
  kind: 'social',      // 'social' | 'webchat' | 'call' | 'email'
  includeArchived: false,
});
// → { conversationId, contactId, memory, todos, recentMessages?, recentCalls? }

Convenience wrapper that parallel-fetches contact memory + active todos + the most recent messages or calls. Use this to give an LLM a single payload to reason about a thread.

webhooks — real-time event push

| Method | Endpoint | |---|---| | webhooks.list(computerId) | GET /webhooks/computers/:cid | | webhooks.create(computerId, { eventType, url }) | POST /webhooks/computers/:cid | | webhooks.delete(computerId, webhookId) | DELETE /webhooks/computers/:cid/:id |

Supported event types:

| Event | When it fires | Key payload fields | |---|---|---| | message.received | Inbound DM, webchat message, or email | conversationId, platform, content, contactId, contactName | | comment.received | New comment on a published post | postId, commentId, commentText, authorName | | dm.sent | Outbound DM completes upstream | conversationId, response (raw upstream body) | | post.published | Scheduled post publishes | postId, platforms, content | | call.started / call.ended | Call lifecycle | callId, direction, phoneE164, summary?, disposition? | | todo.{created,updated,deleted} | Todo lifecycle | todoId, title, status | | task_template.{created,updated,deleted} | Template CRUD | templateId, fields |

Use eventType: '*' to subscribe to everything.

The worker signs payloads with the webhook_secret returned at creation time; verify by HMAC-SHA256 over the raw body before trusting the event.

posts / dm / profileSets / addons / apiKeys

The original surface from version 0.1.0 is preserved unchanged:

ob.profileSets.{ list, get, create, update, delete, connectAccount, disconnectAccount }
ob.posts.{ create, raw }
ob.dm.send                    // legacy one-shot DM (prefer conversations.sendDm)
ob.addons.{ list, get, create, cancel }
ob.apiKeys.{ list, create, revoke }
ob.passthrough.call           // raw social-API passthrough by computer id

CLI reference

Every library method has a CLI command. Run overblast --help for the authoritative list. Highlights:

# Conversations & messages
overblast conv list <profileSetId>
overblast conv messages <profileSetId> <convId> --limit 100
overblast conv send <profileSetId> <convId> "Got it — see you Tuesday."

# Webchat
overblast webchat reply <computerId> webchat_abc123 "We open at 9am."
overblast webchat token <computerId>

# Email
overblast email quota --computer <cid>
overblast email send <cid> [email protected] "Quote follow-up" "Hi Jane…" --domain 0-0.chat
overblast email reply <threadId> "Quick clarification on item 2…"

# Calls
overblast call <cid> +15551234567 "Confirm Tuesday's 3pm" --from +15557654321
overblast call list --computer <cid> --status completed
overblast call recording <callId>
overblast call transcript <callId>

# Todos
overblast todos list <cid>                                  # active only
overblast todos list <cid> --status all                     # incl. archived
overblast todos list <cid> --conversation <convId>          # per-conversation
overblast todos create <cid> --title "Send invoice" --conversation <convId>

# Conversation context (memory + todos + recent activity)
overblast context <cid> <convId> --kind social --profile-set <psid> --contact <contactId>

# Webhooks
overblast webhook list <cid>
overblast webhook create <cid> --event message.received --url https://app.example.com/in
overblast webhook delete <cid> <webhookId>

Error handling

Every method throws OverblastError on non-2xx:

catch (e) {
  if (e instanceof OverblastError) {
    e.status   // HTTP status
    e.message  // server-provided "error" string
    e.body     // full parsed response body (for codes/conflicts/etc.)
  }
}

Common cases worth special-casing:

| Status | Meaning | Typical body | |---|---|---| | 400 | Bad input (e.g. missing computerId, malformed E.164) | { error } | | 401 | Bad / missing API key | { error } | | 402 | Out of credits (calls + media gen) | { error, balanceCents, minRequiredCents } | | 403 | Subscription not active for the workspace | { error } | | 422 | Destination blocked / too expensive (calls) | { error, reason, twilioUsdPerMin } | | 429 | Daily email limit exceeded | { error, threadId, ticket } | | 503 | Backend not configured | { error } |


Wiring it into Claude Code (or any AI agent)

The natural recipe for an agent that needs to talk to external people:

  1. Subscribe to message.received (and call.ended if calling) via webhooks.create. Verify the signature, hand the payload to the agent.
  2. Read context with context.forConversation(...) so the agent has contact memory + open todos + recent messages.
  3. Reply through the right channel:
    • conversations.sendDm for social DMs
    • webchat.reply for website chat
    • email.reply (or email.createThread to start one)
    • calls.create to place a call
  4. Track follow-up with todos.create({ ..., conversationId }) so the work survives across conversations.

A minimal Node webhook receiver:

import { Overblast } from 'overblast';
import express from 'express';

const ob = new Overblast({ apiKey: process.env.OVERBLAST_API_KEY! });
const app = express();

app.post('/inbound', express.json(), async (req, res) => {
  const { event, payload } = req.body;
  if (event !== 'message.received') return res.json({ ok: true });

  const { conversationId, platform, content, contactId, contactName } = payload;

  const ctx = await ob.context.forConversation({
    computerId: payload.computerId,
    conversationId,
    contactId,
    profileSetId: payload.profileSetId,
    kind: platform === 'website' ? 'webchat' : 'social',
  });

  const reply = await yourAgent({ ctx, incoming: content, contactName });

  if (platform === 'website') {
    await ob.webchat.reply(payload.computerId, { conversationId, content: reply });
  } else {
    await ob.conversations.sendDm(payload.profileSetId, conversationId, { text: reply });
  }
  res.json({ ok: true });
});

app.listen(8080);

Claude Code skill

The package ships a self-contained skill at skill/SKILL.md. Install it into your Claude Code config so the agent picks the right tool for the task:

overblast install-skill                  # → ~/.claude/skills/overblast/SKILL.md
overblast install-skill --project        # → ./.claude/skills/overblast/SKILL.md
overblast install-skill --dest <path>    # → <path>/overblast/SKILL.md
overblast install-skill --name custom-name   # rename the skill folder
overblast install-skill --force          # overwrite existing

The skill file teaches Claude when to reach for the SDK/CLI, lists the decision matrix (which method handles which conversational channel), and encodes the platform's hard rules (E.164 only, no PII in prompts, etc.).

If you publish a derivative package, you can also vendor skill/SKILL.md directly into your repo — it has no runtime dependencies.

Building from source

cd packages/overblast
npm install
npm run build       # tsup → dist/{index,cli}.{js,d.ts}
npm run dev         # watch mode
npm run typecheck   # tsc --noEmit

The package ships ESM only. The compiled CLI is dist/cli.js and the bin entry overblast points at it.

Testing

Tests hit the real Overblast backend — no mocks. A flag prevents real side-effecting operations (placing actual calls, sending real emails, creating webhooks) from running unless you opt in.

# Read-only suite — never sends a real message, places a real call, etc.
OVERBLAST_API_KEY=ob_test_... npm test

# Full suite — opts into side-effecting tests. Each side-effecting op is
# individually gated on the env vars it needs.
OVERBLAST_API_KEY=ob_test_... \
  OVERBLAST_TEST_ALLOW_SIDE_EFFECTS=1 \
  OVERBLAST_TEST_FROM_PHONE=+15551110000 \
  OVERBLAST_TEST_TO_PHONE=+15551112222 \
  [email protected] \
  OVERBLAST_TEST_WEBHOOK_URL=https://webhook.site/your-uuid \
  npm test

Without OVERBLAST_API_KEY, the suite skips itself cleanly so CI without secrets stays green.

Recognized test env vars:

| Variable | Effect | |---|---| | OVERBLAST_API_KEY | Required to run any test. | | OVERBLAST_BASE_URL | Override base URL (default: production). | | OVERBLAST_TEST_COMPUTER_ID | Workspace under test (auto-detected if omitted). | | OVERBLAST_TEST_PROFILE_SET_ID | Profile set used by conversation/contact tests (auto-detected if omitted). | | OVERBLAST_TEST_ALLOW_SIDE_EFFECTS=1 | Master switch for write tests. Default OFF. | | OVERBLAST_TEST_FROM_PHONE / OVERBLAST_TEST_TO_PHONE | Caller-id + destination for the call test. | | OVERBLAST_TEST_TO_EMAIL / OVERBLAST_TEST_DOMAIN | Destination + agent domain for the email test. | | OVERBLAST_TEST_WEBHOOK_URL | HTTPS endpoint for the webhook round-trip test. |

CI

.github/workflows/overblast.yml runs build + typecheck on every push and PR (no creds needed), and the read-only test suite when the OVERBLAST_API_KEY secret is configured. Side-effecting tests do not run in CI — they require an explicit OVERBLAST_TEST_ALLOW_SIDE_EFFECTS=1 which the workflow does not set.

License

MIT.