Billing Technical Addendum
A concise technical reference on relay's prepaid credit billing model for engineering teams with Embedded SDK integrations. For the complete billing reference, see the Billing guide. For a plain-language overview, see Billing: What's Changing.
Summary
- Accounts on the prepaid credit model purchase screening credits in advance; completed screening reports draw down the balance.
- When an account's credit balance is exhausted, the SDK delivers a typed
PAYMENT_REQUIREDerror to youronErrorcallback until credits are added. - No SDK upgrade is required to be blocked correctly — the balance gate is backend-enforced. An SDK upgrade is required only to receive the typed error described below; see Minimum version.
PAYMENT_REQUIREDis a billing signal, not a transient error — do not retry. The result is deterministic until the balance is restored.PAYMENT_REQUIREDis also returned, unmodified, for an unrelated per-report condition: the specific renter being screened hasn't completed their own Stripe Checkout payment. Distinguish the two only bymessagetext — see Distinguishing the twoPAYMENT_REQUIREDcauses.
The balance error
When a report request is blocked for insufficient credits, the SDK invokes your onError callback with an SdkError object:
| Property | Type | Value |
|---|---|---|
code | string | "PAYMENT_REQUIRED" |
message | string | Distinguishes the two causes below (subject to change) — no separate code exists for them yet |
recoverable | boolean | false for both causes — retrying never succeeds; only the balance top-up or the renter's payment does |
onError: (error) => {
if (error.code === "PAYMENT_REQUIRED") {
// Do NOT retry in either case. There's no separate code for the two
// causes below, so branch on `message` to route them correctly.
if (error.message.includes("credit balance")) {
alertBillingOwner(); // Account's prepaid credit balance is exhausted.
} else {
alertRenterPaymentIncomplete(); // This renter hasn't paid for this report.
}
return;
}
}
Underneath, the platform returns an HTTP 402 Payment Required to the embedded view. The SDK translates this into the callback above — your host page never needs to inspect HTTP responses directly.
Distinguishing the two PAYMENT_REQUIRED causes
The report view's PAYMENT_REQUIRED code is overloaded across two unrelated HTTP 402 conditions, both with recoverable: false:
| Cause | message | Fix |
|---|---|---|
| TSP account's prepaid credit balance is exhausted | "Your credit balance is $0. Please purchase credits to resume service." | Add credits to the account |
| This specific renter hasn't completed their per-transaction Stripe Checkout payment | "Payment is required before the report can be accessed." | The renter completes payment — not a credit top-up |
There is currently no separate code for the two — match on message if your integration needs to route them differently.
Minimum version
The typed PAYMENT_REQUIRED error is delivered to onError starting in SDK v0.9.0. On earlier versions, the embedded view renders a generic, non-typed error message in place of the report and does not invoke onError — hosts on pre-v0.9.0 SDKs cannot detect the balance condition programmatically and must upgrade to do so.
Recommended behavior:
- Do not retry. Unlike other error codes,
PAYMENT_REQUIREDreturns an identical result on every attempt until its cause is resolved — a credit top-up for the balance cause, or the renter's payment for the renter-payment cause. Exclude it from any automatic retry or backoff logic. - Route by
message, not justcode. For the balance cause, alert whoever manages your relay credits. For the renter-payment cause, alerting that same person won't help — they can't complete another person's Stripe Checkout payment for them; route it to whoever owns that renter's transaction instead. Neither case should be surfaced to the report viewer as a retry button. - Resume without special recovery. Once the relevant cause is resolved, simply mount again — no special recovery path is needed.
No SDK changes required beyond the version above
This billing change introduces no new required options, mount parameters, or breaking changes. Integrations already on SDK v0.9.0+ that handle onError defensively will continue to work without modification. The only recommended (optional) improvement is explicit PAYMENT_REQUIRED handling as shown above, so an exhausted balance surfaces as a clear billing alert rather than a generic failure.
Separation of concerns
relay's billing relationship is with your organization, not with your customers:
- Prepaid credits cover your organization's usage of relay screening services.
- Nothing about this model touches your end-customer billing. How — or whether — you charge your own customers for screenings is entirely your business and is unaffected by this change.
- Consumer-facing payment flows that are part of the screening product (e.g., consumer-paid screening via Stripe Checkout) are a separate mechanism and are not altered by prepaid credits.
Transition period
Existing TSPs on the Stripe Connect / MOR billing model continue to operate that integration without interruption during the transition to prepaid credit billing. There is no hard cutover for existing accounts — the existing per-transaction Stripe Connect flow and the new prepaid credit model run in parallel until an account completes billing setup and migrates. Your existing SDK integration is unaffected until you migrate.
Managing credits
Credit balances, usage, low-balance alerts, and automatic recharges are managed through your relay billing portal, or with the help of your account manager / integration support. If you need help accessing your billing portal, contact integration support.
Questions? Contact integration support if you have questions about a PAYMENT_REQUIRED error your integration received.