Skip to main content

Billing

relay accounts on the prepaid credit billing model purchase screening credits in advance. Each completed screening report draws down the account's credit balance. This page explains how the prepaid model affects SDK behavior and how your integration should handle the balance error the SDK surfaces when credits are exhausted.

For a plain-language overview, see Billing: What's Changing.

Who this applies to

This page applies only to accounts on the prepaid credit model. Accounts billed per transaction through Stripe Connect are unaffected — nothing on this page changes their SDK behavior.

How the prepaid model affects the SDK

Under the prepaid model, your relay account holds a credit balance that is consumed as screening reports are completed. While your balance is positive, the SDK behaves exactly as documented elsewhere — there are no extra steps, options, or callbacks to configure.

When your balance reaches $0, access to individual reports is paused:

  • Mounting the report view for a specific report returns a PAYMENT_REQUIRED error instead of rendering the report.
  • The embedded view displays a billing-specific message to the viewer.
  • The error is delivered to your host page through the onError callback so your application can react programmatically.

The reports view (the list of accessible reports) is not gated by balance — it always renders normally regardless of credit balance. The balance check only applies when opening a specific report via the report view.

Service resumes automatically as soon as credits are added to the account. No SDK re-initialization is required — the next mount succeeds once the balance is restored.

PAYMENT_REQUIRED is also used for an unrelated, per-report condition

The report view returns the same PAYMENT_REQUIRED code when the specific renter being screened hasn't completed their own per-transaction Stripe Checkout payment for that report — this has nothing to do with your account's prepaid credit balance. The two causes are distinguishable only by the error's message text (see the table below); the fix for the renter-payment case is the renter completing payment, not a credit top-up. See Error Codes for both message strings.

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"
messagestring"Your credit balance is $0. Please purchase credits to resume service." for the balance case, or "Payment is required before the report can be accessed." for the per-report renter-payment case (see warning above) — both subject to change, but currently the only way to tell the two causes apart
recoverablebooleanfalse in both cases — for the balance case, retrying will not succeed until credits are added; for the renter-payment case, the report becomes accessible once that renter pays, not on retry
await sdk.mount("#report-container", {
view: "report",
report: { id: reportId },
onError: (error) => {
if (error.code === "PAYMENT_REQUIRED") {
// Do NOT retry in either case — see the warning above for why this
// code covers two unrelated causes. There is no separate code for
// them today, so branch on `message` if you need to route them
// differently.
if (error.message.includes("credit balance")) {
// Your account's prepaid credit balance is exhausted.
notifyBillingOwner("relay credit balance exhausted");
showBillingNotice();
} else {
// This specific renter hasn't completed their own Stripe Checkout
// payment for this report — notify the renter/ops team that owns
// that transaction, not billing. A credit top-up won't fix this.
notifyRenterPaymentIncomplete(reportId);
showRenterPaymentNotice();
}
return;
}

// Handle other errors as usual
console.error(`[${error.code}] ${error.message}`);
},
});

Underneath, the platform returned 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.

Treat PAYMENT_REQUIRED as a billing signal, not a transient failure — but check message first, since the code covers two unrelated causes (see the warning above).

  • Do not retry either cause. Both are deterministic: the balance case won't change until credits are added, and the renter-payment case won't change until that renter pays. recoverable is false for both. Automatic retry loops add no value and are visible to relay as repeated block events.
  • Route each cause to the party who can fix it. For the balance case, the viewer usually can't fix the problem — notify your billing or operations contact. For the renter-payment case, your billing contact can't fix it either — the report unblocks only once that specific renter completes their Stripe Checkout payment, so route it to whoever manages that renter's transaction (e.g. a support/ops queue), not billing.
  • Keep the mount in place or unmount gracefully. The embedded view renders its own message for either cause. If you prefer to show your own UI, unmount the view and render a notice in your application.
  • Resume normally once resolved. Once credits are added (balance case) or the renter pays (renter-payment case), simply mount again — no special recovery path is needed.

Managing credits and recharges

Credit balances, usage history, and recharges are managed outside the SDK:

  • Self-service: manage credits and configure automatic recharges in your relay billing portal.
  • Assisted: contact your relay account manager or integration support to arrange a credit purchase.

Accounts can also enable low-balance email alerts and automatic recharge so the balance never reaches $0 in normal operation. If you need help accessing your billing portal, contact integration support.

Availability

Billing behavior is introduced in SDK v0.9.0. Earlier SDK versions render a generic error inside the embedded view when the balance is exhausted and do not deliver PAYMENT_REQUIRED to onError. See What's New for the effective date.

Next Steps