Recordability Analyze
Status:
stableCategory:recordabilityAdded:2026-07-01Last 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_scoreis 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
| Field | Value |
|---|---|
| Method | POST |
| Path | /api/recordability/analyze |
| Full URL | https://engine.tripod-health.com/api/recordability/analyze |
| Authentication | API key (required) |
| Request body | application/json |
| Response body | application/json |
| Idempotent | No (each call may reason slightly differently over the same case) |
| Rate-limited | Yes |
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
| Header | Required | Notes |
|---|---|---|
apikey | Yes | Your engine API key. |
Content-Type | Yes | application/json. |
X-Request-ID | No | Echoed 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
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
case | object | Yes | — | The de-identified case under analysis. |
case.incident | object | Yes | — | What happened. |
case.incident.description | string | Yes | 1–8,000 chars | Free-text narrative of the event or exposure. Refer to people by role, never by name. |
case.incident.incident_date | string (date) | No | YYYY-MM-DD | Date of the event or exposure. |
case.incident.reported_date | string (date) | No | YYYY-MM-DD | When the incident was reported to the employer; the gap from incident_date is a corroboration signal. |
case.incident.location_context | enum | No | on_premises, parking_lot, company_travel, work_from_home, offsite_work, non_work_location, unknown | Where the event occurred, in work-environment terms. |
case.incident.activity_at_time | string | No | ≤ 1,000 chars | What the employee was doing when the event occurred. |
case.incident.during_assigned_hours | boolean | No | — | Whether the event occurred during assigned working hours. |
case.injury | object | Yes | — | The resulting injury or illness. |
case.injury.description | string | Yes | 1–8,000 chars | Free-text narrative of the injury or illness. |
case.injury.body_part | string | No | ≤ 200 chars | Affected body part. |
case.injury.diagnosis | string | No | ≤ 500 chars | Clinical diagnosis, if one exists. |
case.injury.icd_category | string | No | ≤ 40 chars | ICD category code (structural descriptor, not a patient identifier). |
case.injury.symptom_onset_date | string (date) | No | YYYY-MM-DD | When symptoms first appeared; may differ from incident_date. |
case.injury.onset_type | enum | No | acute, gradual, unknown | Discrete acute event vs. gradual/cumulative onset — the analysis differs materially between the two. |
case.employee | object | No | — | Structural description of the job, never of the person. |
case.employee.job_title | string | No | ≤ 200 chars | Job title. |
case.employee.job_duties | string | No | ≤ 2,000 chars | What the job actually involves (physical demands, typical tasks); grounds mechanism-plausibility reasoning beyond a bare title. |
case.employee.department | string | No | ≤ 200 chars | Department or work area. |
case.employee.tenure_bracket | string | No | ≤ 40 chars | Tenure as a bracket (e.g. "1-3 years"), never a hire date. |
case.treatment | object | No | — | Treatment provided so far. |
case.treatment.provided | array of string | No | ≤ 25 entries, each 1–1,000 chars | Each treatment provided, one entry per intervention. |
case.treatment.provider_type | string | No | ≤ 200 chars | Type of provider (e.g. "occupational medicine clinic"). |
case.treatment.prescription_issued | boolean | No | — | Whether any prescription was issued. |
case.prior_condition | object | No | — | Pre-existing condition affecting the same region, if any. |
case.prior_condition.exists | boolean | No | — | Whether a relevant prior condition exists. |
case.prior_condition.description | string | No | ≤ 4,000 chars | Free-text description of the prior condition and its resolution. |
case.prior_condition.prior_incident_date | string (date) | No | YYYY-MM-DD | Date of the prior incident or episode. |
case.statements | array | No | ≤ 20 entries | Statements gathered during the investigation. |
case.statements[].source | enum | Yes (per entry) | employee, witness, clinician, employer, injury_report | Who the statement is from, by role. |
case.statements[].text | string | Yes (per entry) | 1–8,000 chars | The statement text. Refer to people by role only. |
case.work_status | object | No | — | Deterministic outcome facts; these satisfy recording criteria directly, without AI judgment. |
case.work_status.days_away | integer | No | 0 ≤ n ≤ 3650 | Days away from work. |
case.work_status.restricted_duty | boolean | No | — | Whether the employee was placed on restricted duty. |
case.work_status.job_transfer | boolean | No | — | Whether the employee was transferred to another job. |
case.work_status.loss_of_consciousness | boolean | No | — | Whether the employee lost consciousness. |
case.work_status.fatality | boolean | No | — | Whether the case was fatal. |
lens | enum | No | safety, occupational_medicine | Reasoning-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
| Field | Type | Always present | Description |
|---|---|---|---|
recordability_score | number | Yes | 0.000–1.000. Weighted composite folded along the 1904.4 decision tree. Decision support for the reviewer, never a determination. |
confidence | object | Yes | How much to trust this run. |
confidence.overall | number | Yes | 0–1 blended confidence. |
confidence.tier | string | Yes | Banded label for overall (e.g. "high"). |
confidence.breakdown | object | Yes | The terms behind overall. |
confidence.breakdown.input_completeness | number | Yes | 0–1. How much of the optional case structure you supplied; every populated optional block raises it. |
confidence.breakdown.model_certainty | number | Yes | 0–1. Aggregated per-factor certainty — the analyses' own read of how much reliable information they had. |
criteria_met | object | Yes | Transparency block for the 1904.7 recording-criterion branch. |
criteria_met.fatality | boolean | Yes | Deterministic, from work_status.fatality. |
criteria_met.days_away | boolean | Yes | Deterministic, from work_status.days_away. |
criteria_met.restricted_duty_or_transfer | boolean | Yes | Deterministic, from work_status.restricted_duty / work_status.job_transfer. |
criteria_met.loss_of_consciousness | boolean | Yes | Deterministic, from work_status.loss_of_consciousness. |
criteria_met.medical_treatment_beyond_first_aid | enum | Yes | yes | no | unsure — the treatment factor's leaning. |
criteria_met.significant_condition_or_specific_criteria | enum | Yes | yes | no | unsure — the significance factor's leaning. |
factors | object | Yes | All five full factor assessments, keyed work_relatedness, exceptions, recurrence, treatment, significance. |
factors.<factor>.likelihood | number | Yes | 0–1 likelihood of the factor's factor-specific question. |
factors.<factor>.leaning | enum | Yes | yes | no | unsure. |
factors.<factor>.reasoning | string | Yes | The cited analysis narrative — several paragraphs in production. |
factors.<factor>.citations | array | Yes | 1–12 entries; every passage the analysis relied on. |
factors.<factor>.citations[].source_type | enum | Yes | regulation | faq | interpretation | preamble. |
factors.<factor>.citations[].ref | string | Yes | The cited reference (e.g. "1904.5(b)(2)(vii)", FAQ "5-10"). |
factors.<factor>.citations[].quote | string | null | No | The quoted passage, when one was quoted. |
factors.<factor>.items | array | null | No | Per-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[].key | string | Yes | What the row rules on. |
factors.<factor>.items[].determination | enum | Yes | yes | no | unsure. |
factors.<factor>.items[].note | string | null | No | One-row rationale. |
factors.<factor>.missing_information | array of string | Yes | Up to 10 facts that would sharpen this factor. May be empty. |
factors.<factor>.certainty | number | Yes | 0–1. The analysis's own read of how much reliable information it had for this factor — distinct from likelihood. |
missing_information | array of string | Yes | Merged, deduplicated union of every factor's list — an investigation checklist for the case. |
catalog_version | string | Yes | Version of the stored regulation-and-guidance catalog the citations were drawn from. |
request_id | string | Yes | Correlation ID. Echo it in support tickets. |
timestamp | string | Yes | ISO 8601, UTC. |
The five factors
| Key | Question it answers | Grounded in |
|---|---|---|
work_relatedness | Did an event or exposure in the work environment cause, contribute to, or significantly aggravate the condition? | 1904.5 |
exceptions | Does 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) |
recurrence | Is 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) |
treatment | Did treatment go beyond the exhaustive first-aid list? Each treatment in case.treatment.provided is classified individually in items. | 1904.7(b)(5) |
significance | Is 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
| Code | Meaning | When |
|---|---|---|
200 | OK | Composite analysis completed. |
400 | ValidationError | Body shape, enum violation, over-length field, or an unrecognized field. field names the offender when known. |
400 | DeIdentificationViolation | The body carries an identifier-shaped value — including a precise date outside the four exempt event-date fields. |
401 | Unauthenticated | Missing or invalid API key. |
413 | PayloadTooLarge | Body exceeds 512 KB. |
415 | UnsupportedMediaType | Content-Type is not application/json. |
429 | RateLimited | Per-consumer rate limit exceeded. Respect Retry-After. |
500 | InternalError | Unexpected failure. Report the request_id. |
502 | UpstreamError | An AI factor analysis failed, or its output failed the outbound safety scan. Safe to retry once. |
504 | UpstreamTimeout | An 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_scorewith the per-factor likelihoods and leanings shows exactly where the case is contested. - Getting the merged
missing_informationlist 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/analyzeinstead — it adds the per-dimension presumption breakdown this composite does not surface. - Treating
recordability_scoreas 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
lensexpecting a different answer.lenschanges 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 return400 DeIdentificationViolationwithfieldnaming the offender. See conventions.md. - Outbound: every generated
reasoning,note, andmissing_informationstring is scanned for identifier shapes before the response returns. A match fails the call with502 UpstreamError; the engine never silently scrubs.
Debugging
Checklist when a call fails:
- Capture the
request_idfrom the response body (success or error). Every support ticket starts here. 400 DeIdentificationViolation— thefieldextra names the offending path. Check free text for names or initials, and check for precise dates outside the four exempt event-date fields.400 ValidationError— check enum values (location_context,onset_type,statements[].source,lens), field lengths, and for unrecognized fields — the body schema is strict.401 Unauthenticated— confirm theapikeyheader is present and the key is active.429 RateLimited— respect theRetry-Afterheader; back off.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 therequest_id.504 UpstreamTimeoutor 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.
Related
- recordability-factor.md — the five single-factor endpoints; same case body, one factor's assessment, a fraction of the cost.
POST /api/work_relatedness/analyze— the complete 1904.5 work-relatedness answer with the per-dimension presumption breakdown.GET /api/regulations/search— search the regulation-and-guidance catalog the citations point into.GET /api/regulations/get— fetch a cited passage by reference to render alongside the reasoning.POST /api/naics/calculate— OSHA-300 incidence-rate math over the counts a recordable case feeds.- conventions.md — de-identification contract, request IDs, timestamp shape.
- errors.md — error envelope and code list.
Change history
| Date | Change |
|---|---|
| 2026-07-01 | Initial publication. |