Creator API

Read your releases, supporters and payments from your own systems.

The API gives your own systems, like a members-only site, the same data you see in your project: releases, supporters and payments. The API calls releases creations. This page is also available as plain markdown at https://backers.club/developers.md.

1. Overview

The base URL is https://backers.club/api/v1.

curl https://backers.club/api/v1/creations \
  -H "Authorization: Bearer $API_KEY"

2. Conventions

Lists and pagination

Every list returns the same envelope, ordered by id, oldest first:

{
  "data": [ ... ],
  "next_cursor": "4812"
}

Pass next_cursor back as after to get the next page. When next_cursor is null, you have everything. limit defaults to 100 and is capped at 200. New records always get higher ids, so paging is stable while records are added.

curl "https://backers.club/api/v1/payments?after=4812&limit=200" \
  -H "Authorization: Bearer $API_KEY"

Errors

Errors share one shape:

{
  "error": {
    "code": "not_found",
    "message": "Not found"
  }
}
{
  "error": {
    "code": "invalid",
    "message": "Title can't be blank and URL can't be blank",
    "errors": {
      "title": ["can't be blank"],
      "url": ["can't be blank"]
    }
  }
}

3. Creations

A creation is a release: an episode, video, post or month. Releases synced from your feed and releases you add yourself are both here.

List creations

GET /api/v1/creations

Skipped releases are included with "ignored": true, so matching never silently misses one.

curl "https://backers.club/api/v1/creations?published_after=2026-09-01T00:00:00Z" \
  -H "Authorization: Bearer $API_KEY"
{
  "data": [
    {
      "id": 3051,
      "uid": "https://example.com/episodes/41",
      "title": "Episode 41",
      "url": "https://example.com/episodes/41",
      "published_at": "2026-09-03T08:30:00Z",
      "ignored": false,
      "created_at": "2026-09-03T08:55:12Z",
      "updated_at": "2026-09-03T08:55:12Z"
    }
  ],
  "next_cursor": null
}

Get one creation

GET /api/v1/creations/:id returns the same fields plus a billing summary.

{
  "id": 3051,
  ...
  "payer_count": 182,
  "revenue": {
    "amount": "4550.00",
    "application_fee": "455.00",
    "credit_card_fee": "61.43",
    "payout": "4033.57",
    "currency": "DKK"
  }
}

4. Supporters

GET /api/v1/supporters returns one record per subscription to your project, including cancelled ones. Use it to grant, pause or revoke ongoing access.

{
  "data": [
    {
      "supporter_id": 912,
      "subscription_id": 20417,
      "email": "[email protected]",
      "name": "Ada Lovelace",
      "status": "active",
      "amount": "25.00",
      "currency": "DKK",
      "started_at": "2025-03-14T19:02:44Z",
      "cancelled_at": null,
      "paused_until": null,
      "updated_at": "2026-10-01T06:00:03Z"
    }
  ],
  "next_cursor": null
}

Supporter status

Filters

5. Payments

GET /api/v1/payments returns one record per payment. Use it to grant access per release.

{
  "data": [
    {
      "payment_id": 88120,
      "supporter_id": 912,
      "subscription_id": 20417,
      "email": "[email protected]",
      "creation_ids": [3051, 3052],
      "status": "paid",
      "purchased_at": "2026-10-01T06:00:00Z",
      "transaction_id": "ch_3Q2xYz...",
      "amount": "50.00",
      "currency": "DKK",
      "refunded_at": null,
      "refunded_amount": null,
      "updated_at": "2026-10-01T06:00:03Z"
    }
  ],
  "next_cursor": null
}

Payment status

A refunded payment is always refunded, never paid.

Filters

Who paid for creation X?

curl "https://backers.club/api/v1/payments?creation_id=3051&status=paid" \
  -H "Authorization: Bearer $API_KEY"

Grant access to every email (or supporter_id) in the result. To stay in sync, poll with updated_after set to the latest updated_at you have seen, and status=paid,refunded. Revoke access when a payment turns refunded. updated_after is inclusive, so expect to see the boundary record again.

6. Supporter status and payment status are independent

A supporter’s status says what happens next; a payment’s status says what already happened. Cancelling does not revoke a paid payment: a cancelled supporter keeps every paid payment, and the releases those payments cover stay paid for. Their pending payments are cancelled and become unpaid.

Grant ongoing access from supporters, and per-release access from payments.

7. When a creation is billed

Nothing is charged when a creation is published or created.

Until the run, a creation has no payments, payer_count is 0 and revenue is zero.

The billing estimate returned when creating a creation (section 8) is only a guide:

8. Creating creations

POST /api/v1/creations needs a key with the creations:write scope; other keys get 403. It creates exactly what adding a release in your project creates. No emails are sent.

Send JSON:

Other fields are ignored.

curl -X POST https://backers.club/api/v1/creations \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Episode 42",
    "url": "https://example.com/episodes/42",
    "uid": "episode-42",
    "published_at": "2026-10-14T08:00:00Z"
  }'

Dry run

With "dry_run": true you get 200, nothing is saved, and the creation has no id, created_at or updated_at yet:

{
  "dry_run": true,
  "existing": false,
  "creation": {
    "id": null,
    "uid": "episode-42",
    "title": "Episode 42",
    "url": "https://example.com/episodes/42",
    "published_at": "2026-10-14T08:00:00Z",
    "ignored": false,
    "created_at": null,
    "updated_at": null
  },
  "billing": {
    "charges_immediately": false,
    "billed_in": "2026-11",
    "already_billed_period": false,
    "active_subscriptions": 182,
    "estimated_amount": "4550.00",
    "currency": "DKK"
  }
}

A real create returns the same shape with "dry_run": false and the saved creation.

If your project syncs from a feed

If releases already come in automatically from a podcast or RSS feed, a blog or a YouTube channel, the sync creates them itself. Don’t POST those too, or POST with the same uid the sync uses: the feed item’s guid, or the video id for YouTube. Otherwise the sync creates a duplicate and supporters are billed twice for the same release. GET /api/v1/creations shows the uid of every synced release.