Developer docs · v1.0.0

Assisted living and memory care

Fifty state licensing regimes, one integration: move-in screening, workforce and contractor checks, family-visitor practice and per-community policy in code.

How screening works in assisted living today

Assisted living is licensed and regulated by the states, not certified by CMS. The National Center for Assisted Living's annual *Assisted Living State Regulatory Review* describes a system in which each state sets its own licensing, staffing, training, move-in and disclosure requirements, and the result is real variation: the same operator can run communities under five different rulebooks. Memory care — a secured unit or a dedicated dementia-care licence — adds its own staffing and training rules and, in practice, a more controlled door. Screening is run by the community's executive director, its move-in or sales coordinator, and a regional or corporate HR and compliance function that holds the policy.

Move-in

A move-in begins with a nurse assessment, a negotiated service plan and an admission agreement. Whether it also includes a registry or criminal check of the applicant is a matter of state rule and community policy, and most states say nothing about it. Where a state speaks, it tends to speak about disclosure rather than a check: Virginia requires an assisted living facility to inform each resident, with written acknowledgment, that they may wish to consult the sex offender registry and to assist on request (Va. Code § 63.2-1808(A)(19)), and lets the facility ask the State Police for automatic notice when an offender registers nearby (Va. Code § 9.1-914). Minnesota's registrant-notification statute (Minn. Stat. § 243.166 subd. 4b) puts the disclosure duty on the offender and the notice on law enforcement for the health care facilities it covers; whether a given community falls within it is a licensing question. Illinois' Identified Offenders Program, by contrast, reaches nursing homes and hospitals but not communities licensed under the Assisted Living and Shared Housing Act. Operators that screen applicants anyway do so under their own admission policy, usually at the point the deposit is taken, and usually for both the registry and criminal records in the states the applicant has lived.

Staff and contractors

Here the states are specific, and the specifics differ. Florida requires Level 2 screening — fingerprints through the Care Provider Background Screening Clearinghouse, rescreened every five years — for assisted living personnel who provide personal care or have access to residents' funds, property or living areas (Fla. Stat. §§ 429.174, 408.809(1)(e), 435.04). Washington requires a name-and-date-of-birth check plus a national fingerprint check for the administrator and every caregiver "employed directly or by contract", and the name-and-date-of-birth check for volunteers, students and contractors with unsupervised access (WAC 388-78A-2462); WAC 388-78A-2470 bars employing a registered sex offender or anyone on an abuse, neglect or exploitation registry, and RCW 74.39A.056 requires state and federal checks for all long-term care workers. Oregon makes the licensee responsible for background checks on all "subject individuals", repeated every two years (OAR 411-054-0025). Texas assisted living facilities are "facilities" under Health & Safety Code chapter 250, so the Employee Misconduct Registry and nurse aide registry must be checked before employment, with no direct consumer contact while a criminal history check is pending (§ 250.003). Illinois lists establishments licensed under the Assisted Living and Shared Housing Act as "health care employers" under its Health Care Worker Background Check Act (225 ILCS 46/15), which bars hiring or retaining anyone with a registry finding of abuse, neglect or theft in a direct-care role (225 ILCS 46/25). Communities that bill Medicaid waiver programs also screen staff and contractors against the OIG's LEIE and the state exclusion list on the monthly cadence the OIG recommends (Special Advisory Bulletin, May 2013; 42 CFR 1001.1901).

Family visitors and the memory care door

Assisted living is a residence, and visiting is informal: a sign-in book or tablet at the front, a code or badge at the memory care door, and staff who know the regular visitors by face. Screening of visitors, where it exists, is targeted — a new visitor to a resident with a guardian, a person a family has asked the community to watch for, a state notice — and sits in the community's written visitation policy rather than in a statute. The memory care unit's real controls are elopement prevention and a staffed door, and the visitor log is as much about knowing who was in the building as about screening.

Rules are named, not applied. The citations above locate each rule; they do not say it applies to your community, your role or your decision. State rules change, several reach contractors and volunteers differently, and whether a result may be used at all is for your compliance officer and counsel. The API supplies records with provenance; it does not make a community compliant.

Where the API fits

Workflow stepEndpointFields that matter
Move-in — registry check on the applicant (where policy calls for it)POST /v1/search, all 58 US registriesquery.firstName, lastName, dob; subjectId = resident id, clientId = community; records[].matchState, matchedName.type, registrationState, addressStates, sources[].recordUrl
Move-in — criminal records in the states lived inPOST /v1/criminal/search, cached, one call per statequery.state; records[].recordCategory, cases[].charges[], currentStatus, normalized
Workforce and contractor exclusion check (Medicaid waiver communities)POST /v1/criminal/search with include: ["exclusions"]recordType: "healthcare_exclusion", exclusion.program, authority, convictionBased, excludedOn, reinstatedOn, profession
Per-community policyYour configuration, keyed by clientIdWhich checks run, which states, which roles — set with counsel from the state's rules; the code only reads it
Family visitor at the memory care doorPOST /v1/search with age; see hospitals and visitor management for the kiosk flowquery.age; subjectId = visitor id; status: "partial" → "could not complete"
Look-alike resolved by the executive directorPOST /v1/clearancesproduct, subjectId, clientId, personRef, searchId, verdict: "not_this_person", reviewer, note
Residents and staff stay watchedPOST /v1/monitors, type: "person", one per datasetperson, minConfidence, label (community · person id), channels
The neighbourhood around a community (the API's version of a state's ZIP-code notice)POST /v1/monitors, type: "location"location.address or lat/lng, radiusMiles (0–100, default 3)

Reference integration

The module is written for an operator with several communities. One API key serves all of them; clientId is the community, so a clearance recorded in Austin never hides a record in Tampa; subjectId is your resident or worker id. COMMUNITY_POLICY holds what each community has decided to run — the code reads it and never decides it. move_in_packet returns one Check per policy item for the move-in coordinator to attach to the admission agreement; worker_exclusion_check runs the exclusion tier for staff and contractors with direct access. Run it against the sandbox with an os_test_ key.

"""Assisted living and memory care — move-in and workforce screening for a multi-community operator.
Python 3.11+, requests. Runs against the sandbox with its fixed test names.

  OFFENDERSEARCH_API_KEY   os_test_… (sandbox) or os_live_… (production)
  OFFENDERSEARCH_BASE      https://sandbox.offendersearch.app (default here)

One API key serves every community; clientId (the community id) keeps each community's
clearances to itself, and subjectId (your resident or worker id) ties every search to one person.
"""
from __future__ import annotations

import os
import time
from dataclasses import dataclass, field

import requests

API_KEY = os.environ["OFFENDERSEARCH_API_KEY"]
BASE = os.environ.get("OFFENDERSEARCH_BASE", "https://sandbox.offendersearch.app")
HEADERS = {"X-API-Key": API_KEY, "Content-Type": "application/json"}

# Per-community policy is YOUR configuration, set with counsel from the state's rules — not a statement
# of what any state requires. The code only reads it.
COMMUNITY_POLICY = {

The outcome logic and the reviewer card

OutcomeRuleThe card the coordinator sees
clearrecords empty and status: "complete"; for criminal, counts.sourcesPending also 0The check line reads "clear" with its searchId; the packet proceeds.
reviewCandidates exist, none with the birth date confirmed (matchState is year_match, age_match or no_dob_age_year)Registry: name, aliases, dob/age, matchState, matchBasis, matchedName, registeredBy, livesIn, offense, photo, registryPages. Criminal: recordType, recordCategory, currentStatus, where, one line per charge (description · severity · disposition), the exclusion block when it is a list record, sourcePages.
matchA candidate with matchState: "dob_match"The same card, flagged as the strongest tier. A person compares photo, aliases and addresses against the applicant before anything is decided.
incompletestatus: "partial", or counts.sourcesPending > 0 on a criminal search"A source did not finish" with the names; the check is rerun, not recorded as clear.
skippedThe community's policy does not include this checkShown as skipped, with the policy as the reason, so the packet says what was and was not run.
refused / failed422 (detail on the registry search; error.code and error.message on criminal), 402, other errorsAn operator message; nothing was billed on 429 or 5xx.
Note. The alias scenario matters in senior living: a married name, a maiden name, a shortened first name. The registry search matches aliases and nickname variants itself and tells you when it did (matchedName.type: "alias", matchBasis carrying alias:exact); run a second search only for a prior legal name the applicant gives you, and merge by personRef. See matching and date of birth.

Ongoing monitoring

Residents stay for years and staff turn over quickly, so a move-in or hire-date snapshot ages fast. A person monitor per resident and per worker — one for each dataset you watch — is evaluated once a day and alerts on new, changed and removed events. For a multi-community operator the label is the routing key: put the community id and the person id in it, and the alert reaches the right executive director.

Criminal person monitor for a resident
curl -X POST https://sandbox.offendersearch.app/v1/monitors \
  -H "X-API-Key: $OFFENDERSEARCH_API_KEY" -H "Content-Type: application/json" \
  -d '{
    "product": "criminal",
    "type": "person",
    "person": { "firstName": "Felony", "lastName": "Record", "dob": "1975-06-15" },
    "label": "community-austin-01 · resident-3101",
    "channels": { "emails": ["moveins@your-operator.example.com"] }
  }'
Webhook delivery (type monitor.alert)
{
  "type": "monitor.alert",
  "event": "new",
  "alertId": "hit_2b7e151628ae",
  "monitorId": "mon_7f2a1c9e0b4d",
  "monitorLabel": "community-austin-01 · resident-3101",
  "product": "criminal",
  "detail": {
    "name": "Felony Sample Record",
    "jurisdiction": "OH",
    "locality": "Sampleville",
    "matchLabel": "dob_match",
    "matchConfidence": 0.95,
    "personRef": "prs_1f3a9c0e7b2d4e6f8a1b",
    "recordType": "court_case",
    "externalId": "SBX-CR-2015-000123"
  },
  "occurredAt": "2026-10-25T08:00:00+00:00",
  "sentAt": "2026-10-25T08:04:12+00:00"
}
  • A criminal person monitor alerts on exclusion-list records too (detail.recordType: "healthcare_exclusion" with a detail.exclusion block), which is how a Medicaid waiver community learns about a mid-year exclusion between monthly runs.
  • A location monitor around each community (type: "location", radiusMiles) alerts when a registrant's published address enters or leaves the radius — useful where a state offers a ZIP-code notice and where it does not.
  • Deliveries are signed with the monitor's webhookSecret; verify the header before acting. Cancel monitors at move-out and separation; cancelled monitors and their alerts stay readable.

See person monitoring, location monitoring and delivery.

When this is FCRA

Screening an applicant for move-in is a residential admission under your state's assisted living rules and your policy — not a tenant-screening or credit decision in the FCRA's sense for most communities, though counsel should confirm that for a community whose agreement is structured as a lease. Screening workers is different: deciding whether to hire, retain or assign an employee, agency caregiver or contractor is an employment purpose, and a report procured for it is a consumer report. The self-service API's legal.notice says it may not be used for any FCRA purpose. That workflow belongs on the FCRA Partner API — end users with certified purposes, consent attestations, a criminal search whose exclusions mode furnishes the same exclusion-list records, disputes and signed webhooks — available to approved partners; others receive 403 fcra_not_enabled. worker_exclusion_check above shows the records and fields; where your counsel treats a given workforce screen as a consumer-report use, run it as an FCRA order instead.

Evidence and audit

  • The move-in packet. File each Check with its searchId, outcome, the status/counts/sourceStatus[] of the response and the coordinator's decision. A state surveyor reviewing a resident file then sees what was checked and what it showed.
  • Verification report. POST /v1/report (registry) or POST /v1/criminal/report (criminal) with the searchId renders a timestamped PDF with every record, every field and a source citation per record, +$0.02; render it when the decision is made. Reports, criminal reports.
  • Registry page as evidence. live: { "jurisdictions": [...], "evidence": "pdf" } prints the named registries' own pages; the 202 carries a pollUrl, the finished search carries evidence[].downloadUrl, readable for 30 days. Live evidence.
  • Clearances. Every not_this_person verdict names the searchId, reviewer and note, and survives revocation for the audit trail. GET /v1/clearances?subjectId=…&clientId=… lists a resident's. Clearances.
  • Retention. Searches are kept in the account history for 14 days; store what you need to keep on your side, under your records-retention policy. Resident data is protected health information — backend calls over TLS, minimum fields, a BAA from Dashboard → BAA where counsel requires one.

Rollout plan

  1. Write the policy table first. For each community, decide with counsel which checks run at move-in, for which worker roles, in which states — and record it as the COMMUNITY_POLICY configuration. The code must be able to say "skipped by policy" as clearly as it says "clear".
  2. Run the sandbox module. Create an account, mint an os_test_ key in Dashboard → API keys, run the module against https://sandbox.offendersearch.app and check each test name against the expected outcome, especially the alias and review cases.
  3. Build the card and the two buttons. The reviewer card from the table above, the registry's own page via registryPages, and "this person" / "not this person" wired to POST /v1/clearances with the community as clientId.
  4. Pilot one community. Swap to an os_live_ key for one community, run move-ins and the workforce check alongside the current process, and review every review outcome with the executive director to calibrate what the policy says about each tier.
  5. Add monitoring and the other communities. Create monitors for current residents and staff with label = community · person id, verify the webhook, then add communities one clientId at a time. Confirm with counsel which worker screens move to the FCRA Partner API before a hiring decision depends on one.