npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@epilot/sdk

v2.1.2

Published

JavaScript/TypeScript SDK for epilot APIs

Readme

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

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 typegen

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'

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.