Skip to main content

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_REQUIRED error to your onError callback 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_REQUIRED is a billing signal, not a transient error — do not retry. The result is deterministic until the balance is restored.
  • PAYMENT_REQUIRED is 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 by message text — see Distinguishing the two PAYMENT_REQUIRED causes.

The balance error

When a report request is blocked for insufficient credits, the SDK invokes your onError callback with an SdkError object:

PropertyTypeValue
codestring"PAYMENT_REQUIRED"
messagestringDistinguishes the two causes below (subject to change) — no separate code exists for them yet
recoverablebooleanfalse 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:

CausemessageFix
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:

  1. Do not retry. Unlike other error codes, PAYMENT_REQUIRED returns 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.
  2. Route by message, not just code. 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.
  3. 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.