Polar billing integrations do not start at checkout.
The first real question is usually simpler:
Can my app create the customer and product records it will depend on later?
If that part is shaky, checkout and subscription handling get harder to trust. You end up debugging billing logic when the actual bug was earlier: the customer ID did not persist, the product did not show up in the list call, or your app stored an internal user ID that never made it into the billing system.
The boring part is the important part
Polar's API has the objects you expect in a modern billing system:
- customers
- products
- checkouts
- orders
- subscriptions
- benefits
- webhooks
The checkout flow is the part everyone thinks about. But checkout depends on earlier state.
For example, a product has to exist before you can sell it. A customer has to map back to your own user model before you can reconcile access later. Polar supports this through fields like external_id / external customer IDs, which are exactly the sort of small integration detail that becomes painful if you do not test it early.
The first workflow to prove
The first Polar workflow I want to trust is not payment. It is state.
POST /v1/customers/
→ create a customer with email, name, external_id
→ customer.created webhook fires
GET /v1/customers/{id}
→ read the same customer back
→ verify the ID and external_id survived
And for products:
POST /v1/products/
→ create a product with price data
→ product.created webhook fires
GET /v1/products/
→ verify the product appears in the catalog list
That is not a flashy workflow. It is the foundation.
If your app cannot round-trip customer and product state, you do not have a billing integration yet. You have a few API calls that happened to return 201.
Why mocks are weak here
A static mock can return:
{ "id": "cus_123", "email": "test-buyer@example.com" }
But the next request is where the truth shows up.
If you call GET /v1/customers/cus_123, does the mock know about the customer you just created? Does it preserve your external_id? Does the list endpoint include the product you created one step earlier?
Most mocks do not. Every request lives alone.
For billing APIs, that is a bad tradeoff because the whole integration is stateful. Customers, products, checkouts, orders, subscriptions, and benefits are related. Your code is not just calling endpoints. It is moving through a lifecycle.
Testing Polar in FetchSandbox
We onboarded Polar into FetchSandbox today.
The current sandbox includes:
- Polar OpenAPI spec support
- seeded customers, products, and subscriptions
- stateful customer creation and read-back
- stateful product creation and list verification
- webhook events like
customer.createdandproduct.created - subscription states like
active,past_due,canceled,revoked,trialing
You can run the customer workflow without a Polar token, without creating a Polar organization, and without touching real payment state:
POST /v1/customers/
GET /v1/customers/{id}
Or test product creation:
POST /v1/products/
GET /v1/products/
The useful part is not that the first call returns a successful response. The useful part is that the second call can prove the first one changed state.
What this catches early
This kind of preflight catches boring bugs before they become billing bugs:
- your app loses the billing customer ID
-
external_iddoes not map cleanly back to your user - product creation succeeds but your catalog query does not find it
- your webhook handler assumes a customer exists before the create event is processed
- your tests only check status codes, not persisted state
None of these are dramatic. They are just the kind of bugs that waste an afternoon once checkout and subscriptions are already wired.
Where the real Polar sandbox still matters
This is not a replacement for testing against Polar's own sandbox before launch.
You still want the real environment for final payment behavior, account-specific configuration, hosted checkout, signatures, and anything that depends on Polar's production logic.
The point is earlier than that.
Before you do final validation, you should be able to prove your app understands the basic lifecycle:
- Create billing object
- Store returned ID
- Read it back
- React to the webhook
- Keep your local state aligned
That is the layer FetchSandbox is good at.
Try the Polar sandbox — no Polar token needed.
Curious how other teams test billing integrations before real payment flows. Do you start with the provider sandbox immediately, or do you preflight the API state first?
Top comments (0)