Integrations

Connect your users' third-party apps with the Unified API. Access CRM, storage, communication, and productivity data through a single consistent interface.

Unified API - The Integrations SDK provides a single interface to work with multiple providers. Your code stays the same whether your user connects HubSpot, Salesforce, or Pipedrive.

Available Categories

CRM

HubSpot, Salesforce, Pipedrive

Contacts, Companies, Deals, Notes

Storage

Google Drive, Dropbox, OneDrive

Files, Folders, Upload, Download

Communication

Slack, Discord

Channels, Messages, Users

Productivity

Notion, Google Sheets, Airtable

Documents, Tables, Records

Quick Start

Initialize the SDK and start working with your users' connected accounts:

quick-start.ts
import { Stack0 } from '@stack0/sdk'
const stack0 = new Stack0({
apiKey: process.env.STACK0_API_KEY!
})
// List contacts from a user's connected CRM
const contacts = await stack0.integrations.crm.listContacts('conn_abc123')
// Upload a file to a user's cloud storage
await stack0.integrations.storage.uploadFile('conn_xyz789', {
name: 'report.pdf',
mimeType: 'application/pdf',
data: fileBuffer,
})
// Send a message to a user's Slack
await stack0.integrations.communication.sendMessage('conn_slack123', {
channelId: 'C0123456',
content: 'Hello from your app!',
})

Managing Connections

Connections represent authenticated links between your users and their third-party accounts:

managing-connections.ts
// List all connections for a user
const connections = await stack0.integrations.listConnections()
// Filter by connector
const crmConnections = await stack0.integrations.listConnections({
connectorId: 'hubspot',
status: 'connected',
})
// Get a specific connection
const connection = await stack0.integrations.getConnection('conn_abc123')
console.log(connection.connectorSlug) // 'hubspot'
console.log(connection.status) // 'connected'
// Test if a connection is still valid
const result = await stack0.integrations.testConnection('conn_abc123')
if (!result.success) {
console.log('Connection needs re-authentication:', result.error)
}
// Delete a connection
await stack0.integrations.deleteConnection('conn_abc123')

CRM Operations

Work with contacts, companies, and deals from any CRM:

crm-operations.ts
const connectionId = 'conn_abc123'
// === CONTACTS ===
// List contacts with pagination
const { data: contacts, nextCursor } = await stack0.integrations.crm.listContacts(
connectionId,
{ limit: 50 }
)
// Create a new contact
const newContact = await stack0.integrations.crm.createContact(connectionId, {
firstName: 'John',
lastName: 'Doe',
email: 'john@example.com',
phone: '+1234567890',
})
// Update a contact
await stack0.integrations.crm.updateContact(connectionId, newContact.id, {
title: 'Senior Engineer',
})
// === COMPANIES ===
const { data: companies } = await stack0.integrations.crm.listCompanies(connectionId)
const company = await stack0.integrations.crm.createCompany(connectionId, {
name: 'Acme Corp',
domain: 'acme.com',
industry: 'Technology',
})
// === DEALS ===
const { data: deals } = await stack0.integrations.crm.listDeals(connectionId)
const deal = await stack0.integrations.crm.createDeal(connectionId, {
name: 'Enterprise License',
amount: 50000,
stage: 'proposal',
companyId: company.id,
})

Storage Operations

Upload, download, and manage files in any cloud storage:

storage-operations.ts
const connectionId = 'conn_storage123'
// List files in root folder
const { data: files } = await stack0.integrations.storage.listFiles(connectionId)
// List files in a specific folder
const { data: folderFiles } = await stack0.integrations.storage.listFiles(
connectionId,
'folder_id_123'
)
// Upload a file
const uploadedFile = await stack0.integrations.storage.uploadFile(connectionId, {
name: 'document.pdf',
mimeType: 'application/pdf',
data: fileBuffer, // ArrayBuffer or Uint8Array
folderId: 'folder_id_123', // optional
})
// Download a file
const { data, mimeType, filename } = await stack0.integrations.storage.downloadFile(
connectionId,
'file_id_456'
)
// List folders
const { data: folders } = await stack0.integrations.storage.listFolders(connectionId)
// Create a folder
const folder = await stack0.integrations.storage.createFolder(connectionId, {
name: 'New Folder',
parentId: 'parent_folder_id', // optional
})
// Delete a file
await stack0.integrations.storage.deleteFile(connectionId, 'file_id_456')

Communication Operations

Send messages and interact with channels in Slack or Discord:

communication-operations.ts
const connectionId = 'conn_slack123'
// List available channels
const { data: channels } = await stack0.integrations.communication.listChannels(connectionId)
// Get a specific channel
const channel = await stack0.integrations.communication.getChannel(
connectionId,
'C0123456'
)
// List messages in a channel
const { data: messages } = await stack0.integrations.communication.listMessages(
connectionId,
'C0123456',
{ limit: 20 }
)
// Send a message
const message = await stack0.integrations.communication.sendMessage(connectionId, {
channelId: 'C0123456',
content: 'Hello from Stack0!',
})
// List workspace users
const { data: users } = await stack0.integrations.communication.listUsers(connectionId)

Productivity Operations

Work with documents and tables in Notion, Google Sheets, or Airtable:

productivity-operations.ts
const connectionId = 'conn_notion123'
// === DOCUMENTS (Notion pages, etc.) ===
const { data: documents } = await stack0.integrations.productivity.listDocuments(connectionId)
const doc = await stack0.integrations.productivity.createDocument(connectionId, {
title: 'Meeting Notes',
content: '## Agenda\n- Item 1\n- Item 2',
})
await stack0.integrations.productivity.updateDocument(connectionId, doc.id, {
content: '## Updated Agenda\n- New item',
})
// === TABLES (Sheets, Airtable bases, Notion databases) ===
const { data: tables } = await stack0.integrations.productivity.listTables(connectionId)
// List rows in a table
const { data: rows } = await stack0.integrations.productivity.listTableRows(
connectionId,
'table_id'
)
// Add a row
const row = await stack0.integrations.productivity.createTableRow(
connectionId,
'table_id',
{
fields: {
Name: 'John Doe',
Email: 'john@example.com',
Status: 'Active',
},
}
)
// Update a row
await stack0.integrations.productivity.updateTableRow(
connectionId,
'table_id',
row.id,
{
fields: { Status: 'Completed' },
}
)

Passthrough Requests

For advanced use cases, make raw API calls to the underlying provider:

passthrough.ts
// Make a raw request to the provider's API
const response = await stack0.integrations.passthrough({
connectionId: 'conn_abc123',
method: 'GET',
path: '/crm/v3/objects/custom_objects',
query: { limit: '10' },
})
// POST with body
const createResponse = await stack0.integrations.passthrough({
connectionId: 'conn_abc123',
method: 'POST',
path: '/crm/v3/objects/custom_objects',
body: {
properties: {
custom_field: 'value',
},
},
})

Error Handling

Handle integration-specific errors gracefully:

error-handling.ts
import { Stack0Error } from '@stack0/sdk'
try {
const contacts = await stack0.integrations.crm.listContacts('conn_abc123')
} catch (error) {
if (error instanceof Stack0Error) {
switch (error.code) {
case 'connection_expired':
// Token expired, prompt user to re-authenticate
console.log('Connection expired, re-auth required')
break
case 'rate_limited':
// Provider rate limit hit
console.log('Rate limited, retry after:', error.retryAfter)
break
case 'provider_error':
// Error from the underlying provider
console.log('Provider error:', error.providerMessage)
break
default:
console.log('Integration error:', error.message)
}
}
}

Pagination

All list operations support cursor-based pagination:

pagination.ts
// Fetch all contacts with pagination
let allContacts: Contact[] = []
let cursor: string | undefined
do {
const { data, nextCursor } = await stack0.integrations.crm.listContacts(
'conn_abc123',
{ limit: 100, cursor }
)
allContacts = [...allContacts, ...data]
cursor = nextCursor
} while (cursor)
console.log('Total contacts:', allContacts.length)