> ## Documentation Index
> Fetch the complete documentation index at: https://docs.trdrs.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Billing for Connect apps

> Set up your app's billing before production, see how each month's invoice is charged to your card, and know what a past-due invoice and the billing pause do.

Connect is billed at \$2 a month for each active trader, charged to the card your app keeps on file.
You set billing up once, before your app's production opens: an owner of your app accepts the Connect
terms with a billing name and email, then saves a card through Whop's hosted checkout. From then on,
each month's invoice charges that card on its own, and a month with no active traders charges nothing.

Use this page when you open production, and whenever a charge fails. By the end you know how to set
billing up, how to pay an invoice that is past due, what your app and your traders keep while one is
unpaid, and how your app returns to normal.

<Note>
  Billing runs in production. The sandbox is free and asks for no card, and its billing routes
  answer `409` `production_only`.
</Note>

## What you pay

Each of your apps has its own bill and its own card. A trader of two of your apps is an active trader
of each one they traded through.

| Item | What it is |
| - | - |
| Price | \$2 for each active trader each month, in US dollars. [Active traders](/guides/connect-active-traders) says who counts. |
| First month billed | The month an owner first accepts the Connect terms. |
| When it's charged | Shortly after each month ends in UTC, trdrs issues the month's invoice and charges your card on file. |
| A month with no active traders | The invoice is `zero`, and nothing is charged. |
| A fill that reached trdrs after its month was invoiced | Your next invoice bills that trader once, on a late line for their month. |

Your invoices list each month's lines as Whop shows them, the active traders behind them and their
price, and where each invoice stands: `charging`, `paid`, `past_due`, `void` or `zero`.

## Set up billing

An owner of your app does this once, in the Connect dashboard, as the Billing step on the way to
production. Any member of your team can read your app's billing.

<Steps>
  <Step title="Accept the Connect terms">
    Read the current Connect terms, which the dashboard links, and accept them with a billing name and
    a billing email. The name goes on every invoice, and your billing emails go to that address and
    to every owner of your team.

    The terms carry a version, such as `2026-10-02`. If the terms change while you read them, the
    dashboard shows the new version for you to accept.
  </Step>

  <Step title="Save a card">
    Open the card setup. It takes you to Whop's hosted checkout, where you save a card, and saving it
    charges nothing. Whop then returns you to your app's billing page, which shows the card's brand,
    last four digits and expiry once the save is confirmed.

    A setup stays open for 24 hours. If one expires or ends with no card saved, open another.
  </Step>

  <Step title="Open production">
    With the terms accepted and a card saved, open production with your app's Connect pass, as
    [Open production](/guides/connect-conformance#open-production) describes.
  </Step>
</Steps>

You have a card on file and an app in production. The first invoice comes after the month you
accepted the terms.

Change the billing name or email at any time from your billing page. The change applies from the next
invoice, and the terms you accepted stand as they are.

## Replace your card

Save a new card the same way at any time, including while your app is past due or paused. Each
invoice charges the card saved last, and saving a card while an invoice is past due charges that
invoice again on the new card at once.

## Pay a past-due invoice

When a charge fails, the invoice is past due, and that moment is Day 0. Your app has a grace of five
business days to pay. A business day is a UTC calendar day from Monday to Friday, with no holidays,
and the grace counts only business time:

| When | What happens |
| - | - |
| Day 0 | The invoice is past due. Your billing contacts get an email with the amount, the reason the bank gave, the exact time the billing pause starts, a Pay now link and an Update card link. |
| Business day 2 | The first reminder, naming the pause time. |
| Business day 4 | The second reminder. |
| Business day 5 | The billing pause starts, and an email says so. |

For example:

| Day 0 (UTC) | First reminder | Second reminder | Pause |
| - | - | - | - |
| Thursday 1 October, 00:05 | Monday 5 October, 00:05 | Wednesday 7 October, 00:05 | Thursday 8 October, 00:05 |
| Saturday 3 October, 14:00 | Wednesday 7 October, 00:00 | Friday 9 October, 00:00 | Saturday 10 October, 00:00 |

A second invoice that fails during the grace keeps the same Day 0 and the same pause time.

Pay in any of these ways:

| You | What happens |
| - | - |
| Open **Pay now** in the email or on your billing page | It opens Whop's pay link for the oldest past-due invoice, or your bank's page when the bank asked you to confirm the charge. |
| Choose **Charge my card again** on a past-due invoice | trdrs charges your card on file again, at most once an hour for each invoice. Use it once your bank clears the charge or the card's account is funded. |
| Save a new card | Each past-due invoice is charged again on the new card. |

trdrs also charges the card again by itself after a decline the bank calls temporary, such as
`insufficient_funds`, at each reminder, twice at most. After a decline that names the card lost, stolen,
expired or closed, the invoice waits for a new card.

## Know what the billing pause stops and keeps

The billing pause stops your app's growth. Your traders keep trading exactly as before, so no trader's
evaluation, with its minimum trading days and time limits, ever turns on your bill.

| While paused | |
| - | - |
| Refused | A Connect link for a trader who holds no account through your app. Hosted Connect for such a trader, a new Demo of your white-label paper, and a sign-in on a provider the trader holds no account on through your app. A new production API key. A first production pass for another app of your organization. |
| Kept | Every trader's accounts, positions and orders: every order, cancel and close runs as usual. A trader who holds an account through your app gets Connect links, opens hosted Connect, signs in again on what they hold and opens their Demo. Your API keys and their revocation, websites, tiles, white-label paper, Demos, trader suspensions, name and logo, and billing. Every read. |
| Billed | Invoicing goes on: fills made while paused count toward their month. |

A trader who holds an account through your app is one who connected an account through your Connect,
or holds a Demo of your white-label paper.

## Return to normal

Your app returns to normal once no invoice is past due: each one paid, or voided by trdrs. It happens
on its own, within minutes of the payment, and a last email confirms it. There's nothing else to do.
Every past-due invoice must be settled, so paying one of two keeps the pause in force.

trdrs can hold your pause for a while, for example when a charge failed through an outage at Whop or
at trdrs. Your standing's `heldUntil` shows until when. If an invoice is still past due when the hold
ends, the pause applies at that moment.

## Read your standing

Every read of your app carries `billing`, its standing on the Connect billing line, so your own systems
can watch it:

```json theme={null}
{
  "line": "connect",
  "target": "a:5f0c6b2e-8d4a-4c3e-9b1f-2a7d6e8c9f01",
  "state": "past_due",
  "pastDueSince": "2026-10-01T00:05:00.000Z",
  "firstReminderAt": "2026-10-05T00:05:00.000Z",
  "secondReminderAt": "2026-10-07T00:05:00.000Z",
  "pauseAt": "2026-10-08T00:05:00.000Z",
  "pausedAt": null,
  "heldUntil": null,
  "pastDueCents": 4600,
  "payUrl": "https://whop.com/…",
  "billingUrl": "https://…/apps/5f0c6b2e-8d4a-4c3e-9b1f-2a7d6e8c9f01/billing"
}
```

`state` is `current`, `past_due` or `paused`. `billing` is null on a sandbox app, and on a production
app until an owner accepts the terms.

## Handle billing refusals

A request the billing pause refuses from your own backend or dashboard answers `402` with your
standing and where to pay:

```json theme={null}
{
  "error": "billing_paused",
  "billing": {
    "line": "connect",
    "target": "a:5f0c6b2e-8d4a-4c3e-9b1f-2a7d6e8c9f01",
    "state": "paused",
    "pastDueSince": "2026-10-01T00:05:00.000Z",
    "pausedAt": "2026-10-08T00:05:00.000Z",
    "heldUntil": null,
    "payUrl": "https://whop.com/…",
    "billingUrl": "https://…/apps/5f0c6b2e-8d4a-4c3e-9b1f-2a7d6e8c9f01/billing"
  }
}
```

| Code | Status | When | What to do |
| - | - | - | - |
| `billing_paused` | `402` | Your app's pause is in force: a Connect link for a trader new to your app, or a new production API key. Or another app of your organization is paused when you open production | Pay at `payUrl`, then send the request again |
| `billing_paused` | `403` | In hosted Connect, for a trader new to your app, a new Demo, or a sign-in on a provider new to the trader. The trader's answer names the pause and carries no pay link, since the bill is yours | Pay your past-due invoices; the trader can then go on |
| `billing_setup_required` | `409` | Opening production, saving a card or changing your billing name or email before billing is set up. `missing` lists `terms`, `card` or both | Accept the terms and save a card |
| `billing_unavailable` | `503` | Opening production or saving a card before Connect billing collects in this deployment. A link or a key also answers it when trdrs couldn't read your standing | Try again later, with the same `Idempotency-Key` |
| `terms_version_stale` | `409` | Accepting terms that changed since you read them. `terms` carries the current `version` and `url` | Read the current terms and accept them |
| `production_only` | `409` | A billing route in the sandbox | Billing runs in production |

**Charge my card again** answers `202` with `charging: true` while the charge runs, or `200` with
`paid: true` when the last charge turned out paid. It's refused with `409` and one of these codes:

| Code | When |
| - | - |
| `not_past_due` | The invoice isn't past due. |
| `no_card` | Your app has no card on file. Save one, which charges every past-due invoice again. |
| `too_soon` | You charged this invoice again within the last hour. |
| `in_progress` | A charge of this invoice is being made or closed now. Read it again shortly. |

## The routes this page calls

The Connect dashboard makes these calls in production with your team's Connect sign-in. Any member
reads, and an owner writes:

| Step | Route |
| - | - |
| Read your billing | `GET /api/connect/apps/{appId}/billing` |
| Accept the Connect terms | `PUT /api/connect/apps/{appId}/billing/terms` |
| Change your billing name or email | `PATCH /api/connect/apps/{appId}/billing/profile` |
| Save or replace a card | `POST /api/connect/apps/{appId}/billing/cards` |
| Confirm a card when Whop returns you | `GET /api/connect/apps/{appId}/billing/cards/{cardId}?setupIntent=sint_…` |
| Read your invoices | `GET /api/connect/apps/{appId}/invoices` |
| Charge my card again | `POST /api/connect/apps/{appId}/invoices/{invoiceId}/charge` |

## Next steps

<CardGroup cols={2}>
  <Card title="Pass conformance" icon="list-check" href="/guides/connect-conformance">
    Earn the Connect pass that opens your app's production.
  </Card>

  <Card title="Active traders" icon="receipt" href="/guides/connect-active-traders">
    See who counts as an active trader, and check an invoice.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.