@voltade/envoy-sdk
v1.5.0
Published
A comprehensive TypeScript SDK for the Envoy API with built-in error handling and resource-based architecture
Downloads
1,269
Readme
Envoy SDK
A comprehensive TypeScript SDK for the Envoy API with built-in error handling and resource-based architecture.
Installation
npm install @voltade/envoy-sdkQuick Start
import { EnvoyClient } from "@voltade/envoy-sdk";
const client = new EnvoyClient({
apiKey: "your-api-key",
accountId: "your-account-id",
baseUrl: "https://envoy-crm.voltade.com", // optional
});
// Send a message
const message = await client.conversations.createMessage(123, {
content: "Hello, how can I help you?",
message_type: "outgoing",
private: false,
});
// Escalate to human
const result = await client.conversations.escalateToHuman(123);Features
- Type-safe: Full TypeScript support with comprehensive type definitions
- Resource-based: Organized API methods by resource (conversations, contacts, companies, etc.)
- Error handling: Structured error types for different API failures
- Zod schemas: Runtime validation with exported schemas
- Webhook support: Parse and validate incoming webhook events
Configuration
const client = new EnvoyClient({
apiKey: string; // Required: Your Envoy API key
accountId: string; // Required: Your Envoy account ID
baseUrl?: string; // Optional: Base URL (defaults to https://envoy-crm.voltade.com)
timeout?: number; // Optional: Request timeout in ms (defaults to 30000)
});API Reference
Conversations
createMessage(conversationId, params)
Create and send a message to a conversation. Supports text messages, WhatsApp templates, and file attachments.
// Simple text message
const message = await client.conversations.createMessage(123, {
content: "Hello, how can I help you?",
message_type: "outgoing",
private: false,
});
// WhatsApp template message
const templateMessage = await client.conversations.createMessage(123, {
content: "Template message",
template_params: {
name: "order_confirmation",
category: "MARKETING",
language: "en",
processed_params: {
body: { "1": "121212" },
header: {
media_url: "https://example.com/image.jpg",
media_type: "image",
},
},
},
});
// Message with file attachments
const file = new File([blob], "document.pdf", { type: "application/pdf" });
const messageWithAttachment = await client.conversations.createMessage(123, {
content: "Here is your document",
message_type: "outgoing",
file_attachments: [file],
});escalateToHuman(conversationId)
Escalate a conversation to a human agent.
const result = await client.conversations.escalateToHuman(123);
if (result.success) {
console.log(`Escalated to ${result.escalation_type}`);
if (result.agent) {
console.log(`Agent: ${result.agent.name}`);
}
}get(conversationId)
Get a conversation by ID.
const conversation = await client.conversations.get(123);
console.log(conversation.status); // 'open' | 'resolved' | 'pending' | 'snoozed'getMessages(conversationId)
Get all messages for a conversation.
const response = await client.conversations.getMessages(123);
console.log(response.payload); // Array of messages
console.log(response.meta); // Metadata including labels, assigneeContacts
create(params)
Create a new contact.
const contact = await client.contacts.create({
inbox_id: 1,
name: "John Doe",
email: "[email protected]",
phone_number: "+1234567890",
custom_attributes: { plan: "enterprise" },
});update(contactId, params)
Update an existing contact.
const contact = await client.contacts.update(123, {
name: "Jane Doe",
email: "[email protected]",
custom_attributes: { plan: "pro" },
});get(contactId)
Get a contact by ID.
const contact = await client.contacts.get(123);
console.log(contact.name, contact.email);delete(contactId)
Delete a contact.
await client.contacts.delete(123);list(params?)
List all contacts with pagination.
const response = await client.contacts.list({ page: 1 });
console.log(response.payload); // Array of contacts
console.log(response.meta); // Pagination metadatasearch(params)
Search contacts by name, identifier, email, or phone number.
const response = await client.contacts.search({
q: "[email protected]",
page: 1,
});
console.log(response.payload);Companies
list(params?)
List all companies with pagination.
const companies = await client.companies.list();
// With pagination
const companies = await client.companies.list({ page: 2, per_page: 50 });create(params)
Create a new company.
const company = await client.companies.create({
name: "Acme Corp",
});get(companyId)
Get a company by ID.
const company = await client.companies.get(456);update(companyId, params)
Update an existing company.
const company = await client.companies.update(456, {
name: "Acme Corp Updated",
});search(query, params?)
Search companies by name.
const response = await client.companies.search("Acme");
// With pagination
const response = await client.companies.search("Acme", {
page: 2,
per_page: 50,
});
console.log(response.payload); // Array of matching companies
console.log(response.meta); // { count, current_page }delete(companyId)
Delete a company.
await client.companies.delete(456);Company Members
Manage contacts within a company via client.companies.members.
list(companyId)
List all members (contacts) of a company.
const members = await client.companies.members.list(456);add(companyId, params)
Add contacts to a company.
const members = await client.companies.members.add(456, {
contact_ids: [101, 102, 103],
});remove(companyId, params)
Remove contacts from a company.
await client.companies.members.remove(456, {
contact_ids: [101, 102],
});Inboxes
searchPortals(inboxId, params)
Search the knowledge base portals for articles.
const articles = await client.inboxes.searchPortals(1, {
queries: ["shipping", "policy"],
});
articles.forEach((article) => {
console.log(article.title, article.content);
});uploadWhatsappMedia(inboxId, params)
Upload media file for WhatsApp messages.
// Upload an image
const file = new File([imageBlob], "photo.jpg", { type: "image/jpeg" });
const result = await client.inboxes.uploadWhatsappMedia(123, {
file: file,
type: "image/jpeg",
filename: "photo.jpg",
for_template: false,
});
console.log("Media ID:", result.media_id);
// Upload a document for template
const docFile = new File([pdfBlob], "invoice.pdf", { type: "application/pdf" });
const docResult = await client.inboxes.uploadWhatsappMedia(123, {
file: docFile,
type: "application/pdf",
filename: "invoice.pdf",
for_template: true,
});Orders
list(params?)
List all orders with pagination and filtering.
// List with default pagination
const response = await client.orders.list();
console.log(response.data); // Array of orders
console.log(response.meta); // Pagination metadata
// With date filtering
const response = await client.orders.list({
page: 1,
per_page: 50,
since: "2024-01-01",
until: "2024-12-31",
sort: "-created_at",
});
// With advanced filtering
const response = await client.orders.list({
payload: [{ field: "financial_status", operator: "eq", value: "paid" }],
});upsert(params)
Create or update an order based on source and source_id. If an order with the same source and source_id exists, it will be updated.
const result = await client.orders.upsert({
name: "ORD-12345",
company_id: 101,
total_amount: 150,
currency_code: "USD",
financial_status: "paid",
fulfillment_status: "fulfilled",
source: "shopify",
source_id: "789456123",
order_url: "https://mystore.myshopify.com/admin/orders/789456123",
notes: "Customer requested gift wrapping",
metadata: {
line_items: [
{
part_number: "SKU-001",
quantity: 2,
description: "Widget",
line_total: 75,
},
],
},
});
console.log(result.payload); // The created/updated orderWebhooks
Parse and validate incoming webhook events using the webhookEvent utility.
import { webhookEvent } from "@voltade/envoy-sdk";
// In your webhook handler
app.post("/webhook", (req, res) => {
// Throws ZodError if invalid
const event = webhookEvent.parse(req.body);
if (event.event === "message_created") {
console.log("New message:", event.content);
console.log("Conversation:", event.conversation.id);
console.log("Sender:", event.sender.name);
}
res.sendStatus(200);
});
// Or use safeParse for graceful handling
const event = webhookEvent.safeParse(req.body);
if (event) {
// Handle valid event
} else {
// Invalid payload
}Supported webhook events:
message_created- New message in a conversationmessage_updated- Message was updated
Error Handling
The SDK provides structured error types:
import {
EnvoyError,
AuthenticationError,
BadRequestError,
NotFoundError,
RateLimitError,
ServerError,
NetworkError,
ValidationError,
} from "@voltade/envoy-sdk";
try {
await client.conversations.createMessage(123, { content: "Hello" });
} catch (error) {
if (error instanceof AuthenticationError) {
console.error("Invalid API key");
} else if (error instanceof NotFoundError) {
console.error("Conversation not found");
} else if (error instanceof RateLimitError) {
console.error("Rate limit exceeded, retry after:", error.retryAfter);
} else if (error instanceof BadRequestError) {
console.error("Bad request:", error.response);
} else if (error instanceof ValidationError) {
console.error("Validation failed:", error.errors);
} else if (error instanceof ServerError) {
console.error("Server error:", error.statusCode);
} else if (error instanceof NetworkError) {
console.error("Network error:", error.originalError);
}
}Types
All TypeScript types are exported:
import type {
// Conversations
Message,
Conversation,
ConversationStatus,
CreateMessageParams,
EscalationResponse,
EscalationType,
MessageType,
ContentType,
MessagesResponse,
MessagesResponseMeta,
TemplateParams,
Agent,
Assignee,
Team,
Priority,
Contact,
ContactInbox,
ConversationMeta,
// Contacts
ContactCreateParams,
ContactUpdateParams,
ListContactsParams,
ListContactsResponse,
SearchContactsParams,
// Companies
Company,
CreateCompanyParams,
CreateCompanyResponse,
GetCompanyResponse,
ListCompaniesParams,
ListCompaniesResponse,
UpdateCompanyParams,
UpdateCompanyResponse,
SearchCompaniesResponse,
// Company Members
AddCompanyMembersParams,
AddCompanyMembersResponse,
ListCompanyMembersResponse,
RemoveCompanyMembersParams,
// Inboxes
Article,
SearchParams,
SearchResponse,
UploadWhatsappMediaParams,
UploadWhatsappMediaResponse,
// Orders
Order,
OrdersMeta,
ListOrdersParams,
ListOrdersResponse,
UpsertOrderParams,
UpsertOrderRequest,
UpsertOrderResponse,
UpsertOrderResponsePayload,
// Webhooks
WebhookEvent,
MessageCreatedEvent,
MessageUpdatedEvent,
WebhookConversation,
WebhookMessage,
WebhookSender,
// Client
EnvoyClientConfig,
} from "@voltade/envoy-sdk";Zod Schemas
The SDK exposes Zod schemas for runtime validation. All types are derived from these schemas using z.infer:
import {
// Conversations
MessageSchema,
ConversationSchema,
ConversationStatusSchema,
CreateMessageParamsSchema,
EscalationResponseSchema,
EscalationTypeSchema,
MessageTypeSchema,
ContentTypeSchema,
MessagesResponseSchema,
MessagesResponseMetaSchema,
TemplateParamsSchema,
AgentSchema,
AssigneeSchema,
TeamSchema,
PrioritySchema,
ContactSchema,
ContactInboxSchema,
ConversationMetaSchema,
// Contacts
ContactCreateParamsSchema,
ContactUpdateParamsSchema,
ListContactsParamsSchema,
ListContactsResponseSchema,
SearchContactsParamsSchema,
// Companies
CompanySchema,
CreateCompanyParamsSchema,
CreateCompanyResponseSchema,
GetCompanyResponseSchema,
ListCompaniesParamsSchema,
ListCompaniesResponseSchema,
UpdateCompanyParamsSchema,
UpdateCompanyResponseSchema,
SearchCompaniesResponseSchema,
// Company Members
AddCompanyMembersParamsSchema,
AddCompanyMembersResponseSchema,
ListCompanyMembersResponseSchema,
RemoveCompanyMembersParamsSchema,
// Inboxes
ArticleSchema,
SearchParamsSchema,
SearchResponseSchema,
UploadWhatsappMediaParamsSchema,
UploadWhatsappMediaResponseSchema,
// Orders
OrderSchema,
OrdersMetaSchema,
ListOrdersParamsSchema,
ListOrdersResponseSchema,
UpsertOrderParamsSchema,
UpsertOrderRequestSchema,
UpsertOrderResponseSchema,
UpsertOrderResponsePayloadSchema,
// Webhooks
WebhookEventSchema,
MessageCreatedEventSchema,
MessageUpdatedEventSchema,
WebhookConversationSchema,
WebhookMessageSchema,
WebhookSenderSchema,
} from "@voltade/envoy-sdk";
// Validate data at runtime
const validatedMessage = MessageSchema.parse(messageData);
// Validate user input
const validatedParams = CreateMessageParamsSchema.parse(userInput);
await client.conversations.createMessage(123, validatedParams);Development
# Install dependencies
npm install
# Build the SDK
npm run build
# Lint
npm run lint
# Clean build artifacts
npm run cleanLicense
MIT
