agentcall
v0.1.1
Published
Node.js SDK for AgentCall — programmable phone numbers for AI agents
Maintainers
Readme
agentcall
Node.js SDK for AgentCall — programmable phone numbers for AI agents.
Provision numbers, send/receive SMS, extract OTP codes, and initiate voice calls from your AI agent or backend service.
Install
npm install agentcallQuick start
import AgentCall from 'agentcall'
const client = new AgentCall('ac_live_xxxxxxxxxxxxx')
// 1. Provision a phone number
const number = await client.numbers.provision({ country: 'US', type: 'local' })
console.log(number.number) // +12125551234
// 2. Send an SMS
await client.sms.send({
from: number.number,
to: '+14155559876',
body: 'Your verification code will arrive shortly.',
})
// 3. Wait for an OTP (polls inbox automatically)
const otp = await client.sms.waitForOTP(number.id, { timeout: 60000 })
console.log(otp) // "482913"Authentication
Get your API key from the AgentCall dashboard. Keys are prefixed with ac_live_.
const client = new AgentCall('ac_live_xxxxxxxxxxxxx')Configuration
const client = new AgentCall('ac_live_xxx', {
baseUrl: 'https://api.agentcall.co', // default
timeout: 30000, // request timeout in ms, default 30s
})API Reference
client.numbers
numbers.provision(options?)
Provision a new phone number.
const number = await client.numbers.provision({
country: 'US', // optional, default 'US'
type: 'local', // 'local' | 'tollfree' | 'mobile' | 'sim'
label: 'Signup flow', // optional human-readable label
})Returns: PhoneNumber
{
id: string
number: string // E.164 format, e.g. '+12125551234'
country: string
type: string
label: string | null
status: string // 'active' | 'released'
monthlyRate: number
provisionedAt: string // ISO 8601
}numbers.list(params?)
List all provisioned numbers.
const result = await client.numbers.list({
limit: 20, // optional, default 20
cursor: undefined, // optional, for pagination
country: 'US', // optional filter
type: 'local', // optional filter
})
// result.data — PhoneNumber[]
// result.hasMore — boolean
// result.nextCursor — string | nullnumbers.get(numberId)
Get a single phone number by ID.
const number = await client.numbers.get('num_abc123')numbers.release(numberId)
Release (deactivate) a phone number. Stops billing. Irreversible.
await client.numbers.release('num_abc123')client.sms
sms.send(options)
Send an SMS from a provisioned number.
const message = await client.sms.send({
from: '+12125551234', // your provisioned number (E.164)
to: '+14155559876', // destination (E.164)
body: 'Hello!', // max 1600 characters
})Returns: Message
{
id: string
direction: string // 'inbound' | 'outbound'
from: string
to: string
body: string
otp: string | null // extracted OTP code, if detected
status: string // 'queued' | 'delivered'
cost: number
receivedAt: string
createdAt: string
}sms.inbox(numberId, options?)
Get inbound messages for a phone number.
const inbox = await client.sms.inbox('num_abc123', {
limit: 20, // optional
cursor: undefined, // optional, for pagination
since: '2025-01-01T00:00:00Z', // optional ISO timestamp
otpOnly: true, // optional, only return messages with OTP codes
})sms.get(messageId)
Get a single message by ID.
const msg = await client.sms.get('msg_xyz789')sms.waitForOTP(numberId, options?)
Poll the inbox until an OTP code arrives. This is the primary method for AI agent verification flows.
const otp = await client.sms.waitForOTP('num_abc123', {
timeout: 60000, // max wait in ms, default 60s
pollInterval: 2000, // poll frequency in ms, default 2s
since: new Date().toISOString(), // only look at new messages
})
if (otp) {
console.log(`Got OTP: ${otp}`)
} else {
console.log('Timed out waiting for OTP')
}Returns: string | null — the OTP code, or null if timeout.
client.calls
calls.initiate(options)
Start an outbound phone call.
const call = await client.calls.initiate({
from: '+12125551234', // your provisioned number (E.164)
to: '+14155559876', // destination (E.164)
webhookUrl: 'https://example.com/call-events', // optional
record: false, // optional, Pro plan only ($0.01/min)
})Returns: Call
{
id: string
direction: string // 'inbound' | 'outbound'
from: string
to: string
status: string // 'queued' | 'ringing' | 'in-progress' | 'completed' | 'failed'
duration: number | null // seconds
record: boolean
recordingUrl: string | null
createdAt: string
}calls.list(params?)
List call history.
const calls = await client.calls.list({ limit: 20 })calls.get(callId)
Get a single call by ID.
const call = await client.calls.get('call_abc123')calls.hangup(callId)
Terminate an active call.
await client.calls.hangup('call_abc123')client.webhooks
webhooks.create(options)
Register a webhook endpoint for real-time events.
const webhook = await client.webhooks.create({
url: 'https://example.com/hooks/agentcall',
events: ['sms.inbound', 'sms.otp', 'call.status'],
})
console.log(webhook.secret) // signing secret, shown onceValid events: sms.inbound, sms.otp, call.inbound, call.ringing, call.status, call.recording, number.released
webhooks.list()
List all active webhooks.
const hooks = await client.webhooks.list()webhooks.delete(webhookId)
Deactivate a webhook.
await client.webhooks.delete('wh_abc123')client.usage
usage.get(period?)
Get usage and cost breakdown for a billing period.
const usage = await client.usage.get('2025-06') // YYYY-MM, defaults to current month
console.log(usage.breakdown.sms.outbound) // number of outbound SMS
console.log(usage.total) // total cost
console.log(usage.currency) // 'usd'Returns: UsageData
{
period: string
breakdown: {
numbers: { count: number; cost: number }
sms: { inbound: number; outbound: number; cost: number }
calls: { minutes: number; cost: number }
recording: { minutes: number; cost: number }
}
total: number
currency: string
}Error handling
All API errors throw AgentCallError with a code and statusCode:
import AgentCall from 'agentcall'
try {
await client.numbers.provision({ type: 'sim' })
} catch (err) {
if (err instanceof Error && 'statusCode' in err) {
console.error(err.message) // "SIM numbers require Pro plan"
console.error(err.code) // "plan_limit"
console.error(err.statusCode) // 403
}
}Common error codes:
| Code | Status | Meaning |
|------|--------|---------|
| unauthorized | 401 | Invalid or missing API key |
| plan_limit | 403 | Feature or quota requires upgrade |
| not_found | 404 | Resource doesn't exist |
| validation_error | 422 | Invalid request body |
| rate_limited | 429 | Too many requests (auto-retried by SDK) |
The SDK automatically retries rate-limited (429) and server error (5xx) responses up to 3 times with exponential backoff.
License
MIT
