Skip to content

Repository files navigation

epilot
epilot SDK

CI npm version License

JavaScript/TypeScript SDK for epilot APIs. Full types, tree-shakeable imports, and lazy-loaded OpenAPI specs.

Install

npm i @epilot/sdk axios openapi-client-axios

Quick Start

import { epilot } from '@epilot/sdk'

epilot.authorize(() => '<my-bearer-token>')

const { data: entity } = await epilot.entity.createEntity(
  { slug: 'contact' },
  { first_name: 'John', last_name: 'Doe' },
)

const { data: file } = await epilot.file.getFile({ id: 'file-123' })

const { data: executions } = await epilot.workflow.getExecutions()

API clients are built on openapi-client-axios, which generates fully typed operation methods on top of regular axios instances. All standard axios features (interceptors, defaults, config) work as expected. Each operation is forwarded to a lazy singleton — the spec is loaded and the client initialized on first use, then cached.

Full API documentation: https://docs.epilot.io/api

Packages

Package Description
@epilot/sdk JavaScript/TypeScript SDK for epilot APIs
@epilot/cli CLI for AI agents and automation from the command line
@epilot/app-sdk SDK to build Apps for epilot XRM
@epilot/app-bridge App bridge for communication between epilot apps and the host

API Reference

API Import Docs
epilot.accessToken @epilot/sdk/access-token docs
epilot.address @epilot/sdk/address docs
epilot.addressSuggestions @epilot/sdk/address-suggestions docs
epilot.aiAgents @epilot/sdk/ai-agents docs
epilot.app @epilot/sdk/app docs
epilot.auditLogs @epilot/sdk/audit-logs docs
epilot.automation @epilot/sdk/automation docs
epilot.billing @epilot/sdk/billing docs
epilot.blueprintManifest @epilot/sdk/blueprint-manifest docs
epilot.calendar @epilot/sdk/calendar docs
epilot.configurationHub @epilot/sdk/configuration-hub docs
epilot.consent @epilot/sdk/consent docs
epilot.customerPortal @epilot/sdk/customer-portal docs
epilot.dashboard @epilot/sdk/dashboard docs
epilot.dataGovernance @epilot/sdk/data-governance docs
epilot.deduplication @epilot/sdk/deduplication docs
epilot.design @epilot/sdk/design docs
epilot.document @epilot/sdk/document docs
epilot.emailSettings @epilot/sdk/email-settings docs
epilot.emailTemplate @epilot/sdk/email-template docs
epilot.entity @epilot/sdk/entity docs
epilot.entityMapping @epilot/sdk/entity-mapping docs
epilot.environments @epilot/sdk/environments docs
epilot.eventCatalog @epilot/sdk/event-catalog docs
epilot.file @epilot/sdk/file docs
epilot.iban @epilot/sdk/iban docs
epilot.integrationToolkit @epilot/sdk/integration-toolkit docs
epilot.journey @epilot/sdk/journey docs
epilot.kanban @epilot/sdk/kanban docs
epilot.message @epilot/sdk/message docs
epilot.metering @epilot/sdk/metering docs
epilot.notes @epilot/sdk/notes docs
epilot.notification @epilot/sdk/notification docs
epilot.organization @epilot/sdk/organization docs
epilot.partnerDirectory @epilot/sdk/partner-directory docs
epilot.permissions @epilot/sdk/permissions docs
epilot.pricing @epilot/sdk/pricing docs
epilot.pricingTier @epilot/sdk/pricing-tier docs
epilot.purpose @epilot/sdk/purpose docs
epilot.query @epilot/sdk/query docs
epilot.sandbox @epilot/sdk/sandbox docs
epilot.sharing @epilot/sdk/sharing docs
epilot.snapshot @epilot/sdk/snapshot docs
epilot.submission @epilot/sdk/submission docs
epilot.targeting @epilot/sdk/targeting docs
epilot.templateVariables @epilot/sdk/template-variables docs
epilot.user @epilot/sdk/user docs
epilot.validationRules @epilot/sdk/validation-rules docs
epilot.webhooks @epilot/sdk/webhooks docs
epilot.workflow @epilot/sdk/workflow docs
epilot.workflowDefinition @epilot/sdk/workflow-definition docs

Codebase Structure

sdk-js/
├── clients/                    # 46 API client packages (source specs + types)
├── packages/
│   ├── epilot-sdk-v2/          # @epilot/sdk
│   ├── app-sdk/                # @epilot/app-sdk
│   └── app-bridge/             # @epilot/app-bridge
└── scripts/                    # code generation scripts

Explicit Client Access

import { epilot } from '@epilot/sdk'

epilot.authorize(() => '<my-token>')

// Get the cached singleton client
const entityClient = epilot.entity.getClient()
const { data } = await entityClient.getEntity({ slug: 'contact', id: '123' })

// Create a fresh (non-singleton) client instance
const freshClient = epilot.entity.createClient()
authorize(freshClient, () => '<my-token>')

Tree-Shakeable Imports

Import only what you need. Other APIs never touch your bundle.

import { getClient, authorize } from '@epilot/sdk/entity'

const entityClient = getClient()
authorize(entityClient, () => '<my-token>')

const { data } = await entityClient.getEntity({ slug: 'contact', id: '123' })

// Or use the handle for direct operation forwarding
import { entity } from '@epilot/sdk/entity'
const { data } = await entity.getEntity({ slug: 'contact', id: '123' })

Types

Each API subpath re-exports all schema types generated from the OpenAPI spec. Import them directly:

import type { Entity, EntitySchema, RelationAttribute } from '@epilot/sdk/entity'
import type { FileItem } from '@epilot/sdk/file'
import type { AutomationFlow } from '@epilot/sdk/automation'

The Client, OperationMethods, and PathsDictionary types are also available for typing client instances:

import type { Client } from '@epilot/sdk/entity'

const entityClient: Client = epilot.entity.getClient()

Headers

Global Headers

Set default headers applied to all clients. Useful for x-epilot-org-id, x-epilot-user-id, etc.

import { epilot } from '@epilot/sdk'

epilot.authorize(() => '<my-token>')
epilot.headers({
  'x-epilot-org-id': 'org-123',
  'x-epilot-user-id': 'user-456',
})

const { data } = await epilot.entity.searchEntities(...)

Standard Axios Headers

Use standard axios defaults.headers.common on individual clients:

const entityClient = epilot.entity.getClient()
entityClient.defaults.headers.common['x-epilot-org-id'] = 'org-123'

Auth Patterns

authorize() accepts a string or a function. The function form is preferred — it is called on every request, so tokens stay fresh.

import { authorize } from '@epilot/sdk'
import { getClient } from '@epilot/sdk/entity'

// Per-client — function predicate (recommended)
const entityClient = getClient()
authorize(entityClient, () => '<my-token>')

// Per-client — async function (e.g. OAuth / session)
authorize(entityClient, async () => {
  return await getTokenFromSession()
})

// Per-client — static string (sets default header once)
authorize(entityClient, 'my-static-api-token')
// Global — applies to all clients resolved from the SDK
import { epilot } from '@epilot/sdk'

epilot.authorize(() => '<my-token>')
epilot.authorize(async () => await getTokenFromSession())
epilot.authorize('my-static-api-token')

Fresh Client Instance

import { createClient, authorize } from '@epilot/sdk/entity'

const entityClient = createClient()
authorize(entityClient, () => '<my-token>')
entityClient.defaults.headers.common['x-epilot-org-id'] = 'org-123'

Multiple SDK Instances

import { createSDK } from '@epilot/sdk'

const sdk1 = createSDK()
sdk1.authorize(() => '<token-for-org-1>')
sdk1.headers({ 'x-epilot-org-id': 'org-1' })

const sdk2 = createSDK()
sdk2.authorize(() => '<token-for-org-2>')
sdk2.headers({ 'x-epilot-org-id': 'org-2' })

Interceptors

Use axios interceptors for custom request/response processing. Since clients are axios instances, you can use client.interceptors directly:

entityClient.interceptors.response.use((response) => {
  console.debug(`${response.config.method?.toUpperCase()} ${response.config.url}`, {
    status: response.status,
    data: response.data,
  })
  return response
})

Or register global interceptors applied to all clients:

epilot.interceptors.request((config) => {
  config.headers['x-correlation-id'] = generateTraceId()
  return config
})

Auto-Retry (429 Too Many Requests)

The SDK automatically retries requests that receive a 429 Too Many Requests response. It respects the Retry-After header (in seconds) to determine how long to wait before retrying.

Enabled by default with up to 3 retries.

import { epilot } from '@epilot/sdk'

// Customize retry behavior
epilot.retry({ maxRetries: 5, defaultDelayMs: 2000 })

// Disable retries
epilot.retry({ maxRetries: 0 })
Option Default Description
maxRetries 3 Maximum number of retries. Set to 0 to disable.
defaultDelayMs 1000 Fallback delay in ms when Retry-After header is missing.

For individually imported clients (tree-shakeable imports), apply the interceptor manually:

import { getClient, authorize } from '@epilot/sdk/entity'
import { applyRetryInterceptor } from '@epilot/sdk'

const entityClient = getClient()
authorize(entityClient, () => '<my-token>')
applyRetryInterceptor({ client: entityClient, config: { maxRetries: 3 } })

Large Response Handling (413 Payload Too Large)

epilot APIs use a large response middleware to work around the AWS Lambda 6MB response limit. When a response exceeds ~5.1MB, the API uploads the payload to S3 and returns a presigned URL instead.

The SDK handles this transparently — it sends the opt-in Accept header and automatically fetches the full payload from S3 when a large response URL is returned. Enabled by default.

import { epilot } from '@epilot/sdk'

// Disable large response handling
epilot.largeResponse({ enabled: false })

For individually imported clients (tree-shakeable imports), apply the interceptor manually:

import { getClient, authorize } from '@epilot/sdk/entity'
import { applyLargeResponseInterceptor } from '@epilot/sdk'

const entityClient = getClient()
authorize(entityClient, () => '<my-token>')
applyLargeResponseInterceptor({ client: entityClient, config: { enabled: true } })

Overrides & Custom APIs

Override built-in API specs or register custom APIs via .epilot/sdk-overrides.json. This is useful for testing new versions of an API spec or getting the latest types without waiting for an SDK release.

{
  "entity": "./specs/entity-openapi.json",
  "myNewApi": "./specs/my-new-api-openapi.json"
}
// Built-in API with overridden spec
const { data } = await epilot.entity.getEntity({ slug: 'contact', id: '123' })

Override Commands

# Apply all overrides from .epilot/sdk-overrides.json
npx epilot-sdk override

# Override a single API
npx epilot-sdk override entity ./my-local-entity-spec.yaml

# Regenerate types after spec changes
npx epilot-sdk typegen
Migration from @epilot/*-client

Drop-in replacement — just change the import path:

// Before
import { getClient, createClient, authorize } from '@epilot/entity-client'
import type { Client, Entity } from '@epilot/entity-client'

// After
import { getClient, createClient, authorize } from '@epilot/sdk/entity'
import type { Client, Entity } from '@epilot/sdk/entity'
Client Lifecycle

When you call authorize(), headers(), retry(), largeResponse(), or interceptors, the SDK invalidates all cached client instances. The next operation call creates a fresh client with the updated configuration.

Operation methods are always up to date — calls like epilot.entity.getEntity(...) re-resolve the client on every invocation, so they always use the latest config.

Direct getClient() references can go stale — if you hold a reference and then change config, your reference still points to the old client:

const entityClient = epilot.entity.getClient()

epilot.authorize('new-token') // invalidates all cached clients

// entityClient still has the old token
// epilot.entity.getEntity(...) will use a new client with the new token

If you need a long-lived reference that survives config changes, call getClient() again after changing config, or use operation methods directly.

Contributing

See CONTRIBUTING.md for internal development and publishing instructions.

Releases

Packages

Used by

Contributors

Languages