@epilot/sdk
v2.1.2
Published
JavaScript/TypeScript SDK for epilot APIs
Maintainers
Readme
Install
npm i @epilot/sdk axios openapi-client-axiosQuick 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
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.consent | @epilot/sdk/consent | docs |
| epilot.customerPortal | @epilot/sdk/customer-portal | docs |
| epilot.dashboard | @epilot/sdk/dashboard | docs |
| epilot.dataManagement | @epilot/sdk/data-management | 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.erpIntegration | @epilot/sdk/erp-integration | docs |
| epilot.eventCatalog | @epilot/sdk/event-catalog | docs |
| epilot.file | @epilot/sdk/file | docs |
| epilot.iban | @epilot/sdk/iban | 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.sandbox | @epilot/sdk/sandbox | 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 |
OpenAPI Spec
Retrieve the full OpenAPI specification for any API at runtime. The spec is lazy-loaded on first call and cached.
import { epilot } from '@epilot/sdk'
// Via API handle
const entitySpec = await epilot.entity.openapi()
console.log(entitySpec.info.title) // "Entity API"
console.log(entitySpec.paths) // all paths with full schemas
// Via top-level method
const spec = await epilot.openapi('entity')For tree-shakeable imports:
import { openapi } from '@epilot/sdk/entity'
const spec = await openapi()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 typegenDrop-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'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 tokenIf you need a long-lived reference that survives config changes, call getClient() again after changing config, or use operation methods directly.
