Migrate from the Autohost SDK and API
Checktiv replaces identity verification from Autohost. This guide is for product managers and developers who built on the Autohost SDK (AutohostSDK), the hosted Guest Portal, or the Autohost Data API (data.autohost.ai). It tells you what changes, what stays the same, and how to move each part of your integration.
Which parts apply to you
Section titled “Which parts apply to you”| You use | Read |
|---|---|
| Only an Autohost connection to Guesty, Hostaway, or Track | Integrations first. A Checktiv integration can replace your code. |
| The Autohost SDK in your applicant pages | Step 3 and Step 4 |
| The hosted Guest Portal, as a link or in an iframe | Step 3 and Replace an embedded Guest Portal |
The admin components (ReservationResults, SexOffenders) |
Step 5 |
| The Data API from your server | Step 6 and Step 7 |
| The reseller APIs, for many host accounts | Partners with many host accounts |
| You are a product manager | Overview, What changes for your team, and the checklist |
Overview
Section titled “Overview”Timeline
Section titled “Timeline”The Autohost SDK, the hosted Guest Portal, and the Autohost Data API reach end of life before October 2027. Plan to finish your migration by April 2027.
After the end-of-life date:
- The Autohost API hosts are turned off. Every call to the Autohost Data API and the Autohost SDK fails.
- Guest Portal links stop working, including links you already sent to applicants.
- Autohost sends no more webhooks.
Until that date, your Autohost integration keeps working. You can move to Checktiv at any time before it, and you can run both at the same time while you move.
What happens to your Autohost data
Section titled “What happens to your Autohost data”We copy your Autohost reservations and part of their verification data, including ID images, into your Checktiv organization. Each copied reservation becomes a verification with the decision Autohost recorded. The external_id of its applicant is the Autohost reservation id. See Link copied reservations to your bookings.
We do not copy verification reports or signed e-signature documents (PDFs). Download each report and signed document you must keep before the end-of-life date.
We copy your data into the US region. If your applicants’ data must stay in the EU, create your organization in the EU region. Then email support@autohost.ai before we copy your data, and name that organization.
What you get
Section titled “What you get”Checktiv covers most of the identity verification and screening checks that the Autohost SDK and Data API offered. The table in Map Autohost checks to Checktiv checks shows the Checktiv check to use in place of each one. You also get:
- US or EU data residency. You pick the region when you sign up. Your applicants’ data stays in that region.
- A test mode with predictable results. A test-mode key creates free, synthetic verifications. You choose whether each one passes or goes to review.
- Signed webhooks. Every delivery carries an HMAC signature and a stable event id. You can replay a delivery from the console.
- A workspace reviewer. Your staff approve or decline a verification inside your own admin dashboard. Each token carries only the capabilities you grant.
- Workflow templates. You configure the checks once, in the console or over the API, and reuse them by id.
- Types, React, and cross-device capture. The npm package ships TypeScript types and a React wrapper. An applicant on a desktop can move to a phone for document capture.
- Ready-made integrations for Guesty, Hostaway, and Track. See Integrations.
What is not part of Checktiv
Section titled “What is not part of Checktiv”Checktiv is an identity verification and screening platform. These Autohost features have no Checktiv equivalent:
| Autohost feature | What to do |
|---|---|
Security deposits, payment validation, damage waivers (GET /reservations/{id}/payments, POST /reservations/{id}/payment-event) |
Keep these in your own checkout. Checktiv does not take payments from applicants. |
Guest messaging (Stargate, GET /reservations/{id}/stargate, stargate_webhook_url) |
Send these messages from your own system. Checktiv can email the verification link: set send_invite: true. |
| Business rules that read the reservation details | Keep them on your server. Choose the workflow template before you create the verification. Screening rules cannot read your booking details. |
The details read from the ID document (identification) |
A verification does not return them over the API. To read the fields from ID images outside a verification, call POST /v1/id-verification. Your reviewers see the ID check in the workspace reviewer and the console. |
Loyalty segments (/loyalty/*, loyalty_segments) |
No equivalent. Remove these calls. |
Tenant eviction search (/tenant-evictions/*) |
No equivalent. Remove these calls. |
| Your own blocklist, social verification, authority reporting | No built-in equivalent. Keep this logic in your own system. To act on a list of known emails, add a screening rule on applicant.email with the in operator. |
Standalone lookups (/lookup/*, /validate/*, /predict/*, /fraud/analyze, /global-watchlist/*, /background-check/*) |
No standalone equivalent. Run screening inside a verification. See Map Autohost checks. |
What changes for your team
Section titled “What changes for your team”Some of your integration stays the same:
- Your decision logic. Your code still decides which bookings need a verification. Checktiv does not need your listings.
- Your tiers. If riskier bookings get more checks, keep that logic on your server. Create one workflow template per tier, then send the id of the template you chose.
- Your state management. You still store the verification id next to your booking, and you still update the booking when the result arrives.
Plan for this new work:
- A server route that starts the verification. The Autohost SDK started from a reservation id in the browser. Checktiv starts from your server, which returns a token to the browser. This route must check that the caller is the applicant for that booking.
- The template decides the steps. The workflow template decides the steps and their order. The SDK shows one step at a time. After each step, your page reloads or mounts the SDK again to show the next one. A progress bar you built around your own pages must change.
- Workflow templates. You create one template for each tier. A document the applicant signs belongs to a template, so different agreement text means a different template.
- Booking rules stay on your server. Screening rules in a template read the applicant, the check results, and the fraud signals. They cannot read the dates, the price, or the source of a booking.
- Translations. The Checktiv SDK does not translate its screens for you. You pass your own translated text, and any text you leave out shows in English. See Translations.
- A fraud-signal disclosure. Fraud signals start only after the applicant agrees to the disclosure you show.
- A new webhook receiver. It verifies a signature, reads one event type field, and fetches the verification.
- A server route for the admin reviewer. It mints a short-lived token pair for one staff member and one verification.
Migration checklist
Section titled “Migration checklist”- Find every place that uses Autohost.
- Set up your Checktiv organization: keys, workflow templates, and a webhook subscription.
- Start verifications on your server.
- Replace the Autohost SDK in your applicant pages.
- Replace the admin components.
- Change endpoints and fields.
- Rewrite your webhook receiver.
- Test each result in test mode.
- Move your bookings in stages, then remove Autohost.
Concepts that changed names
Section titled “Concepts that changed names”| Autohost | Checktiv |
|---|---|
| Reservation (the container for a verification request) | Session. The API resource is /v1/sessions and the object is verification_session. |
Guest (guest on the reservation) |
Applicant. Send it inline as applicant on the create. The inline applicant can complete the identity information step; an applicant_id cannot. |
Listing (listing_id, /listings) |
Not needed. Send the transaction details in metadata. See Map the create fields. |
| Guest Portal screens, risk colors, Screening Assistant | Workflow template. It lists the checks and their order. Its screening rules can send a verification to review. |
Guest Portal URL (guest_portal_url) |
Verification link (applicant_url). It opens the hosted journey. It cannot be shown in an iframe. |
| Custom Guest Portal domain | A custom domain for the verification link. |
Host decision (supervised) |
Reviewer decision. outcome is approved or declined, and decision_source is reviewer. |
API key (x-api-key header) |
Secret key (ah_sk_...) in the Authorization: Bearer header. |
SDK key (used on your server to mint the admin apiToken) |
Secret key. It mints the workspace token for the admin reviewer. |
| No key in the applicant pages | Publishable key (ah_pk_...). It is new, and it is safe to put in a page. |
sandbox: true and the Autohost test hosts |
Test mode. Use a test-mode key (ah_sk_us_test_...) against the same API host. |
| Reseller account with child host accounts | One organization, with each host’s verifications marked by tenant_ref. See Partners with many host accounts. |
| Autohost MCP server | Connect an AI assistant to your Checktiv organization. |
Step 1: Find every place that uses Autohost
Section titled “Step 1: Find every place that uses Autohost”Search your code and your configuration for autohost.ai, autohost.ca, verifyhub.org, gueststay.in, AutohostSDK, x-api-key, and guest_portal_url. Then check these places, which a code search does not find:
- Email, SMS, and booking-confirmation templates that contain a Guest Portal link.
- Guest Portal links that your database stores for future bookings. They stop working at the end-of-life date.
- Mobile apps that open a Guest Portal link.
- Scheduled jobs that read Autohost status.
- Your Content Security Policy and other allowlists.
Give this list to your AI assistant with your code.
Step 2: Set up your Checktiv organization
Section titled “Step 2: Set up your Checktiv organization”-
In the console, open Developers → API keys and click Create Key. Select Secret key and give it these scopes:
Scope Why you need it sessions:writeCreate, cancel, and resend verifications, and add notes applicants:writeSend applicant details inline on the create sessions:readRead verifications and their results sessions:read_reportDownload the PDF report and the evidence images sessions:workspace_tokenMint tokens for the workspace reviewer in your admin dashboard applicants:readRead applicant records, and link copied reservations to your bookings sessions:browser_tokenOnly if a template has a custom_formstep, or you translate the signing or credit history screens. See Translations.idv:writeOnly if you call POST /v1/id-verification -
Store the secret key where your server keeps the Autohost API key, for example a secrets manager. Never put it in a page.
-
Click Create Key again and select Publishable key. Add each origin that loads the SDK. The SDK does not render on an origin that the key does not list.
-
In Workflows, create one workflow template for each tier. See Create a verification workflow template.
-
Open Developers → Webhooks and click New subscription. You need the Owner or Admin role. Select these event types:
kyc.session.completed,kyc.session.manual_review_requested,kyc.session.cancelled,kyc.session.expired, and, if a template has a signing step,kyc.session.document_signedandkyc.session.document_declined. A subscription receives events for one mode only, so create one for test mode now and one for live mode later. -
If you show the admin reviewer, open Developers → Workspace origin and enter the
httpsorigin of your admin dashboard. It takes one origin.
Partners with many host accounts
Section titled “Partners with many host accounts”If you used the Autohost reseller APIs, we copy your data into one Checktiv organization. Each Autohost host account becomes a partition of that organization, marked by tenant_ref. The value is the Autohost user id of that host. If some of your hosts’ data must stay in the EU, email support@autohost.ai before we copy your data.
- Keys and webhooks belong to the organization, one set for each mode. One secret key and one webhook subscription can serve all your hosts. Each key has its own rate limit, so a batch for one host spends the budget of every host that shares the key.
- New verifications: send the host’s id as
tenant_refon the create. For a host from Autohost, send its Autohost user id. For a new host, send a stable id from your own system. Do not put personal data in it. - The workspace reviewer: mint each workspace token with the host’s
tenant_ref. The reviewer then refuses a verification that belongs to another host. - The console shows the verifications of all your hosts. There is no console login limited to one host, so a host’s staff review in your admin dashboard, through the workspace reviewer.
- Workflow templates belong to the organization. If hosts need different checks or agreement text, create a template for each and name it after the host.
- Routing results: the webhook body does not carry
tenant_ref. Read it fromGET /v1/sessions/{id}. - Listing by host:
GET /v1/sessionsdoes not filter bytenant_ref. Keep the host for each verification in your own database.
POST /accounts/register, PUT /accounts/{id}, GET /accounts/children, and POST /accounts/signup have no equivalent. To stop a host, stop creating verifications with its tenant_ref in your own code. If you are not a reseller, do not send tenant_ref.
Step 3: Start verifications on your server
Section titled “Step 3: Start verifications on your server”This step moves the start of each verification from the browser to your server. The Autohost SDK took a reservation id in the browser, and the reservation id was the only credential. The Checktiv SDK takes a client token that your server gets when it creates the verification. Your secret key stays on your server.
Before, with Autohost (browser):
const client = await AutohostSDK.init({ reservationId: RESERVATION_ID });After, with Checktiv (your server):
// POST /api/verifications (your backend). Never call the Checktiv API from a browser.import { regionToApiBase } from '@checktiv/sdk-web';
app.post('/api/verifications', requireApplicantForBooking, async (req, res) => { const booking = req.booking; // set by your own access check
// Reuse the verification you already created for this booking. // When you cancel a verification, clear the stored token first. if (booking.checktivClientToken) { res.json({ clientToken: booking.checktivClientToken }); return; }
const response = await fetch(`${regionToApiBase('us')}/v1/sessions`, { method: 'POST', headers: { Authorization: `Bearer ${process.env.CHECKTIV_SECRET_KEY}`, // ah_sk_* 'Content-Type': 'application/json', 'Idempotency-Key': `verification-${booking.id}-${booking.verificationAttempt}`, // a retry returns the same verification }, body: JSON.stringify({ workflow_template_id: templateIdForTier(booking), // your own logic, for example one template per tier applicant: { given_names: booking.guestGivenNames, // an array, for example ["Mary", "Ann"] family_name: booking.guestFamilyName, email: booking.guestEmail, phone: booking.guestPhone, date_of_birth: booking.guestBirthDate, // YYYY-MM-DD booking_name: booking.nameOnBooking, // compared against the ID when Name match is on external_id: booking.id, // your own id, returned when you read the applicant }, metadata: { start_datetime: booking.checkIn, // ISO 8601 with an offset end_datetime: booking.checkOut, amount: booking.totalInMinorUnits, // 125000 means 1,250.00 in usd currency: booking.currency, location: booking.propertyAddress, confirmation_code: booking.confirmationCode, // your own key }, }), }); if (!response.ok) { logCreateError(booking, response.status, await response.json()); // keep the error on your server res.status(502).json({ error: 'verification_unavailable' }); return; }
const { data } = await response.json(); await saveVerification(booking, { verificationId: data.id, // the id that webhooks refer to clientToken: data.client_token, // returned only on this response identityDetailsMissing: Boolean(data.warnings), // see the caution below }); res.json({ clientToken: data.client_token, identityDetailsMissing: Boolean(data.warnings) });});regionToApiBase('us') returns https://api.us.checktiv.com, and regionToApiBase('eu') returns https://api.eu.checktiv.com. This sample calls the REST API directly because it needs the verification id. The sessions.create helper in the SDK returns only the client token.
Rules for this route:
- Check the caller. The client token resumes the applicant’s verification. Return it only to the applicant for that booking, for example after you check a signed link or a login.
- Store the client token. The create returns
client_tokenonce, and a read never returns it again. Store it with the booking and return the stored value when the applicant comes back. - Send the identity details. See the caution below.
- Keep errors on your server. A Checktiv error can describe your key’s region or your request. Log it, and send the browser a short error of your own.
- Use one region. An EU organization uses
regionToApiBase('eu')and EU keys. A key works only in its own region.
Step 4: Replace the Autohost SDK in your applicant pages
Section titled “Step 4: Replace the Autohost SDK in your applicant pages”Remove the Autohost SDK
Section titled “Remove the Autohost SDK”-
Delete the Autohost script tag. It looks like one of these:
<script src="https://sdk.autohost.ai/dist/AutohostSDK.v3.bundle.js"></script><script src="https://sdk.autohost.ai/dist/AutohostSDK.v3.11.0.bundle.js"></script> -
If you installed the Autohost package with npm, remove it:
Terminal window npm uninstall @autohostai/autohost-sdk -
Remove every call to
AutohostSDK.init,client.component(...),client.verification.save,client.reservation.get,AutohostSDK.fraudCollector, andAutohostSDK.createSecuredToken. -
Remove every
autohost.aiandautohost.cahost from your Content Security Policy and other allowlists. Also removeverifyhub.organdgueststay.inif you embedded the Guest Portal.
Do this one booking at a time. A booking with an Autohost verification in progress keeps the Autohost code until that verification ends. See Step 9.
Install the Checktiv SDK
Section titled “Install the Checktiv SDK”npm install @checktiv/sdk-webOr load it from the CDN. The script sets window.Checktiv and registers every module:
<script src="https://sdk.us.checktiv.com/v1/sdk.js" crossorigin="anonymous"></script>For production, pin a version and add a Subresource Integrity hash. See Versioning. If your pages send a Content Security Policy or a Permissions-Policy, add the Checktiv origins. See Security headers.
Mount the journey
Section titled “Mount the journey”Before, with Autohost:
const reservation = client.reservation.get();AutohostSDK.fraudCollector( { reservationID: reservation.id, listingID: reservation.lid, userID: reservation.hid }, { sandbox: false },);
client.component('IDV', { callbacks: { onIDVComplete: () => goToNextStep() } }).mount('#target');
await client.verification.save({ step: 'Finish', complete: true, data: {} });After, with Checktiv:
import { mount } from '@checktiv/sdk-web';import '@checktiv/sdk-web/idv'; // identity verificationimport '@checktiv/sdk-web/fraud'; // only if your templates use fraud signalsimport '@checktiv/sdk-web/esign'; // only if your templates have an esign stepimport '@checktiv/sdk-web/credit-history'; // only if your templates have a credit_history stepimport '@checktiv/sdk-web/capture-ui/style.css'; // required: styles the capture screens
const handle = mount('#target', { publishableKey: 'ah_pk_us_test_...', resumeKey: bookingId, // an applicant who comes back resumes at the current step fetchToken: () => fetch('/api/verifications', { method: 'POST' }) .then((res) => res.json()) .then((body) => body.clientToken), onConsent: () => showFraudDisclosure(), // resolve true to start fraud signals, false to decline onComplete: () => window.location.reload(), // the applicant submitted a step: reload to show the next one onEvent: (event) => { if (event.type === 'checktiv.idv.processing' && event.reason === 'no_renderable_step') { showSubmittedScreen(); // nothing for the applicant to do on this step; the result arrives by webhook } }, onError: (error) => showError(error.code),});On the npm path, each step type needs its import. A step without its import stops the journey with sdk_load_failed. The CDN script registers every module, so it needs no imports.
What changes:
- The template decides the steps. You do not mount each step yourself, and you do not call
savefor each step. Each mount shows the applicant’s current step. - Reload after each step.
onCompletefires each time the applicant submits a step. The journey does not move to the next step by itself: reload the page, or mount again, to show it. When there is nothing for the applicant to do, for example after the last step, the mount reportschecktiv.idv.processingwithreason: "no_renderable_step". Show your own “submitted” screen then. - No finish call. Submitting the last step ends the applicant’s part, and you send no completion signal. Remove
complete: truefrom thesavecall that carried it. - Fraud signals need consent.
onConsentmust resolvetrue. A callback that resolvesfalse, resolves nothing, or throws keeps fraud signals off, and the SDK reports no error. Withmount, you do not call a fraud collector yourself. Autohost recommended calling its collector at least twice. onCompleteis not a result. It carries no ID data and no verdict. Get the outcome from the webhook or fromGET /v1/sessions/{id}on your server.- Desktop-to-phone capture. To offer it, also import
@checktiv/sdk-web/idv/cross-device, passcrossDeviceCopy, and callhandle.openCrossDevice()from your own button. See Cross-device handoff.
For React, use <ChecktivJourney>. It takes the same options. See React.
Replace an embedded Guest Portal
Section titled “Replace an embedded Guest Portal”If you showed the Guest Portal in an iframe (verifyhub.org/{id}?embed=1, or gueststay.in in test), mount the SDK in its place, as shown above. The Checktiv verification link cannot be shown in an iframe: the hosted journey refuses to load inside another site’s page.
| Autohost Guest Portal embed | Checktiv |
|---|---|
<iframe src="https://verifyhub.org/{id}?embed=1"> |
mount(...) in your page, or open the verification link in a new tab |
isMobile=yes |
Not needed. For a full-screen capture on phones, pass layout: 'immersive' to mount. |
allow="geolocation; camera; fullscreen;" on the iframe |
Not needed. The SDK sets the camera permission on its own frame. If your page sends security headers, add the Checktiv origins. |
postMessage event guestportal-completed |
The no_renderable_step event above, then the result by webhook |
postMessage event guestportal-step-completed |
onComplete |
is_repeat_guest, is_previously_declined_guest in the event |
No browser event. A screening rule on fraud.repeatApplicant can send a verification to review. |
Map the SDK components, options, and callbacks
Section titled “Map the SDK components, options, and callbacks”| Autohost SDK | Checktiv |
|---|---|
client.component('IDV', ...) |
The id_verification step. Set Face match to Selfie photo or Active liveness in the workflow template. |
IDV option isIDCollectOnly (ID Collection) |
The id_verification step with Face match set to Selfie photo or Active liveness. Autohost ID Collection also matched a selfie. |
client.component('Selfie', ...) (a selfie with no ID check) |
No selfie-only step. Use the id_verification step with Face match set to Selfie photo. |
IDV options allowSelfieRetryInPlace, includeWhatToExpect, isSinglePage |
No equivalent. The journey controls retries and its own screens. |
client.component('ElectronicSignature', ...) and save for UsageAgreement or HouseRules |
The esign step. See Documents applicants sign. |
ElectronicSignature options signatureModes, showTermsCheckbox, emailSignedCopy |
For emailSignedCopy, the esign step has Email a copy to the applicant, on by default. signatureModes and showTermsCheckbox have no equivalent: the applicant always signs by typing their name. The template sets the other signing options, such as Require the applicant to scroll to the end and Minimum signer age. |
client.component('PersonalInfo', ...) and save({ step: 'PersonalInfo', ... }) |
The applicant object on the create, or collectUserInfo. See Step 3. |
save for GuestList, PurposeOfStay, or AboutYou |
A custom_form step. mount cannot show it: use init(...) and client.mountProvisioned(...) with customFormConfig. See Custom forms and Translations. |
save for BackgroundCheck |
A background check in the workflow template. It reads the name and date of birth that complete collect_user_info. A US background check also needs the address. |
save for CreditCheck |
A credit_history step. The SDK shows its authorization screens. See Credit history. |
save({ step: 'Finish', complete: true }) |
Remove it. |
AutohostSDK.fraudCollector(context, options) |
import '@checktiv/sdk-web/fraud' and onConsent. See Fraud consent. |
fraudCollector option disableGeolocation |
No equivalent. Checktiv fraud signals do not ask for the device location. |
| Remote camera QR code on desktop | handle.openCrossDevice(). See the list above. |
onIDVComplete |
onComplete. It fires when the applicant submits any step. Reload to show the next step. |
onSkippedIDV |
No browser event. Read the result of the ID check in check_results on your server. |
onError |
onError. The error carries a code from the SDK error reference. |
Other callbacks (onStartImageUpload, onLivenessComplete, onSubmit, …) |
onEvent. Event types start with checktiv., for example checktiv.idv.submitted and checktiv.esign.submitted. Ignore types you do not know. |
primaryColor |
theme: { primaryColor } on mount. See Theming. |
locale |
No locale option on mount. See Translations. |
client.reservation.get() |
Nothing in the browser. Read the verification on your server with GET /v1/sessions/{id}. |
Translations
Section titled “Translations”The Autohost SDK translated its screens from a locale. The Checktiv SDK does not translate its screen text. You find the applicant’s language yourself and pass translated text. In copy and esignCopy, every key is optional, and a key you leave out shows in English. In crossDeviceCopy, unavailableMessage is required, and another key you leave out hides that text.
mount takes two text options:
copyfor the capture screens. See Advanced capture.crossDeviceCopyfor the desktop-to-phone handoff. See Cross-device handoff.
With mount, the signing and credit history screens show in English, and a custom_form step does not show at all: the mount reports sdk_load_failed with a message that asks for customFormConfig. To translate the signing and custom form screens, or to show a custom form at all, start the journey with init(...) and client.mountProvisioned(...) and pass customFormConfig. On the credit history screens, you can set only the continue, back, and submit button labels. That path also takes esignCopy, customFormCopy, and creditCopy. It uses a browser token from POST /v1/sessions/{id}/browser_token in place of the client token. See Token handoff and Modules overview.
If your applicants read other languages, plan the work to write and maintain these strings.
Map Autohost checks to Checktiv checks
Section titled “Map Autohost checks to Checktiv checks”| Autohost check or screen | Checktiv |
|---|---|
Personal info (PersonalInfo) |
collect_user_info |
ID verification, ID collection, selfie, liveness (IDVerification, IDCollection, Selfie) |
id_verification |
Name match (name_match) |
Name match on the id_verification step, with applicant.booking_name |
| Sanctions, global watchlist, sex offender search, adverse media | watchlist. background_global also searches adverse media. |
| Background check for applicants in the US | background_us_criminal |
Background check for applicants outside the US, and the global check (/background-check/submit?type=globalcheck) |
background_global |
Credit check (CreditCheck) |
credit_history, for organizations in the US region |
Rental agreement and house rules (UsageAgreement, HouseRules) |
esign |
| Guest list, purpose of stay, about you, file upload, custom screen | custom_form |
| Fraud detection and device fingerprint | The fraud module, with screening rules on its signals |
See Choose the right check types for what each check does.
Step 5: Replace the admin components
Section titled “Step 5: Replace the admin components”The Autohost admin side used ReservationResults and SexOffenders with a short-lived apiToken. Checktiv replaces both with the workspace reviewer. It shows the verification, the evidence, the watchlist matches, and the report.
Before, with Autohost (server, then browser):
// Server: mint an admin token from the SDK keyconst { token: apiToken } = await fetch(`https://embed.autohost.ai/api/auth?token=${SDK_KEY}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ filters: [{ scope: 'read', level: 'reservation', id: reservationId }] }),}).then((res) => res.json());
// Browserclient.component('ReservationResults', { reservationId, apiToken }).mount('#results');Some integrations sent the same filters body to /sdk/authorization with the SDK key in an x-api-key header. If you minted the admin token in the browser, move that call to your server: a Checktiv secret key must never reach a page.
After, with Checktiv:
-
Set your workspace origin. See Step 2.
-
On your server, add a route that mints a token pair with
POST /v1/sessions/{id}/workspace_token. The route must check that the caller is a staff member who may see this verification. Send:origin: your admin origin.actor: the staff member, as{ ext_id, name }.capabilities: what this staff member may do.tenant_ref: the host, if you are a reseller.
The response is
{ data: { framing_token, data_token, expires_at } }. Return it to the browser as{ framingToken, dataToken, expiresAt }. The workspace reviewer page has the complete route. -
In your admin page, mount the reviewer:
import { workspace } from '@checktiv/sdk-web/workspace';const reviewer = workspace({region: 'us',getToken: async ({ sessionId, reason }) => {const res = await fetch(`/api/checktiv/workspace-token/${sessionId}`, {method: 'POST',headers: { 'Content-Type': 'application/json' },body: JSON.stringify({ reason }),});return res.json(); // { framingToken, dataToken, expiresAt }},});const target = document.getElementById('results'); // set an explicit height on this elementif (target) reviewer.mount('reviewer', { sessionId, target });
| Autohost admin | Checktiv workspace reviewer |
|---|---|
ACL scope: 'read' |
session:read, evidence:read, and report:read |
ACL scope: 'write', and Approve and Decline in ReservationResults |
session:decide. Changing a decision on a completed verification needs session:override. |
ACL level: 'listing' |
No listing level. A token minted with a tenant_ref refuses verifications of other hosts. |
SexOffenders component |
The watchlist matches in the reviewer |
ReservationResults option styles |
theme on workspace(...): primaryColor, colorMode, logoUrl, and brandName |
ReservationResults callbacks success and error |
onEvent on mount, with the events checktiv.workspace.navigate and checktiv.workspace.error |
ReservationResults callback revealedIDImage |
No browser event |
Approve or decline
Section titled “Approve or decline”Autohost let your server approve or decline a reservation with POST /reservations/{id}/status. Checktiv differs in three ways:
- A person decides. A reviewer decides a verification that is waiting for review (
status: "awaiting_review"). The reviewer works in the workspace reviewer or in the console, in Applicants. No server API decides a verification that is waiting for review. - Rules about the applicant go in the workflow template. Screening rules read the applicant, the check results, and the fraud signals. An approve rule approves the verification, unless a decline rule also matches or the score reaches the review threshold. A decline rule sends it to review, because Checktiv never declines a verification automatically.
- Rules about the booking stay on your server. A screening rule cannot read the dates, the price, or the source of a booking. Apply those rules before the create, and choose a stricter workflow template when they match.
POST /v1/sessions/{id}/manual_review is a different operation. It records a decision on a verification that is still in progress (created, pending, or in_progress). On a verification that is waiting for review, it is refused with 409.
Step 6: Change endpoints and fields
Section titled “Step 6: Change endpoints and fields”Change the base URL and the authentication header
Section titled “Change the base URL and the authentication header”Replace https://data.autohost.ai/v1 with https://api.us.checktiv.com/v1 for the US region, or https://api.eu.checktiv.com/v1 for the EU region. Test mode and live mode use the same host: the key decides the mode.
# Before (Autohost)curl https://data.autohost.ai/v1/accounts/me \ -H "x-api-key: YOUR_AUTOHOST_API_KEY"
# After (Checktiv)curl https://api.us.checktiv.com/v1/me \ -H "Authorization: Bearer ah_sk_us_test_<your-key>"Map the endpoints
Section titled “Map the endpoints”| Autohost Data API | Checktiv API |
|---|---|
GET /accounts/me |
GET /v1/me |
Every /listings call |
No equivalent. Remove these calls. |
POST /reservations |
POST /v1/sessions. It returns the new verification at once, with status: "pending". The result arrives later by webhook. |
PUT /reservations/{id}, or a repeat POST with the same confirmation_code |
No equivalent. See Booking changes. |
A status: "CANCELED" update |
POST /v1/sessions/{id}/cancel |
GET /reservations/{id}, /status, /guestportal |
GET /v1/sessions/{id}: read status, outcome, and review.causes |
GET /reservations/{id}/summary |
GET /v1/sessions/{id}: read check_results. For a PDF, GET /v1/sessions/{id}/report.pdf |
GET /reservations with from and size |
GET /v1/sessions with limit and starting_after. It filters by status and outcome only. |
GET /reservations?pending_review=true |
GET /v1/sessions?status=awaiting_review |
GET /reservations/{id}?pms=... (look up by confirmation code) |
No lookup by your own key. Store the verification id with your booking, then read by id. See Link copied reservations to your bookings. |
POST /reservations/{id}/status (supervised) |
The workspace reviewer or the console. See Approve or decline. |
GET /reservations/{id}/notes, and notes in a webhook |
POST /v1/sessions/{id}/notes adds a note. GET /v1/sessions/{id} returns the notes in metadata.operatorNotes. |
POST /idcheck/upload/{id}/{step}/{type} |
The SDK, or the verification link. For a document scan with no verification, POST /v1/id-verification. |
GET /idcheck/status/{id} |
GET /v1/sessions/{id}: the id_verification entry in check_results |
GET /idcheck/image/{id}/{step} |
GET /v1/sessions/{id}/idv-image/{artifact}, where artifact is front, back, selfie, or portrait. It returns the image bytes, not base64. See Evidence images. |
GET /reservations/{id}/reports/usage-agreement |
No API returns the signed document. It is attached to the applicant’s record in the console. A copied Autohost reservation does not include it. |
POST /accounts/webhooks, DELETE /accounts/webhooks |
In the console: Developers → Webhooks. No API creates a subscription. |
?skip_gp=1 (screen without the applicant) |
Send the applicant’s details on the create, and use a workflow template whose checks all run on the server, such as watchlist. The verification then runs without the applicant. |
Other /reservations/{id}/* reads, such as /screens |
No equivalent. Read the verification. |
GET /reservations/{id}/embed |
The workspace reviewer. See Step 5. |
Link copied reservations to your bookings
Section titled “Link copied reservations to your bookings”The applicant of each copied verification has the Autohost reservation id in external_id. No API call finds a verification by external_id, so match them once, after we copy your data:
- Page through
GET /v1/applicantswithlimitandstarting_after. Readidandexternal_idfrom each applicant. - Page through
GET /v1/sessionsthe same way. Readidandapplicant_idfrom each verification. - Join the two lists on the applicant id. Store each verification id with the booking that has that Autohost reservation id.
This needs the applicants:read and sessions:read scopes. To find new verifications the same way, send your own booking id as applicant.external_id on the create.
Map the create fields
Section titled “Map the create fields”Autohost took a reservation. Checktiv takes an applicant, a workflow template, and a metadata object that describes the transaction.
Autohost POST /reservations field |
Checktiv POST /v1/sessions field |
|---|---|
guest.first_name |
applicant.given_names, an array. A middle name is another entry. |
guest.last_name |
applicant.family_name. A surname of several words stays one value. |
guest.email |
applicant.email |
guest.phone |
applicant.phone |
guest.birth_date |
applicant.date_of_birth |
guest.location (free text) |
applicant.address: an object with line1, city, and country (two uppercase letters). Leave it out if you have only free text. |
| The name on the booking or on the payment card | applicant.booking_name |
confirmation_code |
Your own key in metadata |
check_in_date (with the listing’s check_in_time) |
metadata.start_datetime, ISO 8601 with an explicit offset |
check_out_date (with the listing’s check_out_time) |
metadata.end_datetime, ISO 8601 with an explicit offset |
total_price |
metadata.amount in minor units, with metadata.currency |
listing_id, listing (the property address) |
metadata.location, one line of text |
guest_portal_screens |
workflow_template_id. One template for each combination of steps you use. |
source, status, number_of_guests, nights |
Your own keys in metadata, if you want them stored with the verification. Nothing in Checktiv reads them. |
without_listing: true |
Remove it. No verification needs a listing. |
?sync=1 |
Remove it. The create always returns the new verification. |
?callback=<url> |
A webhook subscription. See Step 7. |
guest_portal_url in the response |
applicant_url, in the create response only. Or set send_invite: true to email the link, if you send applicant.email. |
Details to check in your code:
- Times need an offset. Autohost read a time without
Zin the listing’s time zone. Checktiv has no listing, so send the offset of the place where the transaction happens, for example2026-03-14T15:00:00-05:00. A value that ends inZis also accepted. A value with no offset is refused. - Amounts are in minor units. Send
125000with"currency": "usd"for 1,250.00. A currency with no decimal places, such asjpy, takes the whole number. A decimal string is refused. Anamountneeds acurrency, andend_datetimecannot be beforestart_datetime. - A document can make a key required. If a document in the workflow template prints a
metadatakey, for example the dates or the amount, every create must send that key. A create without it is refused with403and the codeesign_requirements_not_met. - Your own metadata keys take a string, a number, a boolean, or
null. Some names are reserved, for examplenotes. See Verification metadata. - Names come in parts. The create refuses a
full_nameorlegal_namefield. See Collect user info. - Requests are rate limited. If you create verifications in a batch, handle
429with the coderate_limit_exceeded. See Rate limits.
Booking changes
Section titled “Booking changes”Autohost treated a repeat POST /reservations with the same confirmation_code as an update, with no time limit. After you create a Checktiv verification, you cannot point it at another applicant or change its workflow template or your metadata keys.
- An
Idempotency-Keyprotects retries of one request for 24 hours. A retry with the same body returns the same verification. The same key with a different body returns409with the codeidempotency_conflict. - If a change matters to the verification, cancel it and create a new one with a new
Idempotency-Key. A different applicant, or new dates in a document they sign, are changes of this kind. Clear the stored client token when you cancel. - Keep other booking changes in your own system.
Map the statuses
Section titled “Map the statuses”Autohost put the verdict in verification_status.status and a host decision in supervised. Checktiv uses two fields: status says where the verification is, and outcome says what it decided.
| Autohost | Checktiv |
|---|---|
status: null or status: "pending" |
Any status that is not completed, awaiting_review, expired, or cancelled. outcome is usually null. |
status: "verified" |
status: "completed", outcome: "approved", and decision_source: "automatic" |
status: "review" |
status: "awaiting_review". The reasons are in review.causes. |
| A decline by your business rules | No automatic decline. A decline rule sends the verification to review. |
supervised: "approve" by a person |
status: "completed", outcome: "approved", and decision_source: "reviewer" |
supervised: "decline" by a person |
status: "completed", outcome: "declined", and decision_source: "reviewer" |
| No Autohost equivalent: the applicant refuses to sign | status: "completed", outcome: "declined", and no decision_source |
reason, business_rules, top_risks |
review.causes, and the reasons on each entry of check_results. See Review reasons. |
risk_color, protect_score |
No risk color. Use outcome and review.causes. |
pms_status: "CANCELED" |
status: "cancelled" |
Statuses you did not have in Autohost:
payment_required. A live verification waits here when your wallet has no credit, and it sends no webhook. It continues when you add credit. A verification held when it reaches a document-signing step, before the document is shown, does not continue: create a new verification for that applicant.expired. A verification that the applicant does not finish in time ends here. A verification that nobody decides in review also ends here, after a retention period.awaiting_reviewafter an error. A verification can also stop in review after a processing error. Itsreview.causesthen includesprocessing_error, and it sends no webhook.
See Track verification status for every status.
Map the errors
Section titled “Map the errors”Autohost returned {"error": "<message>"}, mostly with HTTP 400. Checktiv returns an error object with a stable code:
{ "error": { "type": "https://docs.checktiv.com/api/errors/validation_error", "code": "validation_error", "message": "Invalid request body", "param": "metadata", "request_id": "req_...", "doc_url": "https://docs.checktiv.com/api/errors/validation_error", "details": { "issues": [{ "path": ["metadata", "currency"], "message": "..." }] } }}Match on code, not on message. For a validation_error, details.issues names each value at fault. Log the X-Request-Id response header. Every code has a page in the error reference.
Step 7: Rewrite your webhook receiver
Section titled “Step 7: Rewrite your webhook receiver”Autohost sent each kind of event to its own URL, with no event type in the body, and an optional static Authorization header. Checktiv sends every event type you select to one endpoint, with the type in the body and a signature in a header.
Before, with Autohost:
app.post('/webhooks/autohost/screening', express.json(), async (req, res) => { if (req.get('authorization') !== process.env.AUTOHOST_WEBHOOK_AUTH) return res.status(401).end(); await updateBookingStatus(req.body.id, req.body.status); // pending, verified, or review res.status(200).end();});After, with Checktiv:
import crypto from 'node:crypto';
// Read the raw body: the signature covers the exact bytes.app.post('/webhooks/checktiv', express.raw({ type: 'application/json' }), async (req, res) => { const secrets = [ process.env.CHECKTIV_WEBHOOK_SECRET, process.env.CHECKTIV_WEBHOOK_SECRET_NEXT, ].filter(Boolean); const header = req.get('x-webhook-signature'); if (!secrets.some((secret) => verifySignature(header, req.body, secret))) { res.status(400).end(); return; } if (req.get('x-webhook-origin') === 'test_ping') { res.status(200).end(); return; } const eventId = req.get('x-webhook-id'); // the same on every retry of one event if (await alreadyProcessed(eventId)) { res.status(200).end(); return; }
const event = JSON.parse(req.body.toString('utf8')); switch (event.type) { case 'kyc.session.completed': case 'kyc.session.manual_review_requested': case 'kyc.session.cancelled': case 'kyc.session.expired': { const verification = await getVerification(event.sessionId); // GET /v1/sessions/{id} await updateBookingFromVerification(verification); // your own code break; } default: break; // ignore event types you do not handle } await markProcessed(eventId); res.status(200).end();});
function verifySignature(header, rawBody, secret) { const parts = Object.fromEntries((header ?? '').split(',').map((part) => part.split('='))); const timestamp = Number(parts.t); if (!parts.v1 || !Number.isFinite(timestamp)) return false; if (Math.abs(Date.now() / 1000 - timestamp) > 300) return false; // 5-minute window const expected = crypto .createHmac('sha256', secret) .update(`${parts.t}.`) .update(rawBody) .digest('hex'); return ( expected.length === parts.v1.length && crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1)) );}The signing secret shows once, when you create the subscription or rotate its secret. Rotation takes effect at once: every later delivery, retries and replays included, is signed with the new secret only. The receiver reads a second secret so that you can add the new one in configuration, without a code change. Remove the old one after a delivery verifies with the new one. See Verify webhook signatures.
| Autohost webhook setting | Checktiv event |
|---|---|
screening_webhook_url |
kyc.session.completed for an automatic result, a reviewer decision, or an applicant who refuses to sign. kyc.session.manual_review_requested when a verification goes to review. |
guest_portal_webhook_url (the applicant submitted) |
No server event. Use onComplete in the SDK for that moment. |
reservation_webhook_url (created or updated) |
No equivalent, because you create the verification. Use kyc.session.cancelled for a cancellation. |
Signature submitted (ElectronicSignature onSubmit, or the guestportal.signature reservation field) |
kyc.session.document_signed and kyc.session.document_declined |
listing_webhook_url, account_webhook_url |
No equivalent. Remove these URLs from your Autohost account. |
stargate_webhook_url |
No equivalent. See What is not part of Checktiv. |
A per-request ?callback=<url> |
The subscription. Route each event in your receiver, for example by the booking you stored with the verification id. |
Rules for the receiver:
- The body has no personal data. It carries the verification id and, when the event reports one, the outcome. Autohost’s
reservation_webhook_urlsent the full reservation, so remove any code that reads applicant or ID details from a webhook body. - Webhook keys are camelCase, for example
sessionIdanddecisionSource. The REST API uses snake_case, for exampledecision_source. Some keys are optional: see The event payload for when each one is absent, and readoutcomefor the verdict. kyc.session.expiredfires when a verification runs out of time before it finishes, or when it stays in review past its retention period.- Two cases send no webhook. A verification that stops on a processing error goes to review without an event, and a verification that waits at
payment_requiredsends none. RunGET /v1/sessions?status=awaiting_reviewandGET /v1/sessions?status=payment_requiredon a schedule to find these.
See Create a webhook endpoint for every event and its body.
Step 8: Test
Section titled “Step 8: Test”Create verifications with a test-mode key and set expected_outcome on the create. Check that your receiver, your booking status, and your admin handle each result:
expected_outcome |
Result | Webhook |
|---|---|---|
pass |
status: "completed", outcome: "approved" |
kyc.session.completed |
review |
status: "awaiting_review" |
kyc.session.manual_review_requested |
fail |
status: "awaiting_review". A failed check goes to review. |
kyc.session.manual_review_requested |
doc_quality |
status: "awaiting_review" |
kyc.session.manual_review_requested |
To test a declined result, decline a verification that waits for review in the workspace reviewer or the console. If a template has a signing step, also refuse to sign once.
Also test:
- The capture screens. In test mode, simulated buttons replace the camera. To see the real camera screens, run a few verifications with a live-mode key on a real phone. Live verifications are billed.
- Every step. Use a workflow template with every step type you use. Check that a reload after each step shows the next one, and that a missing import shows as
sdk_load_failed. - A webhook with a bad signature, and a repeat
X-Webhook-Id. Your receiver must refuse the first and skip the second. - An applicant who comes back. Your server must return the stored client token, not create a second verification.
See Modes and regions.
Step 9: Move in stages, then remove Autohost
Section titled “Step 9: Move in stages, then remove Autohost”- Record the system for each booking. Store whether each booking started on Autohost or on Checktiv, and route each booking to its own system. A booking that started on Autohost finishes on Autohost.
- Start with a small group. Start new verifications in Checktiv for one host or one property. Check that webhooks arrive, that your booking status updates, and that your admin shows each result.
- Move the rest. Add more hosts when the first group works. If you find a problem before the end-of-life date, you can start new verifications in Autohost again.
- Close what is still open on Autohost. Before the end-of-life date, create a Checktiv verification for each booking whose Autohost verification is not complete. Send the new verification link to the applicant.
- Keep what we do not copy. Download the Autohost reports and signed documents you must keep.
- Remove Autohost. Remove the Autohost code, script tags, and allowlist entries. In your Autohost account, delete your API keys and SDK keys and remove your webhook URLs.
Questions
Section titled “Questions”Do our Autohost API keys work with Checktiv? No. Create new keys in the console. See Step 2.
Can we run Autohost and Checktiv at the same time? Yes, until the end-of-life date. Route each booking to the system it started on.
Do we still send listings? No. Send the transaction details in metadata.
What happens to Guest Portal links we already sent? They work until the end-of-life date, then stop. For a booking that still needs a verification, create a Checktiv verification and send its link.
Can we show the verification link in an iframe? No. Mount the SDK in your page, or open the link in a new tab.
Can our server approve or decline a verification? Not one that is waiting for review. A person decides in the workspace reviewer or the console. Put rules about the applicant in the workflow template, and apply rules about the booking on your server before the create.
Where does the result come from? From the webhook, or from GET /v1/sessions/{id}. onComplete in the SDK is not a result.
Is testing free? Yes, in test mode. Live verifications are billed.
Related pages
Section titled “Related pages”- Quickstart: your first authenticated request
- Embed the verification flow (SDK): the complete SDK walkthrough
- Token handoff: how the client token and browser token work
- Workspace reviewer: the reviewer you embed in your admin dashboard
- Create a webhook endpoint: events and payloads
- Sample app: a complete integration you can run
- Interactive API reference: every endpoint and field