The shortlist
Jump straight to whichever service is closest to what you want to build. Each entry below shows the integration pattern, what you'd ship, and the Partner API resources it uses.
AI alarm-verification responder
Receive verification requests, classify them with a vision model, PATCH dispatch or disregard back to CHeKT.
- Webhooks
- Partner API
- Alarm Verifications
- Contacts
Bulk device onboarding wizard
Create a site and provision its bridge + cameras in one API round-trip with per-device success tracking.
- Sites POST
- Devices POST (bulk)
- BulkDeviceCreationResponseDto
Site contact roster sync
Keep CHeKT contacts in lockstep with your HR or identity provider for on-call routing.
- Contacts CRUD
- Cron / scheduler
Compliance audit exporter
Nightly inventory dump — sites, devices, arming settings, verification responses — to encrypted object storage.
- GET Sites/Devices/Contacts
- fields + filter + sort
- S3 / GCS
After-hours site activation
Activate and deactivate sites on a calendar — retail closing, office weekends, holiday handling.
- Sites activation-status
- Arming Settings
- Cron
Cross-dealer fleet dashboard
One view of every site, device, and monitoring station across all dealers connected to your platform.
- Dealers GET
- Sites GET (paginated)
- Devices GET
- Monitoring Stations GET
Dealer connect flow
The opt-in UI that dealer admins click through to bind their dealer to your platform.
- PUT /dealers/connect
- Authorization access token
- PUT /dealers/{id}/disconnect
AI operator assistant
Drop the CHeKT MCP server into Claude or ChatGPT and let an LLM triage the verification queue in plain English.
- MCP server
- Alarm Verifications PATCH
- Partner API read
AI alarm-verification responder
Receive verification requests, classify them with a vision model, PATCH dispatch or disregard back to CHeKT.
An automated first-pass classifier for alarm verifications. CHeKT issues a verification_id when an alarm needs review; your app receives the webhook, runs the snapshot through a vision model, and PATCHes the verification with action dispatch or disregard. Reduces the human verification queue by 70%+ in typical retail deployments.
Architecture
- 01CHeKTYour appverification.requested webhook
- 02Your appVision modelClassify snapshot
- 03Your appCHeKTPATCH /alarm-verifications/{id}action: dispatch | disregard, contact_id, responded_at
What you'll use
Use it for
- Cutting false-positive load — most motion alarms are wind, cleaning crews, or animals
- Pre-classifying events so human operators see the AI verdict alongside the snapshot
- After-hours sites where seconds-to-dispatch matters more than human nuance
Code sketch
// Minimal AI verifier — handle webhook, classify, PATCH back
app.post("/webhooks/chekt", verifyChektSignature, async (req, res) => {
if (req.body.type !== "verification.requested") return res.sendStatus(200);
const { dealer_id, site_id, verification_id, contact_id, snapshot_url } = req.body.data;
const verdict = await vision.classify(snapshot_url);
const action = verdict.label === "intruder" ? "dispatch" : "disregard";
await fetch(`https://api.chekt.com/partner/v1/dealers/${dealer_id}/sites/${site_id}/alarm-verifications/${verification_id}`, {
method: "PATCH",
headers: {
Authorization: `Bearer ${await getAccessToken()}`,
"Content-Type": "application/json",
"x-partner-trace-id": crypto.randomUUID(),
},
body: JSON.stringify({
verification_id,
contact_id,
action,
responded_at: new Date().toISOString(),
}),
});
res.sendStatus(200);
});Bulk device onboarding wizard
Create a site and provision its bridge + cameras in one API round-trip with per-device success tracking.
When an installer brings up a new site, they typically provision one bridge plus 4–16 cameras at the same time. The bulk-device endpoint accepts the entire batch in one POST and returns per-item success or failure, so partial failures (e.g. one bad MAC address) don't roll back the whole install.
Architecture
- 01Installer UIYour appSubmit: site name + N devices
- 02Your appCHeKTPOST /partner/v1/dealers/{dealerId}/sites
- 03CHeKTYour appReturns site_id
- 04Your appCHeKTPOST /sites/{siteId}/devices [bridge + cameras]
- 05CHeKTYour appBulkDeviceCreationResponseDto (success_count + failure_count + per-item results)
What you'll use
Use it for
- Field installer apps that need a fast "new site" wizard
- Bulk migrations from another platform — import 100 sites in an afternoon
- Integrations with inventory systems where new devices are pre-provisioned in the warehouse
Code sketch
// Provision a new site + bridge + cameras in two API calls
async function onboardSite(dealerId: number, payload: {
name: string; timezone: string;
bridgeMac: string; cameras: Array<{ name: string; zone: string; mac: string }>;
}) {
const token = await getAccessToken();
const headers = { Authorization: `Bearer ${token}`, "Content-Type": "application/json" };
// 1) Create the site
const site = await fetch(`https://api.chekt.com/partner/v1/dealers/${dealerId}/sites`, {
method: "POST", headers,
body: JSON.stringify({
external_site_id: `ext-${Date.now()}`,
name: payload.name,
timezone: payload.timezone,
}),
}).then(r => r.json());
// 2) Bulk-create devices (bridge + cameras in one call)
const devices = [
{ external_device_id: payload.bridgeMac, device_type: "bridge", zone_number: "000", mac: payload.bridgeMac },
...payload.cameras.map(c => ({
external_device_id: c.mac, device_type: "camera",
name: c.name, zone_number: c.zone, mac: c.mac,
})),
];
const result = await fetch(`https://api.chekt.com/partner/v1/dealers/${dealerId}/sites/${site.site_id}/devices`, {
method: "POST", headers,
body: JSON.stringify(devices),
}).then(r => r.json());
return { site, success: result.success_count, failures: result.failure_count, results: result.results };
}Site contact roster sync
Keep CHeKT contacts in lockstep with your HR or identity provider for on-call routing.
Keep CHeKT's per-site contact roster in lockstep with your HR or identity provider. The sync job pulls the current people from your IdP, diffs against the existing CHeKT contacts, and creates / updates / removes to converge. Contacts power the alarm-verification routing — the people CHeKT calls when an alarm fires.
Architecture
- 01HR / IdentityYour sync jobPull current employee roster
- 02Your sync jobCHeKTGET /sites/{siteId}/contacts (current state)
- 03Your sync jobCHeKTPOST / PUT / DELETE contacts to reconcile
- 04CHeKTYour sync jobUpdated ResponseContactDto per call
What you'll use
- Contacts CRUD
- Cron / scheduler
Use it for
- Dealers running large operations teams where staff turnover is frequent
- Compliance-driven workflows where contact records must mirror the canonical HR system
- Multi-tenant operators rolling out across many sites simultaneously
Code sketch
// Reconcile site contacts with HR roster
async function syncSiteContacts(dealerId: number, siteId: number, hrPeople: HrPerson[]) {
const token = await getAccessToken();
const headers = { Authorization: `Bearer ${token}`, "Content-Type": "application/json" };
const base = `https://api.chekt.com/partner/v1/dealers/${dealerId}/sites/${siteId}/contacts`;
const current = await fetch(base, { headers }).then(r => r.json());
const byExt = new Map(current.map(c => [c.external_contact_id, c]));
for (const person of hrPeople) {
const existing = byExt.get(person.id);
if (!existing) {
await fetch(base, { method: "POST", headers, body: JSON.stringify({
external_contact_id: person.id,
first_name: person.firstName, last_name: person.lastName,
phone_number: person.phone, email: person.email,
})});
} else {
await fetch(`${base}/${existing.contact_id}`, { method: "PUT", headers, body: JSON.stringify({
first_name: person.firstName, last_name: person.lastName,
phone_number: person.phone, email: person.email,
})});
}
}
// Soft-delete contacts no longer in HR
const hrIds = new Set(hrPeople.map(p => p.id));
for (const c of current) {
if (!hrIds.has(c.external_contact_id)) {
await fetch(`${base}/${c.contact_id}`, { method: "DELETE", headers });
}
}
}Compliance audit exporter
Nightly inventory dump — sites, devices, arming settings, verification responses — to encrypted object storage.
A nightly exporter that snapshots every site's inventory — devices, contacts, arming setting, activation status — into encrypted object storage. Auditors and regulators get a stable, immutable record without portal access. The exporter uses the standard fields / filter / sort / limit / offset query parameters to keep payloads small.
Architecture
- 01Cron 00:30 UTCYour exporterDaily trigger
- 02Your exporterCHeKTGET /sites?fields=site_id,name,timezone,is_activated&limit=200
- 03Your exporterCHeKTPer-site: GET /devices, /contacts, /arming-settings
- 04Your exporterObject storageUpload audit-2026-05-28.csv (encrypted)
What you'll use
Use it for
- UL 827 central stations with annual audit obligations
- SOC 2 evidence collection for monitoring-platform customers
- Insurance loss reports needing verifiable timestamps per device and contact
Code sketch
// Daily inventory export — sites, devices, contacts, arming settings
import { stringify } from "csv-stringify/sync";
async function exportInventory(dealerId: number) {
const token = await getAccessToken();
const headers = { Authorization: `Bearer ${token}` };
const base = `https://api.chekt.com/partner/v1/dealers/${dealerId}`;
const rows: any[] = [];
// Paginate sites
let offset = 0;
while (true) {
const sites = await fetch(`${base}/sites?limit=200&offset=${offset}`, { headers }).then(r => r.json());
for (const s of sites) {
const [devices, contacts, arming] = await Promise.all([
fetch(`${base}/sites/${s.site_id}/devices`, { headers }).then(r => r.json()),
fetch(`${base}/sites/${s.site_id}/contacts`, { headers }).then(r => r.json()),
fetch(`${base}/sites/${s.site_id}/arming-settings`, { headers }).then(r => r.json()),
]);
rows.push({
site_id: s.site_id, name: s.name, timezone: s.timezone,
is_activated: s.is_activated,
device_count: devices.length, contact_count: contacts.length,
security_type: arming.security_type,
});
}
if (sites.length < 200) break;
offset += 200;
}
await s3.putObject({
Bucket: "compliance-prod", Body: stringify(rows, { header: true }),
Key: `audit/${todayPath()}/inventory.csv`, ServerSideEncryption: "AES256",
});
}After-hours site activation
Activate and deactivate sites on a calendar — retail closing, office weekends, holiday handling.
A scheduled activation service for sites that follow a predictable rhythm — retail closing at 22:00, offices on weekends, warehouses on holidays. Runs on your own cron and uses /sites/{siteId}/activation-status to toggle each site. Optionally PATCHes arming-settings to switch the security system at the same time (e.g. day-mode vs night-mode).
Architecture
- 01Your schedulerYour appTrigger at 22:00 site-local (skip holidays)
- 02Your appCHeKTGET /sites?filter=is_activated,0,eq
- 03Your appCHeKTPATCH /sites/{siteId}/activation-status (each)
- 04Your appCHeKTOptional: PATCH /sites/{siteId}/arming-settings (security_type)
- 05CHeKTYour appEach site now active and routed correctly
What you'll use
Use it for
- Retail chains with consistent open/close hours across many locations
- Multi-tenant offices with cleaning crew windows
- Holiday handling — exclude calendars without touching the dealer portal
Code sketch
// Nightly site activation — runs at 22:00 site-local, weekdays
import { CronJob } from "cron";
new CronJob("0 22 * * 1-5", async () => {
const token = await getAccessToken();
const dealer = process.env.CHEKT_DEALER_ID;
const inactive = await fetch(
`https://api.chekt.com/partner/v1/dealers/${dealer}/sites?filter=is_activated,0,eq&limit=200`,
{ headers: { Authorization: `Bearer ${token}` } },
).then(r => r.json());
for (const s of inactive) {
await fetch(
`https://api.chekt.com/partner/v1/dealers/${dealer}/sites/${s.site_id}/activation-status`,
{
method: "PATCH",
headers: {
Authorization: `Bearer ${token}`,
"x-partner-trace-id": crypto.randomUUID(),
},
},
);
}
}, null, true, "America/Los_Angeles");Cross-dealer fleet dashboard
One view of every site, device, and monitoring station across all dealers connected to your platform.
A platform-scope ETL that pulls sites, devices, monitoring stations, and arming settings from every dealer connected to your platform. Your warehouse holds the union; your BI tool slices by dealer, region, or hardware type. Updates hourly via offset pagination.
Architecture
- 01ETL jobCHeKTFor each connected dealer: GET /dealers/{id}/sites
- 02ETL jobCHeKTGET /devices, /monitoring-stations per dealer
- 03ETL jobWarehouseUpsert by composite (dealer_id, resource_id)
- 04Dashboard UIWarehouseQuery rollups across the entire fleet
What you'll use
Use it for
- Platform partners with hundreds of connected dealers — fleet-wide KPIs
- Customer success teams identifying flaky sites before customers call
- Hardware vendors monitoring deployment health of their devices in the field
Code sketch
// Cross-dealer ETL — pull every dealer your partner credential reaches
async function syncFleet() {
const token = await getAccessToken(); // partner-scoped client credentials
const headers = { Authorization: `Bearer ${token}` };
// Step 1: list dealers you're connected to (your own roster)
for (const dealerId of await db.listConnectedDealers()) {
const sites = await fetch(
`https://api.chekt.com/partner/v1/dealers/${dealerId}/sites?fields=site_id,name,timezone,is_activated&limit=200`,
{ headers },
).then(r => r.json());
await db.sites.upsertMany(sites.map(s => ({ ...s, dealer_id: dealerId })), {
conflictOn: ["dealer_id", "site_id"],
});
// Pull devices per site (parallelise with a small concurrency budget)
for (const s of sites) {
const devices = await fetch(
`https://api.chekt.com/partner/v1/dealers/${dealerId}/sites/${s.site_id}/devices`,
{ headers },
).then(r => r.json());
await db.devices.upsertMany(devices.map(d => ({ ...d, dealer_id: dealerId, site_id: s.site_id })));
}
}
}Dealer connect flow
The opt-in UI that dealer admins click through to bind their dealer to your platform.
The opt-in UI that makes Platform Linking actually start. A dealer admin clicks "Connect CHeKT" in your dashboard, signs into CHeKT, and your code calls PUT /partner/v1/dealers/connect with their authorization access token. Once the bind exists, your partner-scoped credentials can operate on that dealer. Disconnect mirrors the same path.
Architecture
- 01Your dealer UIDealer adminClick "Connect CHeKT"
- 02Dealer adminCHeKT authOAuth: dealer admin signs in to CHeKT and grants access
- 03CHeKT authYour dealer UIAuthorization access token returned
- 04Your dealer UICHeKTPUT /partner/v1/dealers/connect { external_dealer_id, company_name }
- 05CHeKTYour dealer UIResponseDealerDto — your platform can now act on this dealer
What you'll use
Use it for
- Any Platform Linking partner — this is the moment a dealer becomes reachable
- Self-service onboarding flows where new dealers sign up without a sales call
- Multi-product partners where one CHeKT bind unlocks several capabilities
Code sketch
// Connect flow — bind a dealer to your platform
// (run from your dealer-facing UI after the user signs in via CHeKT OAuth)
async function connectDealer(authorizationAccessToken: string, externalDealerId: string, companyName: string) {
const res = await fetch("https://api.chekt.com/partner/v1/dealers/connect", {
method: "PUT",
headers: {
Authorization: `Bearer ${authorizationAccessToken}`, // user's token, NOT your client credentials
"Content-Type": "application/json",
"x-partner-trace-id": crypto.randomUUID(),
},
body: JSON.stringify({
external_dealer_id: externalDealerId,
company_name: companyName,
}),
});
if (!res.ok) throw new Error(`Connect failed: ${res.status}`);
const dealer = await res.json();
// From here on, your partner-scoped client credentials can act on this dealer.
return dealer;
}
// Disconnect mirrors the same flow:
async function disconnectDealer(dealerId: number, authToken: string) {
await fetch(`https://api.chekt.com/partner/v1/dealers/${dealerId}/disconnect`, {
method: "PUT",
headers: { Authorization: `Bearer ${authToken}` },
});
}AI operator assistant
Drop the CHeKT MCP server into Claude or ChatGPT and let an LLM triage the verification queue in plain English.
Drop the CHeKT MCP server into Claude Desktop, ChatGPT Desktop, or your own agent loop. Triage in plain English — "close out anything verified as false-positive at the warehouses tonight" — and let the agent chain through the Partner API with the full audit trail intact.
Architecture
- 01On-call userLLM agent"Show me today's pending verifications at site 12"
- 02LLM agentCHeKT MCPchekt.sites.devices.list / chekt.arming.get
- 03CHeKT MCPPartner APIAuthenticated GET /partner/v1/dealers/{dealerId}/sites/{siteId}/...
- 04Partner APICHeKT MCPJSON results
- 05LLM agentCHeKT MCPchekt.verifications.patch (for confirmed false positives)
- 06LLM agentOn-call userSummarise queue + ask about the rest
What you'll use
Use it for
- Solo on-call shifts where one operator covers many sites and verifications
- Cost-conscious teams using AI to handle routine triage queues
- Power-user operators who prefer typing intent over clicking through a portal
Code sketch
// claude_desktop_config.json — drop CHeKT into Claude
{
"mcpServers": {
"chekt": {
"command": "npx",
"args": ["-y", "@chekt/mcp"],
"env": {
"CHEKT_CLIENT_ID": "<your-client-id>",
"CHEKT_CLIENT_SECRET": "<your-client-secret>",
"CHEKT_DEALER_ID": "<your-dealer-id>"
}
}
}
}
// In Claude:
// "Show pending verifications at site East Bay HQ tonight.
// For motion ones tagged false-positive by AI, mark them as disregard
// with note 'AI: scheduled inspection window'. Leave the rest for me."
//
// Claude chains:
// chekt.sites.list → filter by name
// chekt.verifications.pending → filter by site
// chekt.verifications.patch → action: disregard
// summary back to the operatorNot sure which to start with?
A quick decision flow. None of these answers are wrong — they're just starting shapes you can grow out of.
What's not in this list
These eight examples are starting shapes, not an exhaustive catalog. CHeKT also powers integrations we haven't documented yet — facility-management overlays, access-control bridges, mobile installer apps, and more.
If you have an idea that doesn't fit any of the patterns above, the answer is almost always: start with a CHeKT App, request the smallest permissions, subscribe to the verification webhook, and iterate. Anything the dealer portal can do, the Partner API can do — and anything the Partner API can do, your app can do.