The credit-history module renders a credit_history step in the verification journey: the applicant authorizes a credit report, accounts for their address history, confirms their identity details, then submits. Every screen renders inside a hosted frame served by Checktiv, so your page never receives an applicant’s address history, previous names, or national identifier.
The step is billable and produces a consumer report under the Fair Credit Reporting Act. Read Credit history for what the operator configures and Background-check decisions (FCRA) for what a decline on it obliges them to do.
Register the module
Section titled “Register the module”import '@checktiv/sdk-web/credit-history'; // registers the credit-history module (side-effect import)Like the other managed modules this is a side-effect import: it registers the module so the substrate can resolve it when the session declares it. Keep the import even though nothing reads its value, and do not let a bundler tree-shake it away. Without it, a session that declares the module fails the mount with sdk_load_failed and an actionable message rather than a blank frame.
There is no stylesheet to link. Every screen renders in the hosted frame, and the module injects its own scoped styles for the small amount of chrome it adds to your page.
A credit workflow always needs the collect step satisfied first
Section titled “A credit workflow always needs the collect step satisfied first”This is the single thing most likely to make a correct integration look broken, so handle it before you write anything else.
The check declares a collect_user_info step and a date of birth as required inputs, so a workflow template holding a credit step always holds a collect step ahead of it. The SDK does not render a collect step. A credit workflow therefore opens on a step the SDK cannot render unless you satisfy it first, and the mount stops with sdk_load_failed.
Two resolutions work, and both are covered at Embedded-workflow renderability:
- Seed the applicant at create. Send the inline
applicantfields on the session create, includingdateOfBirth. This is the path the example below takes. - Satisfy the step from your own form. Call
collectUserInfo({ session })before you mount. See Collect user info.
Send the name in parts. familyName plus a givenNames array is the accepted shape; a single typed full-name line is rejected with 422 name_components_required. Nothing can split a verbatim full name into components safely, and guessing which words are the surname orders a credit file on a different person.
End to end
Section titled “End to end”Your backend creates the session and returns the durable clientToken. The secret key never leaves the server.
// GET /kyc/credit-session (your backend)import { sessions, regionToApiBase } from '@checktiv/sdk-web';
app.get('/kyc/credit-session', async (req, res) => { const session = await sessions.create( { templateId: 'wt_01abc', // a workflow template holding a credit_history step applicant: { externalId: req.user.id, // Seeds the collect step so the journey opens on the credit screens. // The name goes in parts; a single full-name line is rejected. familyName: req.user.familyName, givenNames: req.user.givenNames, // e.g. ['Jose', 'Maria'] dateOfBirth: req.user.dateOfBirth, // required: the report cannot be ordered without one email: req.user.email, }, }, { apiBase: regionToApiBase('us'), // credit history runs in the US region secretKey: process.env.CHECKTIV_SECRET_KEY, // ah_sk_* - never in the browser idempotencyKey: req.user.id, }, ); res.json({ clientToken: session.clientToken });});Your page mounts the journey. This compiles under strict with no cast: isChecktivCreditHistoryEvent is the exported runtime guard that narrows the forward-open SDK event union to the closed credit union, so the switch below sees a discriminated union rather than a widened type string.
import { mount } from '@checktiv/sdk-web';import '@checktiv/sdk-web/credit-history'; // registers the module (side-effect import)import { isChecktivCreditHistoryEvent } from '@checktiv/sdk-web/credit-history';
const handle = mount(document.getElementById('checktiv')!, { publishableKey: 'ah_pk_us_live_...', // safe to expose - no scopes fetchToken: () => fetch('/kyc/credit-session') .then((res) => res.json()) .then((data: { clientToken: string }) => data.clientToken), onEvent: (event) => { if (!isChecktivCreditHistoryEvent(event)) return; switch (event.type) { case 'checktiv.credit_history.ready': hideYourSpinner(); return; case 'checktiv.credit_history.screen': // Funnel instrumentation only: a closed screen name and its position. trackStep(event.screen, event.index, event.total); return; case 'checktiv.credit_history.reconnecting': // Recovery is in progress. Paint a notice; do not treat it as a failure. showNotice('Reconnecting...'); return; case 'checktiv.credit_history.submitted': // Terminal for the step, NOT a verdict. Advance the journey. window.location.reload(); return; case 'checktiv.credit_history.declined': case 'checktiv.credit_history.skipped': // Deliberate non-submissions. The frame renders its own explanation. // Do NOT reload: a reload replaces that explanation with the form the // applicant just chose to leave. return; case 'checktiv.credit_history.error': // `error.recovery` names the concrete next step. Render it. showError(event.error); return; } },});Do not exhaustively switch on the outer event.type without the guard. The SDK-wide event union is forward-open and a later release can add a type without a major version bump. See Versioning.
Events
Section titled “Events”The module emits seven events and the union is closed.
| Event type | Payload | Meaning |
|---|---|---|
checktiv.credit_history.ready |
none | The frame started and is initialized. The applicant can begin. |
checktiv.credit_history.screen |
screen, index, total |
The applicant moved to, or resumed on, a screen. A closed screen name and its position, never a field value. |
checktiv.credit_history.reconnecting |
reason |
The frame’s context is being re-established. Not an error: recovery is in progress. |
checktiv.credit_history.submitted |
sessionId |
The step was submitted. Terminal for the step, not a verdict. |
checktiv.credit_history.declined |
none | The applicant did not authorize the report. The journey blocks. |
checktiv.credit_history.skipped |
reason |
The step ended in the form with no report ordered and no charge. |
checktiv.credit_history.error |
error: ChecktivError |
A failure the applicant cannot get past unaided. |
screen is one of consent, address_history, identity_and_title, review, in that order. reason on reconnecting is bootstrap_timeout or credential_expired. reason on skipped is unsupported_jurisdiction.
submitted is a completion, never a verdict. No outcome, score, or finding rides it, and none ever will: the answers go to Checktiv under the frame’s own credential and are never echoed to your page. The verification’s outcome reaches your server on a signed kyc.session.* webhook. See Verdict and webhooks.
The check’s own result is read from the verification, not from the webhook body: GET /v1/sessions/{id} carries a check_results array whose credit_history entry holds the outcome, the file status, the reasons the check needs a human, and the summary counts. See Read the credit result from the session for the fields, and for the ones that are deliberately absent.
What each outcome means, and which ones are not errors
Section titled “What each outcome means, and which ones are not errors”Three of the states below are deliberately not errors. A host that renders a generic failure on the declined state turns a designed recovery into a dead end.
| State | How it arrives | Is it an error? | What your page does |
|---|---|---|---|
| Consent declined | checktiv.credit_history.declined |
No | Nothing visual. The frame renders its own explanation and the applicant’s next step. Do not reload and do not paint a second copy of it. Record the event on your side if you want to know why a journey stopped. |
| Unsupported jurisdiction | checktiv.credit_history.skipped with reason: 'unsupported_jurisdiction' |
No | Nothing visual, for the same reason. The frame’s notice carries the control that takes the applicant back to the rest of the verification. |
| Reconnecting | checktiv.credit_history.reconnecting |
No | Paint a transient notice. The module is re-establishing the frame’s context and the applicant’s earlier screens are preserved. If recovery fails, an error follows. |
| Submitted | checktiv.credit_history.submitted |
No | Reload or navigate so the substrate resolves the next step. The report has not come back and no verdict is available here. |
| A failure | checktiv.credit_history.error |
Yes | Render error.message and the next step in error.recovery. The frame paints its own notice too; this event is what lets you observe and instrument the failure. |
On a decline the journey blocks: no report is ordered, nothing is charged, and the step is not submitted. The invite link stays valid and the session stays resumable, so this is a deliberate non-submission rather than a terminal state, and the applicant can return to the step and authorize. The session does not complete on its own in the meantime, so a host that treats the decline as the end of the journey is ahead of the verification.
On an unsupported jurisdiction the step ends in the form, before a national identifier is ever requested, with no report ordered and nothing charged. What the check lands is the operator’s choice: held for review, or recorded as passed with the reason shown to the reviewer.
Test mode
Section titled “Test mode”A test-mode verification orders no report and is charged nothing. The step still renders every screen, emits every event, and writes a result, so it is the right place to build against.
The Expected outcome value you choose when you create the verification picks which recorded file the step replays. See Forcing an outcome in test mode for the four values and where you enter each one.
| Value | The step replays | The check resolves to |
|---|---|---|
pass |
A clean file with a good score, returned as clear. | Passed |
review and doc_quality |
A lower-scoring file returned marked for review. | Held for review |
fail |
A file where no record matched, returned marked for review. | Held for review |
Read the next part before you write an assertion against it. A recorded file carries the summary of the report but not the account-by-account detail, which is a second read this platform does not make in test mode. Adverse records are found in that detail, so a replayed report produces no findings at all, on any of the four values. The three values that hold for review get there another way: the recorded report was returned marked for review, and a report marked for review is held for a person regardless of what is on it. The reviewer is shown that as the reason.
So a test-mode run exercises the outcome and the reason a reviewer reads, but not the itemized findings underneath them. An adverse credit account driving a verification to review is live-mode behavior, and screening rules are what decide the rest there.
Two of the step’s own states do not depend on the value at all, because both are settled before any report is ordered: an applicant who does not authorize the report still produces checktiv.credit_history.declined, and an applicant outside a supported country still produces checktiv.credit_history.skipped.
Error codes
Section titled “Error codes”checktiv.credit_history.error carries a ChecktivError. The module reports four codes, all of them from the shared journey taxonomy:
error.code |
What happened |
|---|---|
sdk_load_failed |
The credit form could not be loaded or could not start. |
session_expired |
The step could not be set up or restarted for this session. |
submit_failed |
The submit did not land. Nothing the applicant entered has been sent. |
origin_not_allowed |
The frame could not be restarted safely. |
Every one carries a message naming a concrete next step, so there is no state your page has to invent copy for. See Error reference for the full journey set and keep a default branch: a later release can add a code.
Where the check runs
Section titled “Where the check runs”Two independent conditions decide whether a report is ordered, and neither implies the other:
- The organization’s region. Credit history runs on US-region organizations. An EU-region organization cannot author the step at all, so a session will never declare the module.
- The applicant’s country. Reports can be ordered for applicants in the United States and Canada. Any other country ends the step with
skipped, in the form, with nothing charged.
See Where is my data hosted? for the full picture.