Skip to content

TypeScript SDK

The official TypeScript SDK wraps the Trile API in typed clients. It’s built on the native fetch API, so it runs in Node.js 18+, Deno, Bun, browsers, and edge runtimes with zero runtime dependencies.

Terminal window
npm install @trilehq/sdk
import { Configuration, CustomersApi } from '@trilehq/sdk'
const config = new Configuration({
apiKey: process.env.TRILE_KEY, // your nep_test_… or nep_live_… key
})
const customers = new CustomersApi(config)
// Every response is wrapped in { success, data, meta } — your result is in `.data`.
const { data: customer } = await customers.createCustomer({
createCustomer: { email: 'asha@example.com', name: 'Asha K.' },
})
console.log(customer.id) // → "cus_…"

Pass a secret API key (see Authentication). Use a nep_test_… key against test data and a nep_live_… key in production. The SDK sends it as the x-api-key header, so keep it server-side — never ship it in client-side code.

const config = new Configuration({ apiKey: 'nep_live_…' })
OptionTypeDescription
apiKeystringYour secret API key. Sent as the x-api-key header.
basePathstringAPI base URL. Defaults to https://api.trile.app.
headersRecord<string, string>Extra headers sent on every request.
fetchApitypeof fetchCustom fetch implementation (e.g. for testing).
middlewareMiddleware[]Hooks to run before/after each request.

Every successful response is wrapped in the standard { success, data, meta } envelope — your result is always in data, and meta.requestId is handy when contacting support. Destructure it:

const { data, meta } = await customers.getCustomer({ customerId: 'cus_…' })
console.log(data.email, meta.requestId)

Any non-2xx response throws a ResponseError carrying the raw Response, so you can read the status and the API’s error envelope.

import { ResponseError } from '@trilehq/sdk'
try {
await customers.getCustomer({ customerId: 'cus_missing' })
} catch (err) {
if (err instanceof ResponseError) {
console.error(err.response.status) // e.g. 404
console.error(await err.response.json()) // { success: false, error: { code, message }, meta }
} else {
throw err
}
}

List endpoints return { items, nextCursor } inside data. Pass nextCursor back as cursor to page; it’s null on the last page. All filter arguments are optional. See Pagination.

let cursor: string | undefined
do {
const { data: page } = await customers.listCustomers({ limit: '50', cursor })
for (const customer of page.items) console.log(customer.id, customer.email)
cursor = page.nextCursor ?? undefined
} while (cursor)

Every create/mutating call accepts an optional idempotencyKey — sending the same key retries safely. See Idempotency.

await customers.createCustomer({
idempotencyKey: crypto.randomUUID(),
createCustomer: { email: 'asha@example.com' },
})

Each resource has its own client class; construct it with your Configuration.

ClientMethods
CustomersApicreateCustomer, getCustomer, listCustomers, updateCustomer, archiveCustomer
CatalogApicreateProduct, getProduct, listProducts, updateProduct, archiveProduct, uploadProductImage, createPrice, getPrice, listPrices, updatePrice, archivePrice
SubscriptionsApicreateSubscription, getSubscription, listSubscriptions, updateSubscription, cancelSubscription
InvoicesApicreateInvoice, getInvoice, listInvoices, updateInvoice, sendInvoice, listInvoiceEvents
CheckoutApicreateCheckoutSession
WebhooksApicreateWebhookEndpoint, getWebhookEndpoint, listWebhookEndpoints, updateWebhookEndpoint, deleteWebhookEndpoint, rotateWebhookSecret, sendTestWebhook, replayWebhookDeliveries, listWebhookDeliveries
EventsApilistEvents, getEvent

Every request and response is fully typed — your editor autocompletes the exact fields. For endpoint-level detail, see the API Reference.