Recurring charges

Once you have a payment_token, each billing period is a normal create_payment_session call with the token attached. The customer isn’t present and there’s no redirect—Truemed charges the card on file.

Your system decides when to charge. Truemed decides whether the charge is allowed.

Charge a stored token

Pass payment_token instead of collecting customer details. Amounts are integers in cents.

$curl https://api.truemed.com/payments/v1/create_payment_session \
> -X POST \
> -H "Content-Type: application/json" \
> -H "x-truemed-api-key: $TRUEMED_API_KEY" \
> -d '{
> "payment_token": "dev_tm_token_8a1f0c2e-77b4-4f0a-9c31-2f5c7a9d4e10",
> "total_amount": 4200,
> "success_url": "https://example.com/account/orders",
> "failure_url": "https://example.com/account/orders",
> "idempotency_key": "sub_12345_period_7",
> "metadata": "subscription_12345",
> "order_items": [
> {
> "name": "Monthly B12",
> "quantity": 1,
> "sku": "b12-monthly",
> "price": 4200,
> "amount_details": {}
> }
> ],
> "amount_details": {}
> }'
1{
2 "id": "e7d2b810-4a3c-4c11-9f5e-0c8a1b2d3e4f"
3}

A 200 means the charge was accepted, not that funds are secured. Use a distinct idempotency_key per billing period so a retried request doesn’t double-charge.

order_items must match what you’re actually billing for on this charge. Unlike a normal card payment, where only the amount matters, Truemed re-checks eligibility against the items on every charge. The customer’s LMN covers specific items—anything outside it is blocked with a 422 and next_action: "TakeHealthSurvey", and the billing period fails.

This catches people out in two ways:

  • Reusing a hardcoded or stale order_items payload across billing periods. It works until the subscription changes, then silently starts failing.
  • Changing the subscription in your system without telling Truemed. Call update_payment_token at the moment items change, not at charge time—see Update a Subscription.

Fulfillment rules

Fulfill from the payment_session_complete webhook, exactly as with a one-time payment. A stored-token charge returns no redirect_url—the field appears only on a 422, where it’s where you send the customer to resolve the block.

StatusCustomer communicationFulfillment behavior
processingNothing, or “your order is being prepared”.Do not fulfill yet.
capturedConfirm the order is paid.Fulfill the order.
rejectedTell the customer this period’s payment couldn’t be completed.Don’t fulfill. Ask for another payment method or retry next period.

Make fulfillment idempotent—webhooks are at-least-once, so the same status can arrive more than once. See Webhooks and Fulfillment for the full handler checklist.

Prevent failures before they happen

Truemed does not warn you before a token stops working, and does not email your customers. Catching expirations ahead of the charge is your job, and it’s the difference between a customer who renews and one who churns.

  • Store expiration dates on every token. Keep lmn_expires_at and the card expiration from retrieve_payment_token alongside your subscription record.
  • Run a daily expiration sweep. Query list_payment_token with lmn_expires_before and card_expires_before set about 30 days out. lmn_expires_before only returns LMNs expiring between today and that date—already-lapsed ones are excluded, which is why you keep your own copy of lmn_expires_at. See Partner Operations.
  • Prompt those customers before their next charge. Email them a link generated with update_payment_token, escalating as the date gets closer. For an expiring card send update_card_info: true; for an expiring LMN send renew_eligibility: true with the subscription’s current order_items, or the response comes back next_action: "None" with nothing to link to. See Renew eligibility before the LMN expires.
  • Call update_payment_token whenever subscription items change—at the moment of the change, not at charge time. A cart change that falls outside the existing LMN blocks the next charge. See Update a Subscription.

When a charge fails

A blocked charge returns 422 with a next_action telling you what the customer has to do, and a redirect_url to send them to. The customer isn’t present, so you’ll relay this by email and wait for payment_token_updated before charging again.

Token Lifecycle covers every failure cause, the recovery loop, and suggested customer messaging.

Next steps