Webex
TypeScript SDK reference for Cisco Webex — client, credential management, and types.
Installation
npm install agent-messengerimport { WebexClient, WebexCredentialManager, WebexError } from 'agent-messenger/webex'WebexClient
The main client for interacting with the Webex REST API programmatically. All API methods include automatic rate-limit handling with per-bucket tracking and exponential backoff on server errors.
OAuth tokens auto-refresh via the stored refresh token. Bot tokens never expire. PATs expire in 12 hours.
import { WebexClient } from 'agent-messenger/webex'
const client = await new WebexClient().login({ token })Or use automatic credential extraction — credentials are loaded from stored OAuth/bot tokens, no manual token needed:
import { WebexClient } from 'agent-messenger/webex'
const client = await new WebexClient().login()Authentication
// Verify credentials and get identity
const me = await client.testAuth()
// → WebexPerson { id, displayName, emails, orgId, type }Spaces
// List all spaces (default limit: 50)
const spaces = await client.listSpaces()
const grouped = await client.listSpaces({ type: 'group', max: 20 })
// → WebexSpace[]
// Get a specific space by ID
const space = await client.getSpace(spaceId)
// → WebexSpace { id, title, type, isLocked, lastActivity, created, creatorId }Messages
// Send a message to a space
const msg = await client.sendMessage(roomId, 'Hello world')
// → WebexMessage { id, roomId, roomType, text, personId, personEmail, created }
// Send a markdown message
await client.sendMessage(roomId, '**Bold** and _italic_', { markdown: true })
// Send a direct message by email
const dm = await client.sendDirectMessage('alice@example.com', 'Hey!')
await client.sendDirectMessage('alice@example.com', '**Important**', { markdown: true })
// List messages in a space (default limit: 50)
const messages = await client.listMessages(roomId)
const limited = await client.listMessages(roomId, { max: 25 })
// → WebexMessage[]
// Get a single message by ID
const message = await client.getMessage(messageId)
// → WebexMessage
// Edit a message
const updated = await client.editMessage(messageId, roomId, 'Updated text')
await client.editMessage(messageId, roomId, '**Updated**', { markdown: true })
// → WebexMessage
// Delete a message
await client.deleteMessage(messageId)
// Send a typing indicator ("…is typing")
await client.setTyping(roomId)
// Clear the typing indicator
await client.setTyping(roomId, false)Typing indicators are sent over Webex's internal conversation service, which the public REST API does not expose. They require an extracted (browser) or password token — bot and OAuth tokens have no device URL and throw a WebexError. The indicator is ephemeral and auto-expires after a few seconds, so re-send periodically to sustain it.
People
// List people (search by email or display name)
const people = await client.listPeople({ email: 'alice@example.com' })
const byName = await client.listPeople({ displayName: 'Alice', max: 10 })
// → WebexPerson[]Memberships
// List members of a space
const members = await client.listMemberships(roomId)
const limited = await client.listMemberships(roomId, { max: 100 })
// → WebexMembership[]Files
// Upload a file to a space (optionally with a text comment)
const msg = await client.uploadFile(roomId, { content: blob, filename: 'report.pdf' }, { text: 'Latest report' })
// → WebexMessage { id, roomId, files, ... }
// Download a file attachment by content URL or ID
const { data, filename, contentType } = await client.downloadContent(contentUrlOrId)
// → { data: ArrayBuffer, filename: string, contentType: string }WebexCredentialManager
Manages Webex credentials stored at ~/.config/agent-messenger/webex-credentials.json. Files are written with 0o600 permissions. Supports OAuth Device Grant flow, bot tokens, and PATs.
import { WebexCredentialManager } from 'agent-messenger/webex'
const manager = new WebexCredentialManager()
// Custom path: new WebexCredentialManager('/custom/config/dir')// Load config from disk (returns null if file doesn't exist)
const config = await manager.loadConfig()
// → WebexConfig | null
// Save config to disk (atomic write)
await manager.saveConfig(config)
// Get stored access token (auto-refreshes OAuth tokens if expired)
const token = await manager.getToken()
// → string | null
// Refresh an OAuth token manually
const refreshed = await manager.refreshToken(refreshToken, clientId, clientSecret)
// → WebexConfig | null
// Start OAuth Device Grant flow (request device code)
const device = await manager.requestDeviceCode(clientId)
// → { deviceCode, userCode, verificationUri, verificationUriComplete, expiresIn, interval }
// Poll for device token approval
const tokenConfig = await manager.pollDeviceToken(deviceCode, interval, expiresIn, clientId, clientSecret)
// → WebexConfig
// Clear all stored credentials (deletes the file)
await manager.clearCredentials()Types
import type { WebexSpace, WebexMessage, WebexPerson, WebexMembership, WebexConfig } from 'agent-messenger/webex'Zod Schemas
Runtime-validated schemas are also exported for parsing API responses:
import {
WebexSpaceSchema,
WebexMessageSchema,
WebexPersonSchema,
WebexMembershipSchema,
WebexConfigSchema,
} from 'agent-messenger/webex'Examples
Deploy Notifier
Post a deployment message, then update it when done.
import { WebexClient } from 'agent-messenger/webex'
const client = await new WebexClient().login()
// Post initial status
const msg = await client.sendMessage(spaceId, 'Deploying v2.1.0 to production...')
// Stream progress
await client.sendMessage(spaceId, 'Building application...')
await client.sendMessage(spaceId, 'Running tests (142 passed)...')
await client.sendMessage(spaceId, 'Rolling out to 3 regions...')
// Update original message with final status
await client.editMessage(msg.id, spaceId, 'Deployed v2.1.0 to production')Space Monitor
List spaces and pull recent messages from each one.
import { WebexClient } from 'agent-messenger/webex'
const client = await new WebexClient().login()
const spaces = await client.listSpaces({ type: 'group', max: 10 })
for (const space of spaces) {
const messages = await client.listMessages(space.id, { max: 5 })
console.log(`${space.title} (${messages.length} recent messages)`)
for (const msg of messages) {
console.log(` [${msg.personEmail}] ${(msg.text ?? '').slice(0, 80)}`)
}
}Workspace Summary
Build a snapshot-style overview: spaces, members, and latest activity.
import { WebexClient } from 'agent-messenger/webex'
const client = await new WebexClient().login()
const spaces = await client.listSpaces()
console.log(`Total spaces: ${spaces.length}`)
for (const space of spaces.slice(0, 5)) {
const members = await client.listMemberships(space.id)
const messages = await client.listMessages(space.id, { max: 1 })
const latest = messages[0]
console.log(`${space.title} (${members.length} members)`)
if (latest) {
console.log(` Latest: "${(latest.text ?? '').slice(0, 60)}" — ${latest.personEmail}`)
}
}Direct Message Pipeline
Send a DM to multiple people by email.
import { WebexClient } from 'agent-messenger/webex'
const client = await new WebexClient().login()
const recipients = ['alice@example.com', 'bob@example.com', 'carol@example.com']
for (const email of recipients) {
await client.sendDirectMessage(email, 'Reminder: standup in 5 minutes')
// Respect rate limits
await new Promise((r) => setTimeout(r, 200))
}