Skip to content

Latest commit

 

History

History
209 lines (167 loc) · 13.4 KB

File metadata and controls

209 lines (167 loc) · 13.4 KB

assembly-kit

TypeScript SDK for the Assembly platform. ESM-only, Node.js 18+ and Bun.

Quick Start

import { createAssemblyKit, KitMode } from "assembly-kit";

// Local mode (default) — only apiKey required
const kit = createAssemblyKit({ apiKey: "your-key" });

// Local mode with workspaceId — compound key: workspaceId/apiKey
const kit = createAssemblyKit({ apiKey: "your-key", workspaceId: "ws-123" });

// Local mode with token — token parsed, compound key from token payload
const kit = createAssemblyKit({ apiKey: "your-key", token: encryptedToken });

// Marketplace mode — either token or workspaceId required
const kit = createAssemblyKit({
  apiKey: "your-key",
  token: encryptedToken,
  kitMode: KitMode.Marketplace,
});
  • kitMode: "local" (default) → only apiKey required. workspaceId and token are optional.
  • kitMode: "marketplace" → either token or workspaceId must be provided.

createAssemblyKit(options)

Option Type Default Description
apiKey string Required. Assembly API key.
token string Encrypted token. Takes precedence over workspaceId.
workspaceId string Workspace ID. Required when token is not provided.
kitMode KitMode "local" "local" or "marketplace". See Quick Start above.
validateResponses boolean true Validate all API responses through Zod schemas.
baseUrl string https://api.assembly.com Base URL for all API requests.
retryCount number 2 Number of retry attempts for retryable errors.
requestsPerSecond number 20 Maximum requests per second (sliding-window rate limiter).
fetch typeof globalThis.fetch Injectable fetch function for testing.

Resource Namespaces

Access API resources via kit.<namespace>.<method>():

Namespace Methods
workspace retrieve()
me retrieve()
clients list() retrieve() retrieveWithAppVisibility() create() update() delete() listAll()
companies list() retrieve() create() update() delete() addClients() listAll()
internalUsers list() retrieve() update() retrieveNotificationSettings() listAll()
notes list() retrieve() create() update() delete() listAll()
tasks list() retrieve() create() update() delete() listAll()
taskComments list() retrieve() delete() listAll()
taskTemplates list() retrieve() listAll()
invoices list() retrieve() create() listAll()
invoiceTemplates list() listAll()
subscriptions list() retrieve() create() cancel() listAll()
subscriptionTemplates list() listAll()
refunds list() create() listAll()
payments list() listAll()
products list() retrieve() create() listAll()
prices list() retrieve() create() listAll()
contracts retrieve() send()
contractTemplates list() retrieve()
forms list() retrieve() create() listSubmissions() listAllSubmissions() listAll()
formResponses list() create()
files list() retrieve() create() delete() retrieveDownloadUrl() download() updateFolderPermissions() updateRootFolderPermissions() listAll()
fileChannels list() retrieve() create() listAll()
messageChannels list() retrieve() create() listUnread() listAll()
messages list() send() listAll()
events list() retrieve() create() listAll()
notifications list() retrieve() create() delete() markRead() markUnread()
customFields list() create()
customFieldOptions list()
appConnections list() create()
appInstalls list() retrieve() retrieveNotificationSettings() createNotificationSettings() updateNotificationSettings()

Pagination

listAll() auto-paginates and returns Promise<T[]>. For manual pagination use list() and handle nextToken:

const allCompanies = await kit.companies.listAll();
const page = await kit.companies.list({ limit: 100 });
if (page.nextToken) {
  const next = await kit.companies.list({ limit: 100, nextToken: page.nextToken });
}

Typed Custom Fields

createAssemblyKit accepts optional generic parameters that type the customFields shape returned from kit.clients.* and kit.companies.*:

// Single shape applied to both clients and companies
const kit = createAssemblyKit<{ roles: string[] }>({ apiKey, workspaceId });
const client = await kit.clients.retrieve("id");
client.customFields; // { roles: string[] } | null | undefined

// Different shapes per resource
const kit = createAssemblyKit<{ roles: string[] }, { industry: string }>({
  apiKey,
  workspaceId,
});

The generics only narrow types — runtime parsing still uses the loose Record<string, unknown> schema, so unexpected fields won't throw.

Token Utilities

Standalone token decryption (not required for normal SDK usage):

import { AssemblyToken, createToken } from "assembly-kit";

const token = new AssemblyToken({ token: encryptedHex, apiKey });
token.workspaceId; // string
token.clientId; // string | undefined
token.companyId; // string | undefined
token.internalUserId; // string | undefined
token.isClientUser; // boolean
token.isInternalUser; // boolean
token.isProxying; // boolean — internal user previewing as a client (both IDs present)

const client = token.ensureIsClient(); // ClientTokenPayload (throws if not client)
const internal = token.ensureIsInternalUser(); // InternalUserTokenPayload (throws if not internal)

// Encrypt a payload into a token
const encrypted = createToken({
  payload: { workspaceId: "ws-123", clientId: "cl-1", companyId: "co-1" },
  apiKey,
});

Error Handling

All errors extend AssemblyError. Import from assembly-kit:

import {
  AssemblyError, // base class (statusCode, details)
  AssemblyNoTokenError, // 400 — token required but missing
  AssemblyInvalidTokenError, // 401 — token decryption/validation failed
  AssemblyUnauthorizedError, // 401 — API key rejected or identity assertion failed
  AssemblyForbiddenError, // 403 — insufficient permissions
  AssemblyNotFoundError, // 404 — resource not found
  AssemblyValidationError, // 422 — request payload rejected
  AssemblyRateLimitError, // 429 — rate limited (.retryAfter?: number)
  AssemblyServerError, // 500 — server error
  AssemblyResponseParseError, // 500 — Zod validation failed (.zodError)
  AssemblyConnectionError, // 503 — network error
} from "assembly-kit";

try {
  await kit.companies.retrieve(id);
} catch (err) {
  if (err instanceof AssemblyRateLimitError) {
    // err.retryAfter — seconds until retry
  } else if (err instanceof AssemblyError) {
    // err.message, err.statusCode, err.details
  }
}

Schemas

Zod 4 schemas and inferred types for all resources:

import { ClientSchema, CompanySchema, TaskSchema } from "assembly-kit/schemas";
import type { Client, Company, Task } from "assembly-kit/schemas";

// Response schemas (paginated)
import { ClientsResponseSchema } from "assembly-kit/schemas";

// Request schemas
import { ClientCreateRequestSchema } from "assembly-kit/schemas";

Multi-Workspace (React Server Components)

Use React cache() to deduplicate per request:

import { cache } from "react";
import { createAssemblyKit } from "assembly-kit";

export const getAssemblyKit = cache((apiKey: string, workspaceId: string) =>
  createAssemblyKit({ apiKey, workspaceId }),
);

Entry Points

Import path Key exports
assembly-kit createAssemblyKit, AssemblyKit, errors, schemas, token utils
assembly-kit/schemas All Zod schemas and inferred types
assembly-kit/client createAssemblyKit, AssemblyKit, AssemblyKitOptions
assembly-kit/errors All error classes
assembly-kit/token AssemblyToken, createToken
assembly-kit/logger createLogger, createPrettyLogger, logger (requires pino peer dep; createPrettyLogger also needs pino-pretty)
assembly-kit/bridge-ui usePrimaryCta, useSecondaryCta, useActionsMenu (requires react + @assembly-js/app-bridge peer deps)