Loading documentation

Access required

Your account doesn't have access to the documentation. Contact your administrator.

Sign out
Skip to main content

Recordability Analyze

Status: stable Category: recordability Added: 2026-07-01 Last reviewed: 2026-07-01

Summary

Run the full OSHA 29 CFR 1904 recordability composite over one de-identified injury or illness case. Five key factors are analyzed concurrently — work-relatedness (1904.5), the 1904.5(b)(2) exceptions, new case vs. recurrence/aggravation (1904.6, 1904.5(b)(4)), treatment beyond first aid (1904.7(b)(5)), and condition significance plus the specific recording criteria (1904.7(b)(7), 1904.8–1904.11) — each a cited AI analysis grounded only in stored regulation text and official OSHA guidance. A deterministic combiner then folds the five factors along the 1904.4 decision tree into a single recordability_score with a confidence report, a criteria transparency block, and a merged missing-information list.

The engine never makes the final determination. The recordability_score is weighted, cited decision support. A qualified professional — whoever owns your OSHA 300 log — reviews the factors, weighs the citations, and makes the recordability call. Treat every response from this endpoint as an input to that judgment, never as a substitute for it.

Endpoint

FieldValue
MethodPOST
Path/api/recordability/analyze
Full URLhttps://engine.tripod-health.com/api/recordability/analyze
AuthenticationAPI key (required)
Request bodyapplication/json
Response bodyapplication/json
IdempotentNo (each call may reason slightly differently over the same case)
Rate-limitedYes

Expect latency in the tens of seconds: the five factor analyses run concurrently, so total time tracks the slowest single analysis, not the sum — but each is a substantial AI analysis. Set client timeouts to at least 90 seconds.

Every factor's generated text passes the engine's outbound de-identification scan before returning; identifier-shaped output fails the call with 502 UpstreamError rather than scrubbing silently.

Purpose

Answers the whole recordability question in one call: "does this case belong on the OSHA 300 log, and why?" The response decomposes the answer the way 1904.4 does — a case is recordable when it is work-related AND a new case AND meets at least one recording criterion, with a ruled-in 1904.5(b)(2) exception negating work-relatedness — so a reviewer can see exactly which branch of the decision tree a gray case turns on. Deterministic work_status facts (fatality, days away, restricted duty or job transfer, loss of consciousness) satisfy the recording-criterion branch directly, without AI judgment.

If you only need one factor, use the single-factor endpoints documented in recordability-factor.md — they accept the same case body and cost a fraction of the composite. If you only need work-relatedness, use POST /api/work_relatedness/analyze.

Authentication

Standard API-key. Set apikey: $ENGINE_API_KEY on the request. See authentication.md.

Request

Headers

HeaderRequiredNotes
apikeyYesYour engine API key.
Content-TypeYesapplication/json.
X-Request-IDNoEchoed back; lets you correlate logs.

Path parameters

None.

Query parameters

None.

Body

The body is a de-identified case object plus an optional lens. Only case.incident.description and case.injury.description (and their parent objects) are required — everything else is optional, and every optional block you populate raises the confidence report's input_completeness term. Unrecognized fields anywhere in the body are rejected with 400 ValidationError.

{
"case": {
"incident": {
"description": "Employee slipped on ice in the company parking lot while walking from their parked car to the building entrance at the start of their shift, landing on their right side.",
"incident_date": "2026-06-22",
"reported_date": "2026-06-24",
"location_context": "parking_lot",
"activity_at_time": "walking from personal vehicle to the building entrance before clocking in",
"during_assigned_hours": false
},
"injury": {
"description": "Right shoulder pain and limited range of motion, worsening over two days after the fall.",
"body_part": "right shoulder",
"diagnosis": "rotator cuff strain",
"symptom_onset_date": "2026-06-22",
"onset_type": "acute"
},
"employee": {
"job_title": "warehouse associate",
"job_duties": "Repetitive overhead lifting of boxes up to 50 lbs, pallet loading, operating a manual pallet jack across an 8-hour shift.",
"tenure_bracket": "1-3 years"
},
"treatment": {
"provided": [
"ice pack applied on site",
"prescription naproxen",
"referral to physical therapy"
],
"provider_type": "occupational medicine clinic",
"prescription_issued": true
},
"prior_condition": {
"exists": true,
"description": "Prior right shoulder impingement treated with physical therapy, resolved eight months before this incident.",
"prior_incident_date": "2025-10-15"
},
"statements": [
{
"source": "employee",
"text": "I parked in the employee lot and slipped on a patch of ice near the walkway. I did not think it was serious until the shoulder got worse at work."
},
{
"source": "witness",
"text": "Another employee saw the fall from the entrance and helped the employee up."
}
],
"work_status": {
"days_away": 0,
"restricted_duty": true
}
},
"lens": "safety"
}

Body fields

FieldTypeRequiredConstraintsDescription
caseobjectYesThe de-identified case under analysis.
case.incidentobjectYesWhat happened.
case.incident.descriptionstringYes1–8,000 charsFree-text narrative of the event or exposure. Refer to people by role, never by name.
case.incident.incident_datestring (date)NoYYYY-MM-DDDate of the event or exposure.
case.incident.reported_datestring (date)NoYYYY-MM-DDWhen the incident was reported to the employer; the gap from incident_date is a corroboration signal.
case.incident.location_contextenumNoon_premises, parking_lot, company_travel, work_from_home, offsite_work, non_work_location, unknownWhere the event occurred, in work-environment terms.
case.incident.activity_at_timestringNo≤ 1,000 charsWhat the employee was doing when the event occurred.
case.incident.during_assigned_hoursbooleanNoWhether the event occurred during assigned working hours.
case.injuryobjectYesThe resulting injury or illness.
case.injury.descriptionstringYes1–8,000 charsFree-text narrative of the injury or illness.
case.injury.body_partstringNo≤ 200 charsAffected body part.
case.injury.diagnosisstringNo≤ 500 charsClinical diagnosis, if one exists.
case.injury.icd_categorystringNo≤ 40 charsICD category code (structural descriptor, not a patient identifier).
case.injury.symptom_onset_datestring (date)NoYYYY-MM-DDWhen symptoms first appeared; may differ from incident_date.
case.injury.onset_typeenumNoacute, gradual, unknownDiscrete acute event vs. gradual/cumulative onset — the analysis differs materially between the two.
case.employeeobjectNoStructural description of the job, never of the person.
case.employee.job_titlestringNo≤ 200 charsJob title.
case.employee.job_dutiesstringNo≤ 2,000 charsWhat the job actually involves (physical demands, typical tasks); grounds mechanism-plausibility reasoning beyond a bare title.
case.employee.departmentstringNo≤ 200 charsDepartment or work area.
case.employee.tenure_bracketstringNo≤ 40 charsTenure as a bracket (e.g. "1-3 years"), never a hire date.
case.treatmentobjectNoTreatment provided so far.
case.treatment.providedarray of stringNo≤ 25 entries, each 1–1,000 charsEach treatment provided, one entry per intervention.
case.treatment.provider_typestringNo≤ 200 charsType of provider (e.g. "occupational medicine clinic").
case.treatment.prescription_issuedbooleanNoWhether any prescription was issued.
case.prior_conditionobjectNoPre-existing condition affecting the same region, if any.
case.prior_condition.existsbooleanNoWhether a relevant prior condition exists.
case.prior_condition.descriptionstringNo≤ 4,000 charsFree-text description of the prior condition and its resolution.
case.prior_condition.prior_incident_datestring (date)NoYYYY-MM-DDDate of the prior incident or episode.
case.statementsarrayNo≤ 20 entriesStatements gathered during the investigation.
case.statements[].sourceenumYes (per entry)employee, witness, clinician, employer, injury_reportWho the statement is from, by role.
case.statements[].textstringYes (per entry)1–8,000 charsThe statement text. Refer to people by role only.
case.work_statusobjectNoDeterministic outcome facts; these satisfy recording criteria directly, without AI judgment.
case.work_status.days_awayintegerNo0 ≤ n ≤ 3650Days away from work.
case.work_status.restricted_dutybooleanNoWhether the employee was placed on restricted duty.
case.work_status.job_transferbooleanNoWhether the employee was transferred to another job.
case.work_status.loss_of_consciousnessbooleanNoWhether the employee lost consciousness.
case.work_status.fatalitybooleanNoWhether the case was fatal.
lensenumNosafety, occupational_medicineReasoning-style flavor only: safety frames the reasoning in exposure/process terms, occupational_medicine in clinical terms. The determination itself never differs by lens.

De-identification requirement

The case must describe a person structurally, never identifiably. Free-text fields must not contain names, initials, SSN-shaped values, email addresses, or phone numbers — refer to people by role ("the employee," "a witness," "the treating clinician"). Precise calendar dates are normally rejected as potential dates of birth, but the four named event-date fields — incident_date, reported_date, symptom_onset_date, and prior_incident_date — are exempt: an event date does not identify a person, and the timing gaps between them are analytically load-bearing. A body containing an identifier returns 400 DeIdentificationViolation naming the offending field. See the De-identification contract section below and conventions.md.

Response

Success — 200 OK

The response below is a real run over the example case above — a parking-lot slip with a prior shoulder condition, a genuinely gray case. For readability, each factor's reasoning is compacted to its opening sentences, citations are trimmed to two or three per factor, and repeated items and missing_information entries are trimmed; in production, reasoning runs several paragraphs per factor, citations run up to 12, and every exception and specific criterion is ruled in or out individually. All scores, leanings, likelihoods, certainties, and the criteria_met block are verbatim.

{
"recordability_score": 0.517,
"confidence": {
"overall": 0.9172,
"tier": "high",
"breakdown": {
"input_completeness": 1,
"model_certainty": 0.862
}
},
"criteria_met": {
"fatality": false,
"days_away": false,
"restricted_duty_or_transfer": true,
"loss_of_consciousness": false,
"medical_treatment_beyond_first_aid": "yes",
"significant_condition_or_specific_criteria": "yes"
},
"factors": {
"work_relatedness": {
"likelihood": 0.78,
"leaning": "yes",
"reasoning": "The employee slipped on ice in the employer's parking lot while walking from their vehicle to the building entrance at the start of their shift. This case hinges on whether the injury is work-related despite occurring before clocking in and on the application of the motor vehicle exception in 1904.5(b)(2)(vii).",
"citations": [
{
"source_type": "regulation",
"ref": "1904.5(a)",
"quote": "You must consider an injury or illness to be work-related if an event or exposure in the work environment either caused or contributed to the resulting condition or significantly aggravated a pre-existing injury or illness."
},
{
"source_type": "regulation",
"ref": "1904.5(b)(1)",
"quote": "OSHA defines the work environment as 'the establishment and other locations where one or more employees are working or are present as a condition of their employment.'"
},
{
"source_type": "faq",
"ref": "5-10",
"quote": "Company parking lots are part of the employer's premises and therefore part of the establishment... those parking areas where the employer can limit access (such as parking lots limited to the employer's employees and visitors)."
}
],
"items": [
{
"key": "geographic_presumption",
"determination": "yes",
"note": "Employee slipped in the company parking lot while walking to the building entrance at the start of shift. Per 5-10 FAQ, company parking lots are part of employer premises under the employer's control. Per 5-11 FAQ, injuries in the work environment are work-related even if the employee has not clocked in."
},
{
"key": "preexisting_contribution",
"determination": "unsure",
"note": "Prior right shoulder impingement resolved approximately eight months before incident. While the prior condition may have left residual vulnerability, the acute trauma (fall on ice) is a distinct and proximate workplace event. Evidence does not clearly establish whether prior condition significantly contributed or merely coincided with new trauma; however, 1904.5(b)(4)(iv) is satisfied if workplace event necessitated medical treatment not previously needed."
}
],
"missing_information": [
"Whether the company parking lot is under the employer's exclusive control or is shared with other businesses or public (needed to confirm 5-10 geographic presumption)."
],
"certainty": 0.82
},
"exceptions": {
"likelihood": 0.15,
"leaning": "no",
"reasoning": "The employee slipped on ice in a company parking lot while walking from their personal vehicle to the building entrance before clocking in. The injury—a rotator cuff strain to the right shoulder—is the acute result of that fall.",
"citations": [
{
"source_type": "regulation",
"ref": "1904.5(a)",
"quote": "Work-relatedness is presumed for injuries and illnesses resulting from events or exposures occurring in the work environment, unless an exception in § 1904.5(b)(2) specifically applies."
},
{
"source_type": "regulation",
"ref": "1904.5(b)(2)(vii)",
"quote": "The injury or illness is caused by a motor vehicle accident and occurs on a company parking lot or company access road while the employee is commuting to or from work."
},
{
"source_type": "faq",
"ref": "5-11",
"quote": "Yes. For purposes of OSHA recordkeeping injuries and illnesses occurring in the work environment are considered work-related. Punching in and out with a time clock (or signing in and out) does not affect the outcome for determining work-relatedness."
}
],
"items": [
{
"key": "1904.5(b)(2)(vii)",
"determination": "no",
"note": "This exception applies only to motor vehicle accidents; the injury resulted from a pedestrian slip on ice, not a vehicle accident."
}
],
"missing_information": [
"Whether the parking lot is truly under employer control (e.g., exclusive employee use, employer-maintained, employer-cleared of ice/snow)"
],
"certainty": 0.9
},
"recurrence": {
"likelihood": 0.78,
"leaning": "yes",
"reasoning": "This case presents a NEW work-related injury that must be recorded as a distinct case, not a continuation or simple recurrence of the prior shoulder condition. Although the employee has a documented history of right shoulder impingement treated roughly eight months before the current incident, the facts strongly support classification as a new case under 1904.6(a)(2) coupled with significant aggravation of a pre-existing condition under 1904.5(b)(4).",
"citations": [
{
"source_type": "regulation",
"ref": "1904.6(a)(2)",
"quote": "The employee previously experienced a recorded injury or illness of the same type that affected the same part of the body but had recovered completely (all signs and symptoms had disappeared) from the previous injury or illness and an event or exposure in the work environment caused the signs or symptoms to reappear."
},
{
"source_type": "regulation",
"ref": "1904.5(b)(4)(iv)",
"quote": "Medical treatment in a case where no medical treatment was needed for the injury or illness before the workplace event or exposure, or a change in medical treatment was necessitated by the workplace event or exposure."
}
],
"items": [
{
"key": "Prior condition fully resolved",
"determination": "yes",
"note": "Shoulder impingement was treated with physical therapy and resolved completely roughly eight months before the current incident. No ongoing symptoms or restrictions are documented in the interval."
},
{
"key": "Case qualifies as new under 1904.6(a)(2)",
"determination": "yes",
"note": "Complete recovery from prior condition plus a workplace event causing reappearance of signs/symptoms. Falls squarely within the regulation."
}
],
"missing_information": [
"Documentation of whether the employee had any ongoing pain, stiffness, or activity limitation from the prior impingement during the eight-month interval (to conclusively establish 'complete recovery')"
],
"certainty": 0.82
},
"treatment": {
"likelihood": 0.85,
"leaning": "yes",
"reasoning": "The employee sustained an acute rotator cuff strain from a slip-and-fall in the parking lot at the start of their shift. Occupational medicine evaluated the injury and provided three interventions: on-site ice pack, a prescription for naproxen, and referral to physical therapy.",
"citations": [
{
"source_type": "regulation",
"ref": "1904.7(b)(5)(ii)(A)",
"quote": "Using a non-prescription medication at nonprescription strength (for medications available in both prescription and non-prescription form, a recommendation by a physician or other licensed health care professional to use a non-prescription medication at prescription strength is considered medical treatment for recordkeeping purposes)"
},
{
"source_type": "regulation",
"ref": "1904.7(b)(5)(ii)(M)",
"quote": "Using massages (physical therapy or chiropractic treatment are considered medical treatment for recordkeeping purposes)"
},
{
"source_type": "faq",
"ref": "7-10a",
"quote": "In the case of prescription medications, OSHA considers that medical treatment is provided once a prescription is issued."
}
],
"items": [
{
"key": "Ice pack applied on site",
"determination": "no",
"note": "Meets first-aid definition at 1904.7(b)(5)(ii)(E): 'Using hot or cold therapy.'"
},
{
"key": "Prescription naproxen",
"determination": "yes",
"note": "Prescription medication is medical treatment beyond first aid. Non-prescription medications at non-prescription strength are first aid (1904.7(b)(5)(ii)(A)). Prescription issuance constitutes provision of medical treatment per guidance 7-10a."
},
{
"key": "Referral to physical therapy",
"determination": "yes",
"note": "Physical therapy is explicitly listed as medical treatment, not first aid, per 1904.7(b)(5)(ii)(M): 'physical therapy or chiropractic treatment are considered medical treatment for recordkeeping purposes.'"
}
],
"missing_information": [],
"certainty": 0.92
},
"significance": {
"likelihood": 0.72,
"leaning": "yes",
"reasoning": "The employee sustained an acute rotator cuff strain with associated right shoulder pain and restricted range of motion diagnosed by an occupational medicine clinic following a fall in the company parking lot. This injury meets multiple general recording criteria under 1904.7, making the \"significant condition\" prong less determinative, but warrants careful evaluation.",
"citations": [
{
"source_type": "regulation",
"ref": "1904.7(b)(7)",
"quote": "Work-related cases involving cancer, chronic irreversible disease, a fractured or cracked bone, or a punctured eardrum must always be recorded under the general criteria at the time of diagnosis by a physician or other licensed health care professional."
},
{
"source_type": "regulation",
"ref": "1904.7(b)(5)",
"quote": "If a work-related injury or illness results in medical treatment beyond first aid, you must record it on the OSHA 300 Log."
}
],
"items": [
{
"key": "Fracture or cracked bone (1904.7(b)(7))",
"determination": "no",
"note": "Diagnosed condition is rotator cuff strain, a soft-tissue injury, not a fracture or cracked bone."
},
{
"key": "Needlestick or sharps injury (1904.8)",
"determination": "no",
"note": "Slip-and-fall injury; no contaminated sharps or bloodborne pathogen exposure."
}
],
"missing_information": [
"Whether the restricted duty imposed or recommended restricts one or more of the employee's routine job functions (overhead lifting, pallet loading, operating a manual pallet jack)—if yes, the case is recordable under 1904.7(b)(4) regardless of significance."
],
"certainty": 0.85
}
},
"missing_information": [
"Whether the company parking lot is under the employer's exclusive control or is shared with other businesses or public (needed to confirm 5-10 geographic presumption).",
"Witness name and statement details regarding exactly what was observed and whether any vehicle involvement occurred.",
"Medical record from occupational medicine clinic detailing examination findings, diagnosis rationale, and whether prior shoulder impingement showed clinical evidence of reactivation or fresh trauma.",
"Employer's incident reporting policy and whether the two-day reporting delay was standard practice or unusual."
],
"catalog_version": "0.20.0",
"request_id": "15f34e08-f3db-446a-aef6-7e30534f3191",
"timestamp": "2026-07-02T00:44:41.083196+00:00"
}

Note what the gray case does to the numbers: every factor leans yes, yet recordability_score lands at 0.517 rather than near 1.0 — the pre-shift parking-lot setting, the prior shoulder condition, and the two-day reporting delay all pull weight out of the composite even though no single factor flips. That is the score doing its job: signaling "this needs a human look," not "record it."

Response fields

FieldTypeAlways presentDescription
recordability_scorenumberYes0.0001.000. Weighted composite folded along the 1904.4 decision tree. Decision support for the reviewer, never a determination.
confidenceobjectYesHow much to trust this run.
confidence.overallnumberYes01 blended confidence.
confidence.tierstringYesBanded label for overall (e.g. "high").
confidence.breakdownobjectYesThe terms behind overall.
confidence.breakdown.input_completenessnumberYes01. How much of the optional case structure you supplied; every populated optional block raises it.
confidence.breakdown.model_certaintynumberYes01. Aggregated per-factor certainty — the analyses' own read of how much reliable information they had.
criteria_metobjectYesTransparency block for the 1904.7 recording-criterion branch.
criteria_met.fatalitybooleanYesDeterministic, from work_status.fatality.
criteria_met.days_awaybooleanYesDeterministic, from work_status.days_away.
criteria_met.restricted_duty_or_transferbooleanYesDeterministic, from work_status.restricted_duty / work_status.job_transfer.
criteria_met.loss_of_consciousnessbooleanYesDeterministic, from work_status.loss_of_consciousness.
criteria_met.medical_treatment_beyond_first_aidenumYesyes | no | unsure — the treatment factor's leaning.
criteria_met.significant_condition_or_specific_criteriaenumYesyes | no | unsure — the significance factor's leaning.
factorsobjectYesAll five full factor assessments, keyed work_relatedness, exceptions, recurrence, treatment, significance.
factors.<factor>.likelihoodnumberYes01 likelihood of the factor's factor-specific question.
factors.<factor>.leaningenumYesyes | no | unsure.
factors.<factor>.reasoningstringYesThe cited analysis narrative — several paragraphs in production.
factors.<factor>.citationsarrayYes1–12 entries; every passage the analysis relied on.
factors.<factor>.citations[].source_typeenumYesregulation | faq | interpretation | preamble.
factors.<factor>.citations[].refstringYesThe cited reference (e.g. "1904.5(b)(2)(vii)", FAQ "5-10").
factors.<factor>.citations[].quotestring | nullNoThe quoted passage, when one was quoted.
factors.<factor>.itemsarray | nullNoPer-item determinations where the factor decomposes — one row per 1904.5(b)(2) exception, per treatment classified against the first-aid list, per specific criterion, per work-relatedness dimension.
factors.<factor>.items[].keystringYesWhat the row rules on.
factors.<factor>.items[].determinationenumYesyes | no | unsure.
factors.<factor>.items[].notestring | nullNoOne-row rationale.
factors.<factor>.missing_informationarray of stringYesUp to 10 facts that would sharpen this factor. May be empty.
factors.<factor>.certaintynumberYes01. The analysis's own read of how much reliable information it had for this factor — distinct from likelihood.
missing_informationarray of stringYesMerged, deduplicated union of every factor's list — an investigation checklist for the case.
catalog_versionstringYesVersion of the stored regulation-and-guidance catalog the citations were drawn from.
request_idstringYesCorrelation ID. Echo it in support tickets.
timestampstringYesISO 8601, UTC.

The five factors

KeyQuestion it answersGrounded in
work_relatednessDid an event or exposure in the work environment cause, contribute to, or significantly aggravate the condition?1904.5
exceptionsDoes one of the nine 1904.5(b)(2) exceptions negate work-relatedness? Each exception is ruled in or out individually in items.1904.5(b)(2)
recurrenceIs this a new case rather than a recurrence, and does any aggravation of a prior condition qualify as significant?1904.6, 1904.5(b)(4)
treatmentDid treatment go beyond the exhaustive first-aid list? Each treatment in case.treatment.provided is classified individually in items.1904.7(b)(5)
significanceIs the condition a significant injury or illness, or does it meet a specific recording criterion?1904.7(b)(7), 1904.8–1904.11

The deterministic combiner folds them the way 1904.4 does: a case is recordable when it is work-related AND a new case AND meets at least one recording criterion; a ruled-in exception negates work-relatedness. The deterministic criteria_met booleans satisfy the recording-criterion branch directly — if work_status reports a fatality or days away, that branch is settled fact, not AI judgment.

Status codes

CodeMeaningWhen
200OKComposite analysis completed.
400ValidationErrorBody shape, enum violation, over-length field, or an unrecognized field. field names the offender when known.
400DeIdentificationViolationThe body carries an identifier-shaped value — including a precise date outside the four exempt event-date fields.
401UnauthenticatedMissing or invalid API key.
413PayloadTooLargeBody exceeds 512 KB.
415UnsupportedMediaTypeContent-Type is not application/json.
429RateLimitedPer-consumer rate limit exceeded. Respect Retry-After.
500InternalErrorUnexpected failure. Report the request_id.
502UpstreamErrorAn AI factor analysis failed, or its output failed the outbound safety scan. Safe to retry once.
504UpstreamTimeoutAn AI factor analysis exceeded the engine's time budget.

Error envelope

All non-2xx responses use the uniform envelope:

{
"timestamp": "2026-07-01T17:32:10.812Z",
"error": "DeIdentificationViolation",
"message": "Field 'case.statements[0].text' appears to contain an email address",
"request_id": "8f2c3b1d-5e4a-4a9c-9b1e-2a7f1d3e4c5b",
"field": "case.statements[0].text"
}

See errors.md for the full code taxonomy and extras.

Examples

curl

curl -sS -X POST "https://engine.tripod-health.com/api/recordability/analyze" \
--max-time 120 \
-H "apikey: $ENGINE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"case": {
"incident": {
"description": "Employee slipped on ice in the company parking lot while walking from their parked car to the building entrance at the start of their shift, landing on their right side.",
"incident_date": "2026-06-22",
"reported_date": "2026-06-24",
"location_context": "parking_lot",
"activity_at_time": "walking from personal vehicle to the building entrance before clocking in",
"during_assigned_hours": false
},
"injury": {
"description": "Right shoulder pain and limited range of motion, worsening over two days after the fall.",
"body_part": "right shoulder",
"diagnosis": "rotator cuff strain",
"symptom_onset_date": "2026-06-22",
"onset_type": "acute"
},
"employee": {
"job_title": "warehouse associate",
"job_duties": "Repetitive overhead lifting of boxes up to 50 lbs, pallet loading, operating a manual pallet jack across an 8-hour shift.",
"tenure_bracket": "1-3 years"
},
"treatment": {
"provided": [
"ice pack applied on site",
"prescription naproxen",
"referral to physical therapy"
],
"provider_type": "occupational medicine clinic",
"prescription_issued": true
},
"prior_condition": {
"exists": true,
"description": "Prior right shoulder impingement treated with physical therapy, resolved eight months before this incident.",
"prior_incident_date": "2025-10-15"
},
"statements": [
{
"source": "employee",
"text": "I parked in the employee lot and slipped on a patch of ice near the walkway. I did not think it was serious until the shoulder got worse at work."
},
{
"source": "witness",
"text": "Another employee saw the fall from the entrance and helped the employee up."
}
],
"work_status": {
"days_away": 0,
"restricted_duty": true
}
},
"lens": "safety"
}'

Python (requests)

# Uses the call() helper from quickstart.md; raise its timeout to 120 s
# for this endpoint.
result = call("POST", "/api/recordability/analyze", {
"case": {
"incident": {
"description": "Employee slipped on ice in the company parking lot while walking from their parked car to the building entrance at the start of their shift, landing on their right side.",
"incident_date": "2026-06-22",
"reported_date": "2026-06-24",
"location_context": "parking_lot",
"activity_at_time": "walking from personal vehicle to the building entrance before clocking in",
"during_assigned_hours": False,
},
"injury": {
"description": "Right shoulder pain and limited range of motion, worsening over two days after the fall.",
"body_part": "right shoulder",
"diagnosis": "rotator cuff strain",
"symptom_onset_date": "2026-06-22",
"onset_type": "acute",
},
"employee": {
"job_title": "warehouse associate",
"job_duties": "Repetitive overhead lifting of boxes up to 50 lbs, pallet loading, operating a manual pallet jack across an 8-hour shift.",
"tenure_bracket": "1-3 years",
},
"treatment": {
"provided": [
"ice pack applied on site",
"prescription naproxen",
"referral to physical therapy",
],
"provider_type": "occupational medicine clinic",
"prescription_issued": True,
},
"prior_condition": {
"exists": True,
"description": "Prior right shoulder impingement treated with physical therapy, resolved eight months before this incident.",
"prior_incident_date": "2025-10-15",
},
"statements": [
{
"source": "employee",
"text": "I parked in the employee lot and slipped on a patch of ice near the walkway. I did not think it was serious until the shoulder got worse at work.",
},
{
"source": "witness",
"text": "Another employee saw the fall from the entrance and helped the employee up.",
},
],
"work_status": {
"days_away": 0,
"restricted_duty": True,
},
},
"lens": "safety",
})

print(f"score: {result['recordability_score']}")
print(f"confidence: {result['confidence']['tier']}")
for key, factor in result["factors"].items():
print(f"- {key}: {factor['leaning']} ({factor['likelihood']})")
print("Still to investigate:")
for item in result["missing_information"]:
print("-", item)

Node.js (native fetch) — minimum viable case

Only the two descriptions are required. A minimal case is valid but lands with a lower confidence.breakdown.input_completeness and a longer missing_information list — the analyses tell you what they were missing.

// Uses the call() helper from quickstart.md; raise its timeout to 120 s
// for this endpoint.
const result = await call("POST", "/api/recordability/analyze", {
case: {
incident: {
description:
"Employee slipped on ice in the company parking lot while walking to the building entrance at the start of their shift.",
},
injury: {
description:
"Right shoulder pain and limited range of motion, worsening over two days after the fall.",
},
},
});

console.log("score:", result.recordability_score);
console.log("input completeness:", result.confidence.breakdown.input_completeness);
console.log("investigate next:", result.missing_information);

Intended use

  • Full recordability decision support for an OSHA 300 log determination — one call returns all five factors, the decision-tree fold, and the citations the reviewer needs to check the reasoning.
  • Surfacing which factors drive a gray case: a mid-range recordability_score with the per-factor likelihoods and leanings shows exactly where the case is contested.
  • Getting the merged missing_information list as an investigation checklist — run early with what you have, collect what the response names, and re-run richer.
  • Feeding the resulting recordable/not-recordable decision (made by your professional) into OSHA-300 rate math via POST /api/naics/calculate.

Mistaken use

  • Needing only one factor — classifying treatments against the first-aid list, or ruling the nine exceptions in or out. Use the single-factor endpoints (recordability-factor.md) instead; they take the same case body at a fraction of the cost.
  • Needing only the work-relatedness determination. Use POST /api/work_relatedness/analyze instead — it adds the per-dimension presumption breakdown this composite does not surface.
  • Treating recordability_score as the final determination. It never is. The score is weighted, cited decision support; a qualified professional makes the recordability call and owns the OSHA 300 entry.
  • Sending lens expecting a different answer. lens changes the reasoning's framing for its reader, never the determination.

De-identification contract

This endpoint enforces both directions of the engine's de-id contract:

  • Inbound: the case must describe the person structurally. Free-text fields (description, activity_at_time, job_duties, statements[].text, ...) must never contain names, initials, SSN-shaped values, email addresses, or phone numbers — refer to people by role. Precise dates are normally rejected as potential dates of birth; the named event-date fields (incident_date, reported_date, symptom_onset_date, prior_incident_date) are exempt, because an event date does not identify a person. Failures return 400 DeIdentificationViolation with field naming the offender. See conventions.md.
  • Outbound: every generated reasoning, note, and missing_information string is scanned for identifier shapes before the response returns. A match fails the call with 502 UpstreamError; the engine never silently scrubs.

Debugging

Checklist when a call fails:

  1. Capture the request_id from the response body (success or error). Every support ticket starts here.
  2. 400 DeIdentificationViolation — the field extra names the offending path. Check free text for names or initials, and check for precise dates outside the four exempt event-date fields.
  3. 400 ValidationError — check enum values (location_context, onset_type, statements[].source, lens), field lengths, and for unrecognized fields — the body schema is strict.
  4. 401 Unauthenticated — confirm the apikey header is present and the key is active.
  5. 429 RateLimited — respect the Retry-After header; back off.
  6. 502 UpstreamError — a factor analysis failed or its output failed the outbound safety scan. Safe to retry once; if it persists, file a ticket with the request_id.
  7. 504 UpstreamTimeout or a client-side timeout — this endpoint runs tens of seconds. Confirm your client timeout is at least 90 seconds before assuming the engine failed.

Rate limits

Per-consumer limits are managed at the gateway. See rate-limits.md. This is one of the engine's heavier calls — see credits.md for how it is metered.

Change history

DateChange
2026-07-01Initial publication.