---
title: "Test and live mode"
description: "Every business has a live mode and a test mode. Build against test mode with test cards for each failure and Time Travel, then switch your key to go live."
canonical_url: "https://twominutebilling.com/help/developers/getting-started/test-and-live"
---
# Test and live mode

> Every business has a live mode and a test mode. Build against test mode with test cards for each failure and Time Travel, then switch your key to go live.

Every business has two modes, and each mode is a business of its own with its own id:

- **Live mode** charges real cards through the payment gateways you connect.
- **Test mode** has a built-in test gateway that cannot move money, and Time Travel.

The two modes share nothing at run time: customers, subscriptions, invoices and money in one mode
never appear in the other. Same endpoints, same validation, same billing math, same events and
webhook signatures — only the gateway and the clock differ.

## Find both ids

`POST /v1/businesses` creates both modes at once. Every business object names its other mode:

```json [Response]
{
  "object": "business",
  "id": "biz_XXXXXXXXXXXXXXXXXXXXXX01",
  "name": "Fernhill Analytics",
  "livemode": "test",
  "live_business_id": "biz_XXXXXXXXXXXXXXXXXXXXXX02",
  "test_business_id": null
}
```

On a test business, `live_business_id` is its live mode. On a live business, `test_business_id`
is its test mode. A live business created before test modes existed has `test_business_id: null`
until you open its test mode once:

<endpoint method="POST" path="/v1/businesses/{biz}/test_mode">



</endpoint>

Call it with the live business id. It returns the test business, and creates it on the first call.

## Use the key for the mode

Create API keys under **Settings → Developer → API keys**. Each key belongs to one mode:

<table>
<thead>
  <tr>
    <th>
      Key
    </th>
    
    <th>
      Reaches
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        sk_test_…
      </code>
    </td>
    
    <td>
      Test businesses only
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        sk_live_…
      </code>
    </td>
    
    <td>
      Live businesses only
    </td>
  </tr>
</tbody>
</table>

A key never crosses modes. Ask a test key for a live business id, or the reverse, and you get
`404` `No such business` — the same answer as for an id that does not exist. So a test key in a
misconfigured environment cannot touch live data.

Create with a test key and you get the test business. The live one is created beside it. A test
key cannot ask for `"livemode": "live"` (`400`).

<tip title="Use the same catalog ids in both modes">

Products, prices and coupons take readable ids you set, such as `pro` and `pro-monthly-usd`.
Use the same ids in test and live mode, and switching modes is a change of key and business id,
not of code.

</tip>

## Know your plan limits

<note title="Cloud only">

Plans, the live-mode lock and `account_restricted` apply on Two Minute Billing Cloud. On a
self-hosted installation they never apply: `live_access` is always `enabled` and `status` is
always `active`.

</note>

On the hosted service, a new organization starts on the **free plan** with live mode on, every
feature. No credit card required. It is free while you make less than
[the Free plan's monthly limit](https://twominutebilling.com/pricing). Then a flat monthly price. When you bill more than your plan covers, your billing
carries on and the Billing page tells you to change to a larger plan.

Live mode is locked only if our team turns it off for your organization. Then every write to a
live business answers:

```json
{
  "error": {
    "type": "permission_error",
    "code": "live_access_required",
    "message": "Live mode is off for this organization. Use test mode, or contact us to turn live mode on."
  }
}
```

Reads still work.

The whole organization can become read-only: writes answer `403` with code `account_restricted`.
Your customers keep being billed. This occurs in two cases:

- A paid plan becomes unpaid. Pay the open invoice to make changes again.
- You stay above your plan's limit and our team makes the organization read-only. Change to a
plan that covers your billing to make changes again.

## Use the test cards

The test gateway reads the card number you pass as the payment method token, and behaves the
same way every time:

<table>
<thead>
  <tr>
    <th>
      Card number
    </th>
    
    <th>
      What happens
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        4242424242424242
      </code>
    </td>
    
    <td>
      Saves and charges successfully.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        4000000000000002
      </code>
    </td>
    
    <td>
      Hard decline. Not retried.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        4000000000000069
      </code>
    </td>
    
    <td>
      Expired card. Not retried.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        4000000000009995
      </code>
    </td>
    
    <td>
      Insufficient funds. Retried, so it runs your dunning schedule.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        4000000000003155
      </code>
    </td>
    
    <td>
      Asks for 3-D Secure authentication.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        4000000000000341
      </code>
    </td>
    
    <td>
      Saves, then fails every charge.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        4000000000005126
      </code>
    </td>
    
    <td>
      Succeeds, then fails later as a reversal.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        4000000000000077
      </code>
    </td>
    
    <td>
      Times out. The outcome stays unknown until reconciliation.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        4000000000000101
      </code>
    </td>
    
    <td>
      Accepted and still in progress. Settles only by webhook.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        4000000000002008
      </code>
    </td>
    
    <td>
      Fails on the first attempt, succeeds on the next.
    </td>
  </tr>
</tbody>
</table>

Three widely used test numbers work as aliases: `4111111111111111` succeeds,
`4005519200000004` is insufficient funds, and `4556761029983886` asks for 3-D Secure. Any other
number succeeds.

<tip title="Test the failures, not only the success">

`4242…` proves the happy path. The interesting bugs are in the other rows: a late failure
reopening a paid invoice, a timeout that must not charge twice, a 3-D Secure challenge with no
buyer present.

</tip>

The test gateway sends its own signed asynchronous webhooks back to the engine, so the settle and
reverse paths run for real. To deliver the pending ones now instead of waiting:

<endpoint method="POST" path="/v1/tmtest/advance">



</endpoint>

A live key gets `404`.

## Fast-forward the clock

Most of subscription billing happens over months. In a test business, open **Time Travel** in
the dashboard: start a simulated clock, then move it forward. Everything due in that interval runs
— trial ends, renewals, invoices, collection and dunning retries. Stop it to return to real time.
Stopping deletes the business's test customers and transactions by default. The catalog and
settings stay.

Time Travel is a dashboard tool. Its endpoints need the dashboard's own credential, so an
integration key gets `403`. You can read where the clock is with any test key:

<endpoint method="GET" path="/v1/businesses/{biz}/time_travel">



</endpoint>

## Fill a test business with sample data

<endpoint method="POST" path="/v1/businesses/{biz}/sample_data">



</endpoint>

<endpoint method="DELETE" path="/v1/businesses/{biz}/sample_data">



</endpoint>

Creates a plausible catalog, customers and subscription history, so you can see how a screen or a
report looks with data in it. Test businesses only (`400` on a live one).

## Test mode limits

On the hosted service, a test business holds at most **1,000 customers** and **1,000
subscriptions**. Every customer counts, archived ones too. Every subscription counts, cancelled
ones too, until you delete it. Live businesses have no such limits. On a self-hosted
installation there is no limit unless you set `TEST_BUSINESS_CUSTOMER_LIMIT` or
`TEST_BUSINESS_SUBSCRIPTION_LIMIT` (`0` = no limit).

<endpoint method="GET" path="/v1/businesses/{biz}/test_limits">



</endpoint>

Returns `used` and `limit` for `customers` and `subscriptions`. At the limit, a create answers
`400`:

```json
{
  "error": {
    "type": "invalid_request_error",
    "code": "test_business_limit_reached",
    "message": "We could not create the customer. This test business has reached its limit of 1,000 customers. Delete test data, or contact us to increase the limit."
  }
}
```

To make space, delete test data under **Settings → Transfer & Sample Data**, or stop Time Travel,
which deletes the test customers. To import more than the limit into test mode, contact us first.

## Move your catalog to live mode

Build and test your catalog in test mode, then copy it to live mode in the dashboard under
**Settings → Transfer & Sample Data**. A transfer copies configuration — catalog, coupons, tax
rates and settings, and on request the company profile and email sending — never customers or
money. It does not copy email templates, branding, or the source's invoice prefixes and checkout
URLs; set new prefixes in the transfer if the destination needs them.

Select **Check changes** first. The list shows every value the copy changes, from its value now
to its value after, with secrets masked, and filters them into new, replaced and left out. If a
section cannot be copied, the list says why and you can leave that section out. Two live
businesses can copy their test businesses in the same run, and **Past copies** lists every earlier
copy with its result.

A live destination is merge-only: the copy adds what is new and does not change what exists.
To also change its settings, company profile, email sending, numbering and tax profiles, an
owner or admin selects **Also update what is there** and types the business name to confirm. The
audit log records each value it changed. In the API this is `live_override` with the
`plan_digest` from `POST …/transfer_configurations/preview`.

Like Time Travel, Transfer spans both modes, so it is a dashboard tool: an integration key gets
`403`. An organization on the free plan can run it, because the transfer starts from the test business.

## Go live

1. On the hosted service, check that your plan covers what you bill each month. The free plan
is free while you make less than [the Free plan's monthly limit](https://twominutebilling.com/pricing). Change plan in **Settings → Billing**.
2. Connect a live payment gateway to the live business.
3. Copy your catalog to live mode with **Transfer**.
4. Create a `sk_live_…` key and point your integration at the live business id.

## Related

- [Test with Time Travel in the dashboard](https://twominutebilling.com/help/guides/test-with-time-travel)
- [API keys and the mode check](https://twominutebilling.com/help/developers/api-essentials/authentication)
- [Go live from the dashboard](https://twominutebilling.com/help/getting-started/go-live)


## Sitemap

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