Checkout and portal sessions
Your API key can charge every card in the organization, so keep it on your server. Both surfaces here work the same way: you create a single-use, short-lived session from your server and send your buyer a link.
Create a hosted checkout session
/v1/businesses/{biz}/checkout_sessionscurl -X POST $TMBILLING_URL/v1/businesses/$BIZ/checkout_sessions \
-H "Authorization: Bearer $TMBILLING_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" -H "Content-Type: application/json" \
-d '{
"items": [{ "price": "pro-monthly-usd", "quantity": 1 }],
"coupons": ["WELCOME20"]
}'
You get back a URL of the form /checkout/s/<token>. Send your buyer there. They enter their
details and card, and tmbilling creates the subscription when they finish.
Select a mode
| Mode | What it does |
|---|---|
create (default) | Subscribes a new customer to the items. Pass price and quantity as shorthand for a single-item items array. |
change | Applies the items to an existing subscription when the buyer finishes — a plan swap, a quantity change, an add-on. Requires subscription. tmbilling pins the customer to that subscription's owner when you create the session, so the buyer cannot reassign it. |
tmbilling validates items and coupons when you create the session, not when the buyer finishes. A
bad price or coupon gives you a 404 now instead of breaking the page halfway through payment.
/v1/businesses/{biz}/checkout_sessions/{id}/revokeRevoke a link that leaked.
Create a customer portal session
Give an existing customer a place to manage their own billing:
/v1/businesses/{biz}/customers/{cus}/portal_sessionscurl -X POST $TMBILLING_URL/v1/businesses/$BIZ/customers/$CUS/portal_sessions \
-H "Authorization: Bearer $TMBILLING_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" -H "Content-Type: application/json" \
-d '{}'
You get back a /portal/s/<token> link. Behind it your customer manages payment methods and
billing details, so your support team never handles a card.
/v1/businesses/{biz}/customers/{cus}/portal_sessions/{id}/revokeHandle the link correctly
The session has its own, later expiry. The one hour limits how long the link works, not how long your customer can stay on the page.
Select the right surface
| Situation | Use |
|---|---|
| A new buyer subscribing | Checkout, mode: create |
| An existing customer changing plan, confirming payment themselves | Checkout, mode: change |
| An existing customer updating a card | Portal |
| Changing a plan with no buyer interaction | Neither — call change directly |
Brand both surfaces
tmbilling renders both with your business's logo, icon and brand colour, taken from the business record. Your buyer sees your company, so set these before you send anyone a link:
/v1/businesses/{biz}/v1/businesses/{biz}/brand_imagesConfirm the outcome from the webhook
Don't rely on your buyer landing back on the return URL. They close tabs, and networks fail at the worst moment.
Treat the webhook as the source of truth: subscription_created for a create session, and the
relevant subscription and invoice events for a change. See Webhooks.
Related
One-time purchases
Sell something once through a hosted checkout, a shareable payment link or your public pricing page, or charge a saved card for a one-off amount from the API.
Failed payments
Set the retry schedule for declined cards, see what a failed renewal looks like, recover it when the customer adds a card, and decide what happens at the end.