The first order
The charge waits for the practitioner’s decision
A Truemed payment token is what lets you charge a customer through Truemed, and both stored cards live inside it. Its HSA/FSA side is unlocked only after an independent licensed practitioner has reviewed that customer’s LMN and approved it. Until then, nothing may touch the benefits card. The token is minted once the LMN is decided. On an approval it carries coverage. On a rejection it still arrives, covering nothing, so every charge routes to the regular card.
We should be straight with you about what this is: a limitation of how Truemed tokens work today. A token is issued once per customer and carries their clinical decision with it, so we cannot hand you one before that decision exists. The reason we hold the line is compliance: no HSA/FSA amount may be charged, held, or promised to a specific customer before a practitioner has approved the LMN. The consequence lands on you, in the shape of a first order that waits on us.
So instead of approving earlier, the charge happens later. On the first order the charge step is
delayed until after you have received the token. The customer places the order and you hold it; the
charge happens once payment_token.updated arrives. Nobody waits on a screen.
That webhook is the go signal. It is how you learn the token exists, and only once it has landed do you
call create_payment_session for that box. It arrives on an approval and on a rejection alike, so your
fulfilment worker can treat it as an unconditional go signal. Every order after the first already has a
token, so nothing waits at all.
This is the one thing the flow asks of your order pipeline: the customer places their first order before there is a way to charge it, and you take payment later, when you are ready to ship.
Holding the first order is the mechanism that keeps the clinical guarantee, meaning no HSA/FSA hold before a practitioner approves, without making the customer wait on a screen or sit through a second checkout. If your pipeline cannot hold an unpaid order that way, raise it with your Truemed contact before you build.
Clinical review runs while you prepare the order: the customer places the box, you hold it for fulfilment, and the decision lands during that window. Your Truemed contact can share current turnaround figures so you can size the window against your own lead time.
How the first order flows
Step 5 is the only step that waits on Truemed. Review runs while you prepare the order, and your Truemed contact can share current turnaround.
How you hear about the decision
Approval and rejection both deliver the token. payment_token.updated arrives either way, so your
fulfilment worker waits on one event and the charge path stays single. The two branches are told apart
on the payload itself: alongside payment_token, payment_methods, lmn_expires_at,
provision_token_request_id, metadata and the two payment-session ids, it carries
eligibility_status, the same vocabulary the eligibility read answers with. A first order therefore
costs you a single webhook. The read stays authoritative for which items are covered, and it is what
you call to badge a menu.
- Approved gives you
payment_token.updatedwitheligibility_status: "approved", carrying the token with the HSA/FSA side live andlmn_expires_atset to a future date. Step 7 unblocks, and the read names the covered items when you need them. - Rejected gives you the same
payment_token.updatedwitheligibility_status: "rejected", zero HSA/FSA coverage andlmn_expires_at: null. The held first order charges fully to the regular card and the box ships. That is the cue to explain that HSA/FSA did not apply, suppress requalification prompts, and make cancelling easy. The same answer is available on the provision-request read if you would rather pull it than rely on a delivery.
Two smaller things on that payload. lmn_expires_at tracks the outcome without replacing it: it is
non-null exactly when the customer has live HSA/FSA coverage, which makes rejected and expired
indistinguishable through that field alone. And payment_methods comes back carrying only the regular
card on a rejection, which is a payment-instrument fact rather than a clinical one, so branch on
eligibility_status rather than inferring from the card list. Neither field says which items are
covered, so anything that badges a menu still needs the read.
Subscribing is self-serve. In the Truemed merchant dashboard under Developers → Webhooks: add
your endpoint URL, tick payment_token.updated, the one event this integration needs, and copy the
signing secret it issues. The same screen carries a per-endpoint delivery log, which is the quickest way
to confirm your handler is receiving and acknowledging deliveries. No ticket to Truemed required.
Truemed emails the customer the rejection notice directly, so your messaging only needs to handle payment rather than the clinical explanation.
Push, pull, or both. The shape this guide recommends is the webhook on its own: wait for
payment_token.updated and branch on eligibility_status. If you would rather not depend on a delivery
at all, poll the provision-request read
on a schedule instead: pending means wait and ship, approved means coverage is live, and rejected
means the token is on its way with zero coverage, so ship on the regular card. Most integrations will
want both: the webhook to unblock the charge, and the read to badge the menu and to recover from a
delivery that went missing.
(Retrieve Provision Token Request
substitutes for neither: it returns payment_token: null for both pending and rejected.)
Badging the first menu before the LMN is decided
The first order has a gap that later orders do not: the customer picks their first box minutes after finishing the health survey, but the token they would be badged against does not exist until the practitioner decides. Without a second way to read eligibility, that first menu would carry no badges.
The survey outcome itself does not wait on the practitioner. The items the customer pre-qualified for
are known the instant the frame reports the survey is done, and only the clinical sign-off is pending.
So the eligibility read has a second key for exactly this window:
by provision request,
GET /api/v1/eligibility/provision_request/{provision_token_request_id}. It has the same response shape
as the token read and is keyed on the provision-request id you persisted in step 1, so badging the
first menu costs you nothing new. While the LMN is with the practitioner it returns
eligibility_status: "pending" with the survey-predicted items and lmn_expires_at: null. The full
request and response are in
Step 4 of API calls.
- Provisional means pending clinical review, and the display should say so. Nothing is promised until the LMN is approved, and the first charge waits for the token in either branch.
- If the practitioner declines, the badges come down and nothing breaks.
eligibility_statuscomes backrejected, the token still arrives, and the held order charges fully to the regular card (step 6a). - This read is also your polling fallback.
pendingmeans wait and ship on the webhook;rejectedmeans the badges come down and the box still ships on the regular card.