apideck-node
npx skills add https://github.com/apideck-libraries/api-skills --skill apideck-node
Agent 安装分布
Skill 文档
Apideck TypeScript SDK Skill
Overview
The Apideck Unified API provides a single integration layer to connect with 200+ third-party services across accounting, CRM, HRIS, file storage, ATS, e-commerce, and more. The official TypeScript SDK (@apideck/unify) provides typed clients for all unified APIs.
Key capabilities:
- Accounting – Invoices, bills, payments, ledger accounts, journal entries, tax rates, balance sheets, P&L
- CRM – Contacts, companies, leads, opportunities, activities, pipelines, notes
- HRIS – Employees, departments, payrolls, time-off requests, schedules
- File Storage – Files, folders, drives, shared links, upload sessions
- ATS – Jobs, applicants, applications
- Vault – Connection management, OAuth flows, custom field mapping
- Vault JS – Embeddable modal UI for users to authorize connectors and manage settings
- Webhook – Event subscriptions and real-time notifications
Installation
npm add @apideck/unify
Requires Node.js 18+. The SDK is fully typed with TypeScript definitions.
IMPORTANT RULES
- ALWAYS use the
@apideck/unifySDK. DO NOT make rawfetch/axioscalls to the Apideck API. - ALWAYS pass
apiKey,appId, andconsumerIdwhen initializing the client. These are required for all API calls. - ALWAYS set the
APIDECK_API_KEYenvironment variable rather than hardcoding API keys. - USE
serviceIdto specify which downstream connector to use (e.g.,"salesforce","quickbooks","xero"). If a consumer has multiple connections for an API,serviceIdis required. - USE cursor-based pagination with
for await...offor iterating large result sets. DO NOT implement manual pagination. - USE the
filterparameter to narrow results server-side. DO NOT fetch all records and filter client-side. - USE the
fieldsparameter to request only the columns you need. This reduces response size and improves performance. - ALWAYS handle errors with try/catch. The SDK throws typed errors for different HTTP status codes.
- DO NOT store Apideck API keys, App IDs, or Consumer IDs in source code. Use environment variables or a secrets manager.
Quick Start
import { Apideck } from "@apideck/unify";
const apideck = new Apideck({
apiKey: process.env["APIDECK_API_KEY"] ?? "",
appId: "your-app-id",
consumerId: "your-consumer-id",
});
// List CRM contacts
const { data } = await apideck.crm.contacts.list({
limit: 20,
filter: { email: "john@example.com" },
});
for (const contact of data) {
console.log(contact.name, contact.emails);
}
SDK Patterns
Client Setup
import { Apideck } from "@apideck/unify";
const apideck = new Apideck({
apiKey: process.env["APIDECK_API_KEY"] ?? "",
appId: "your-app-id",
consumerId: "your-consumer-id",
});
The consumerId identifies the end-user whose connections are being used. In multi-tenant apps, set this per-request or per-user session.
CRUD Operations
All resources follow the same pattern: apideck.{api}.{resource}.{operation}().
// LIST - retrieve multiple records
const { data } = await apideck.crm.contacts.list({
serviceId: "salesforce",
limit: 20,
filter: { email: "john@example.com" },
sort: { by: "updated_at", direction: "desc" },
fields: "id,name,email,phone_numbers",
});
// CREATE - create a new record
const { data: created } = await apideck.crm.contacts.create({
serviceId: "salesforce",
contact: {
first_name: "John",
last_name: "Doe",
emails: [{ email: "john@example.com", type: "primary" }],
phone_numbers: [{ number: "+1234567890", type: "mobile" }],
},
});
console.log(created.id); // "contact_abc123"
// GET - retrieve a single record
const { data: contact } = await apideck.crm.contacts.get({
id: "contact_abc123",
serviceId: "salesforce",
});
// UPDATE - modify an existing record
const { data: updated } = await apideck.crm.contacts.update({
id: "contact_abc123",
serviceId: "salesforce",
contact: { first_name: "Jane" },
});
// DELETE - remove a record
await apideck.crm.contacts.delete({
id: "contact_abc123",
serviceId: "salesforce",
});
Pagination
Use async iteration to automatically handle cursor-based pagination:
const result = await apideck.accounting.invoices.list({
serviceId: "quickbooks",
limit: 50,
});
// Automatically fetches next pages
for await (const page of result) {
for (const invoice of page.data) {
console.log(invoice.number, invoice.total);
}
}
Or handle pagination manually:
let cursor: string | undefined;
do {
const { data, meta } = await apideck.accounting.invoices.list({
serviceId: "quickbooks",
limit: 50,
cursor,
});
for (const invoice of data) {
console.log(invoice.number);
}
cursor = meta?.cursors?.next ?? undefined;
} while (cursor);
Error Handling
import { Apideck } from "@apideck/unify";
import * as errors from "@apideck/unify/models/errors";
try {
const { data } = await apideck.crm.contacts.get({ id: "invalid" });
} catch (e) {
if (e instanceof errors.BadRequestResponse) {
console.error("Bad request:", e.message);
} else if (e instanceof errors.UnauthorizedResponse) {
console.error("Invalid API key or missing credentials");
} else if (e instanceof errors.NotFoundResponse) {
console.error("Record not found");
} else if (e instanceof errors.PaymentRequiredResponse) {
console.error("API limit reached or payment required");
} else if (e instanceof errors.UnprocessableResponse) {
console.error("Validation error:", e.message);
} else {
throw e;
}
}
Common Parameters
Most list endpoints accept these parameters:
| Parameter | Type | Description |
|---|---|---|
serviceId |
string |
Downstream connector ID (e.g., "quickbooks", "salesforce") |
limit |
number |
Max results per page (1-200, default 20) |
cursor |
string |
Pagination cursor from previous response |
filter |
object |
Resource-specific filter criteria |
sort |
object |
{ by: string, direction: "asc" | "desc" } |
fields |
string |
Comma-separated field names to return |
passThrough |
object |
Pass-through query parameters for the downstream API |
Pass-Through Parameters
When the unified model doesn’t cover a connector-specific field, use passThrough:
const { data } = await apideck.accounting.invoices.list({
serviceId: "quickbooks",
passThrough: {
search: "overdue",
},
});
For creating/updating, use pass_through in the request body to send connector-specific fields:
const { data } = await apideck.crm.contacts.create({
serviceId: "salesforce",
contact: {
first_name: "John",
last_name: "Doe",
pass_through: [
{
service_id: "salesforce",
operation_id: "contactsAdd",
extend_object: { custom_sf_field__c: "value" },
},
],
},
});
API Namespaces
The SDK organizes APIs by namespace. See the reference files for detailed endpoints:
| Namespace | Reference | Resources |
|---|---|---|
apideck.accounting.* |
references/accounting-api.md | invoices, bills, payments, customers, suppliers, ledgerAccounts, journalEntries, taxRates, creditNotes, purchaseOrders, balanceSheet, profitAndLoss, and more |
apideck.crm.* |
references/crm-api.md | contacts, companies, leads, opportunities, activities, notes, pipelines, users |
apideck.hris.* |
references/hris-api.md | employees, companies, departments, payrolls, timeOffRequests |
apideck.fileStorage.* |
references/file-storage-api.md | files, folders, drives, driveGroups, sharedLinks, uploadSessions |
apideck.ats.* |
references/ats-api.md | applicants, applications, jobs |
apideck.vault.* |
references/vault-api.md | connections, connectionSettings, consumers, customMappings, logs, sessions |
apideck.webhook.* |
references/webhook-api.md | webhooks, eventLogs |
Vault JS (Embeddable UI)
Use @apideck/vault-js to embed a pre-built modal that lets your users authorize connectors and manage integration settings. Session creation must happen server-side.
// 1. Server-side: create a session
const { data } = await apideck.vault.sessions.create({
session: {
consumer_metadata: { account_name: "Acme Corp", user_name: "John Doe", email: "john@acme.com" },
redirect_uri: "https://myapp.com/integrations",
settings: { unified_apis: ["accounting", "crm"] },
theme: { vault_name: "My App", primary_color: "#4F46E5" },
},
});
// 2. Client-side: open the modal
import { ApideckVault } from "@apideck/vault-js";
ApideckVault.open({
token: sessionToken,
onConnectionChange: (connection) => console.log("Changed:", connection),
onClose: () => console.log("Closed"),
});
See references/vault-js.md for full configuration options, theming, React integration, and event callbacks.