Skip to content

Integration

Universal API + Bastle

What syncs from Universal API, what it makes possible, and how to connect it.

Live

This connector ships today. Connect it from workspace settings and Bastle backfills the history the source will serve.

What does the Universal API integration do?

Bastle's write API accepts subscription data from any billing system, including one you built yourself. A single batched import endpoint upserts plans, customers, subscriptions, charges and refunds against your own external ids, and a read API returns the same metrics the dashboard renders. It is available today, self-serve, with scoped API keys.

What syncs

Bastle reads the following from Universal API and normalises it into the same entities every other source produces. Ingestion is read-only: nothing is created, changed or cancelled upstream.

  • Inbound: plans, customers, subscriptions, charges and refunds, posted as one batched payload and upserted idempotently on your own object ids.
  • Inbound: per-entity endpoints for reading and updating a single record by external id.
  • Outbound: metrics, segments, annotations, goals, customer attributes and cancellation insights.
  • Every import records an ingestion run and emits an import-completed event to your webhook endpoints.
  • Cadence: whatever you choose. The API is synchronous and idempotent, so re-posting the same batch is safe.

Once connected

What Universal API data unlocks

Connecting a source is not the point; what you can answer afterwards is. These are the questions this data makes answerable.

Homegrown billing becomes a first-class source

If your billing lives in your own database, you get the same metrics, segmentation and cancellation analysis as a Stripe account, without waiting for a connector to be written.

Bulk import without a support ticket

Historical data can be pushed as batches against the API rather than emailed as a CSV template and processed by someone else.

Idempotent by construction

Records upsert on the pair of source and your external id, so a retried request after a network timeout cannot double-count revenue.

Metrics wherever you need them

The read API returns the same computed metrics the dashboard shows, so an internal admin page or a board deck script does not need to reimplement any definitions.

Setup

Connecting Universal API

The whole flow, start to first chart. No implementation call and no data engineer.

  1. Create an API key in Settings → API keysKeys are scoped to read or write. Only the prefix and a hash are stored, so the full key is shown once at creation and cannot be retrieved afterwards.
  2. Post your first batchSend plans, customers, subscriptions, charges and refunds to the import endpoint. Omitting a source id targets your workspace's API source, which is created on first use.
  3. Re-post whenever data changesUpserts key on your own object ids, so sending a record again updates it rather than duplicating it. There is no separate update call to reason about.
  4. Subscribe to outbound eventsRegister a webhook endpoint to be notified when an import completes, and to receive the same subscription and charge events Bastle derives from any source.

Why this exists

Analytics tools tend to treat non-standard billing as an edge case: you either use a supported processor or you email a CSV to support and wait. A meaningful share of subscription businesses bill through something they wrote themselves, or through a processor nobody has built a connector for. The write API makes that a first-class path rather than a workaround, and it is deliberately the first thing in this directory marked live.

The contract

One request carries whole batches of related entities. References inside the payload are made with your own ids — a subscription names its customer and plan by your identifiers — and Bastle resolves them to internal keys as it writes. That means you never have to make a round trip to learn an id before you can reference it, and it means a batch is order-independent.

Every write upserts on the pair of source and external id. Retrying a request that timed out is safe. Replaying yesterday's batch is safe. This is worth stating plainly because the failure mode of a non-idempotent revenue import is a revenue chart that is quietly wrong.

Keys and scopes

API keys carry read or write scope. Bastle stores only a prefix and a hash of each key and verifies by hashing what is presented, so the plaintext exists exactly once, in the modal that created it. A read-only key is the right choice for anything that only pulls metrics.

Limits worth knowing

Import payloads are capped in size, so very large historical loads should be chunked rather than sent as one enormous body. Sources created through the API are API sources, and the import endpoint refuses to write into a source owned by a provider connector — otherwise a hand-written record and a Stripe-derived record could contend for the same row.

Related

Other sources

Companies billing through Universal API usually have at least one of these in the stack too.

Universal API and Bastle: common questions

Is the write API actually available now?

Yes. Scoped API keys, the batched import endpoint, the per-entity endpoints and the metrics read endpoints are all shipped and self-serve. It is one of only two integrations in this directory marked live, and the status field on the others is not decoration.

What happens if I post the same batch twice?

Nothing bad. Every record upserts on the combination of source and your own external id, so a repeated batch updates existing rows rather than creating duplicates. Retrying after a timeout is the intended behaviour, not a risk.

Can I push into a source that came from a connector?

No. The import endpoint only writes into API sources, and rejects an attempt to write into a Stripe or Chargebee source. Provider connectors own their rows, and letting two writers contend for the same record would make discrepancies impossible to explain.

How large can an import batch be?

There is a body size cap, so a full historical load should be sent as a series of chunks rather than a single request. Because writes are idempotent, chunking is safe to parallelise and safe to retry.

Connect Universal API and see your own history.

Bastle backfills what Universal API will serve, then keeps current over webhooks — usually a couple of minutes before the first real chart. Free while in beta, no card required.