Skip to content

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.

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

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.

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.

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.

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.

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.
  1. Find every place that uses Autohost.
  2. Set up your Checktiv organization: keys, workflow templates, and a webhook subscription.
  3. Start verifications on your server.
  4. Replace the Autohost SDK in your applicant pages.
  5. Replace the admin components.
  6. Change endpoints and fields.
  7. Rewrite your webhook receiver.
  8. Test each result in test mode.
  9. Move your bookings in stages, then remove Autohost.
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.

  1. 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:write Create, cancel, and resend verifications, and add notes
    applicants:write Send applicant details inline on the create
    sessions:read Read verifications and their results
    sessions:read_report Download the PDF report and the evidence images
    sessions:workspace_token Mint tokens for the workspace reviewer in your admin dashboard
    applicants:read Read applicant records, and link copied reservations to your bookings
    sessions:browser_token Only if a template has a custom_form step, or you translate the signing or credit history screens. See Translations.
    idv:write Only if you call POST /v1/id-verification

    See Choosing scopes for your key.

  2. Store the secret key where your server keeps the Autohost API key, for example a secrets manager. Never put it in a page.

  3. 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.

  4. In Workflows, create one workflow template for each tier. See Create a verification workflow template.

  5. 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_signed and kyc.session.document_declined. A subscription receives events for one mode only, so create one for test mode now and one for live mode later.

  6. If you show the admin reviewer, open Developers → Workspace origin and enter the https origin of your admin dashboard. It takes one origin.

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_ref on 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 from GET /v1/sessions/{id}.
  • Listing by host: GET /v1/sessions does not filter by tenant_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_token once, 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”
  1. 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>
  2. If you installed the Autohost package with npm, remove it:

    Terminal window
    npm uninstall @autohostai/autohost-sdk
  3. Remove every call to AutohostSDK.init, client.component(...), client.verification.save, client.reservation.get, AutohostSDK.fraudCollector, and AutohostSDK.createSecuredToken.

  4. Remove every autohost.ai and autohost.ca host from your Content Security Policy and other allowlists. Also remove verifyhub.org and gueststay.in if 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.

Terminal window
npm install @checktiv/sdk-web

Or 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.

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 verification
import '@checktiv/sdk-web/fraud'; // only if your templates use fraud signals
import '@checktiv/sdk-web/esign'; // only if your templates have an esign step
import '@checktiv/sdk-web/credit-history'; // only if your templates have a credit_history step
import '@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 save for each step. Each mount shows the applicant’s current step.
  • Reload after each step. onComplete fires 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 reports checktiv.idv.processing with reason: "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: true from the save call that carried it.
  • Fraud signals need consent. onConsent must resolve true. A callback that resolves false, resolves nothing, or throws keeps fraud signals off, and the SDK reports no error. With mount, you do not call a fraud collector yourself. Autohost recommended calling its collector at least twice.
  • onComplete is not a result. It carries no ID data and no verdict. Get the outcome from the webhook or from GET /v1/sessions/{id} on your server.
  • Desktop-to-phone capture. To offer it, also import @checktiv/sdk-web/idv/cross-device, pass crossDeviceCopy, and call handle.openCrossDevice() from your own button. See Cross-device handoff.

For React, use <ChecktivJourney>. It takes the same options. See React.

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}.

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:

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.

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.

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 key
const { 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());
// Browser
client.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:

  1. Set your workspace origin. See Step 2.

  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.

  3. 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 element
    if (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

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.

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.

Terminal window
# 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>"
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.

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:

  1. Page through GET /v1/applicants with limit and starting_after. Read id and external_id from each applicant.
  2. Page through GET /v1/sessions the same way. Read id and applicant_id from each verification.
  3. 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.

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 Z in the listing’s time zone. Checktiv has no listing, so send the offset of the place where the transaction happens, for example 2026-03-14T15:00:00-05:00. A value that ends in Z is also accepted. A value with no offset is refused.
  • Amounts are in minor units. Send 125000 with "currency": "usd" for 1,250.00. A currency with no decimal places, such as jpy, takes the whole number. A decimal string is refused. An amount needs a currency, and end_datetime cannot be before start_datetime.
  • A document can make a key required. If a document in the workflow template prints a metadata key, for example the dates or the amount, every create must send that key. A create without it is refused with 403 and the code esign_requirements_not_met.
  • Your own metadata keys take a string, a number, a boolean, or null. Some names are reserved, for example notes. See Verification metadata.
  • Names come in parts. The create refuses a full_name or legal_name field. See Collect user info.
  • Requests are rate limited. If you create verifications in a batch, handle 429 with the code rate_limit_exceeded. See Rate limits.

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-Key protects retries of one request for 24 hours. A retry with the same body returns the same verification. The same key with a different body returns 409 with the code idempotency_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.

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_review after an error. A verification can also stop in review after a processing error. Its review.causes then includes processing_error, and it sends no webhook.

See Track verification status for every status.

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.

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_url sent the full reservation, so remove any code that reads applicant or ID details from a webhook body.
  • Webhook keys are camelCase, for example sessionId and decisionSource. The REST API uses snake_case, for example decision_source. Some keys are optional: see The event payload for when each one is absent, and read outcome for the verdict.
  • kyc.session.expired fires 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_required sends none. Run GET /v1/sessions?status=awaiting_review and GET /v1/sessions?status=payment_required on a schedule to find these.

See Create a webhook endpoint for every event and its body.

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”
  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. Keep what we do not copy. Download the Autohost reports and signed documents you must keep.
  6. 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.

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.