---
title: "SDKs and tools"
description: "Use the typed TypeScript client for the billing API, or generate a client in your own language from the OpenAPI document that this reference is built from."
canonical_url: "https://twominutebilling.com/help/developers/getting-started/sdks"
---
# SDKs and tools

> Use the typed TypeScript client for the billing API, or generate a client in your own language from the OpenAPI document that this reference is built from.

Call the Two Minute Billing API from TypeScript with the typed client, or from any language with a client you generate from the OpenAPI document. Both use the same REST API that the API reference describes.

## Use the TypeScript client

The client is a thin, dependency-free wrapper over the REST API. Its response types come from the
OpenAPI document, so they match what the engine returns. It sends an `Idempotency-Key` on every
write for you. Pass `idempotencyKey` in the options to replay a specific request.

Install it from the npm registry. It has no dependencies and uses the platform `fetch`, so it
runs on Node 20+, Deno, Bun and in the browser:

```sh [terminal]
pnpm add @two-minute-billing/sdk
```

The package version is the Two Minute Billing release it was built from. Install the version
that matches your API. The source is in `sdk/` in the repository.

```ts [billing.ts]
import { Tmbilling } from "@two-minute-billing/sdk";

const tmb = new Tmbilling({
  apiKey: process.env.TMBILLING_API_KEY!,
  baseUrl: process.env.TMBILLING_URL,
});

const biz = await tmb.businesses.create({ name: "Fernhill Analytics", default_currency: "USD" });
const product = await tmb.products.create(biz.id, { name: "Pro" });
const price = await tmb.prices.create(biz.id, {
  product: product.id,
  name: "Pro monthly",
  model: "flat",
  currency: "USD",
  amount_minor: 2900,
  interval: "month",
});

const customer = await tmb.customers.create(biz.id, { email: "maya@example.com", currency: "USD" });
const subscription = await tmb.subscriptions.create(biz.id, customer.id, {
  items: [{ price: price.id, quantity: 1 }],
  trial_days: 14,
});
```

Set `baseUrl` to your API host. Without it the client calls `http://localhost:4000`.

## Handle errors from the client

A non-2xx answer throws a `TmbillingError` with the HTTP `status`, the error `type`, the
`message`, and the full response in `body`. Branch on them as described in
[Errors](https://twominutebilling.com/help/developers/api-essentials/errors):

```ts [collect.ts]
import { TmbillingError } from "@two-minute-billing/sdk";

try {
  await tmb.invoices.collect(biz.id, invoiceId);
} catch (err) {
  if (err instanceof TmbillingError && err.type === "rate_limit_error") {
    // Nothing was processed. Wait, then retry the same request.
  }
  throw err;
}
```

Some errors also carry a `code`, such as `live_access_required`. Read it from
`err.body.error.code`.

The client exports the resource types too — `Business`, `Customer`, `Price`, `Subscription`,
`Invoice` and more — so you can type your own functions against the API's objects.

## Know what the client covers

The client covers the billing flow end to end: businesses, the catalog (products, product groups,
prices, coupons and coupon sets), customers, payment methods and payment intents, subscriptions
(including estimates and plan changes), invoices, payments, the wallet, credit notes, payment
links and checkout sessions, usage (meters, usage events, usage keys and model prices), events,
metadata rules, tax profiles and regions, and webhook endpoints. Products, prices and
subscriptions take your own `id` when you create them.

For the rest of the API, call it directly with `fetch` and the same `Authorization` and
`Idempotency-Key` headers. That includes:

- reports and analytics,
- settings, team members and API keys,
- integrations,
- the dunning actions on an invoice (pause, resume, stop),
- creating a customer with your own `id` (the API accepts it; the client's type does not yet).

The [API reference](https://twominutebilling.com/help/developers/api-reference) lists every endpoint.

## Generate a client in another language

Fetch the spec from your API host:

```sh
curl $TMBILLING_URL/openapi.json -o openapi.json
```

It is a standard OpenAPI 3.1 document, so the usual generators work:

<code-group>

```sh [Python]
openapi-generator-cli generate -i openapi.json -g python -o ./tmbilling-python
```

```sh [Go]
oapi-codegen -package tmbilling openapi.json > tmbilling.go
```

```sh [TypeScript types]
npx openapi-typescript openapi.json -o schema.d.ts
```

</code-group>

This site's [API reference](https://twominutebilling.com/help/developers/api-reference) is generated from the same document.

## Use the built-in tools

<table>
<thead>
  <tr>
    <th>
      Tool
    </th>
    
    <th>
      What you get
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      Webhook signature check
    </td>
    
    <td>
      A few lines in any language, no library needed. See <a href="https://twominutebilling.com/help/developers/webhooks/signatures">
        Verifying signatures
      </a>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      Test gateway
    </td>
    
    <td>
      Test cards for every failure, and Time Travel for a year of renewals. See <a href="https://twominutebilling.com/help/developers/getting-started/test-and-live">
        Test and live mode
      </a>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      Estimates
    </td>
    
    <td>
      A dry run for new subscriptions and plan changes that returns the real invoice and changes nothing.
    </td>
  </tr>
</tbody>
</table>


## Sitemap

See the full [sitemap](https://twominutebilling.com/sitemap.md) for all pages.
