Adverse action & revisions
Pre- and post-adverse notices sent for you, the waiting period by jurisdiction, disputes that pause the clock, and report revisions with their own receipts.
Livehttps://api.offendersearch.appSandboxhttps://sandbox.offendersearch.appHow it works
When a direct or platform partner’s end user is considering a decision against the consumer because of the report, the API runs the two-step adverse-action process as the consumer reporting agency. You name the records the decision rests on; we send the consumer the pre-adverse notice with the report access code and the summary of rights, wait the period the use location requires, and send the post-adverse notice. A dispute pauses the clock; a correction cancels the action and revises the report. The end user still makes the decision — the API never decides for it.
- Read the adverse items: every record the current report furnishes, in plain language, plus the rule the use location adds (
GET …/adverse-items). - Start the adverse action with the item ids and, where the rule requires it, your written individualized assessment. The pre-adverse notice goes to the consumer’s e-mail on the order; the order’s
adjudicationbecomespre_adverse_action. If the mail provider does not accept the notice (failedorskipped), nothing starts: the request answers 502pre_notice_not_deliveredand the action is cancelled withcancelReason: "pre_notice_not_delivered". Fix the address and start again. - The waiting period runs from the moment the pre-adverse notice is delivered: the latest of your
waitingDays(default 7 calendar days), the rule’s business days, and a floor of five business days that applies everywhere. AwaitingDaysbelow 7 is refused with 422waiting_period_too_short. The consumer may respond to the end user, dispute with us, or do nothing. - When it has run, the post-adverse notice goes and
adjudicationbecomespost_adverse_action. If you change your mind, cancel it;adjudicationclears.
What a decision could rest on — GET /v1/fcra/orders/{order_id}/adverse-items
Every record the current report furnishes, as items a decision could rest on, and the rule the use location adds.
Request
| Field | Type | Description |
|---|---|---|
| order_id required | string | Example "fo_ee0b34c5b52fd35b" |
Response
| Field | Type | Description |
|---|---|---|
| orderId | string | |
| items | array of AdverseItem | |
| rule | AdverseRule or null |
| Status | Code | When |
|---|---|---|
| 401 | — | No valid X-API-Key (the body is { "detail": "…" }, a string). |
| 403 | fcra_not_enabled | This account has no active FCRA partner agreement. |
| 403 | fcra_not_on_trial | FCRA orders are not available on a trial account. |
| 404 | not_found | No such order or adverse action on this account. |
The AdverseItem object — a record a decision could rest on
One record the current report furnishes, in plain language, with the record id you name on the adverse action.
Returned or accepted by GET /v1/fcra/orders/{order_id}/adverse-items.
| Field | Type | Description |
|---|---|---|
| id | string | The record id (recordId on the furnished record).Example "crim:OH-COURT:1234" |
| type | string one of "sex_offender", "criminal", "healthcare" | sex_offender or criminal: which search the record came from. |
| searchId | string | The search it was furnished by. |
| text | string | A plain-language line, as the pre-adverse notice will quote it. |
Start adverse action — POST /v1/fcra/orders/{order_id}/adverse-actions
Sends the pre-adverse notice to the consumer now, with the report access code and the summary of rights, and schedules the post-adverse notice after the waiting period.
Request
| Field | Type | Description |
|---|---|---|
| order_id required | string | Example "fo_ee0b34c5b52fd35b" |
| Field | Type | Description |
|---|---|---|
| adverseItemIds required | array of string | The items the decision rests on, from adverse items. |
| reasonText optional | string or null | Kept on the adverse action; not sent to the consumer. |
| waitingDays optional | integer or null | Calendar days before the post-adverse notice, 1 to 60. Default 7. The use location's rule may lengthen it. |
| individualizedAssessment optional · default false | boolean | Whether a written individualized assessment was made. Required where the rule says so. |
| assessmentText optional | string or null | The assessment, sent with the pre-adverse notice. |
| medium optional | object or null | How the notices go. {"email": true} today; postal is not yet available. |
Response
The adverse action, pending.
The body is the AdverseAction object. An adverse action on an order: the pre-adverse notice sent, the waiting period, the post-adverse notice scheduled or sent, and what paused or cancelled it.
| Status | Code | When |
|---|---|---|
| 401 | — | No valid X-API-Key (the body is { "detail": "…" }, a string). |
| 403 | fcra_not_enabled | This account has no active FCRA partner agreement. |
| 403 | fcra_not_on_trial | FCRA orders are not available on a trial account. |
| 403 | managed_tier_required | Your agreement names you as the CRA; run adverse action in your own flow. |
| 404 | not_found | No such order or adverse action on this account. |
| 409 | order_not_complete | |
| 409 | adverse_action_open | One is already pending or paused on this order. |
| 422 | consumer_contact_required | The order has no consumer e-mail (set it with the consumer route). |
| 422 | unknown_adverse_item | An id is not in the current report. |
| 422 | individualized_assessment_required | The use location's rule requires a written assessment. |
The AdverseAction object
An adverse action on an order: the pre-adverse notice sent, the waiting period, the post-adverse notice scheduled or sent, and what paused or cancelled it.
Returned or accepted by POST /v1/fcra/orders/{order_id}/adverse-actions, GET /v1/fcra/orders/{order_id}/adverse-actions, GET /v1/fcra/adverse-actions, GET /v1/fcra/adverse-actions/{aa_id}, POST /v1/fcra/adverse-actions/{aa_id}/pause, POST /v1/fcra/adverse-actions/{aa_id}/resume, POST /v1/fcra/adverse-actions/{aa_id}/cancel.
| Field | Type | Description |
|---|---|---|
| id | string | The adverse action's id (aa_…).Example "fa_1b2c3d4e5f607182" |
| orderId | string | The completed order the decision is based on. |
| status | string one of "pending", "paused", "complete", "cancelled" | pending (the clock is running), paused (a dispute, or you), complete (the post-adverse notice was sent), cancelled. |
| adverseItemIds | array of string | The record ids from the report that the decision rests on. Every one must be on the report. |
| reasonText | string or null | Your stated reason, printed on both notices. null when you gave none. |
| waitingDays | integer | The calendar days actually waited: the later of yours and the rule's. |
| rule | AdverseRule or null | The use location's rule, when one applied. |
| individualizedAssessment | boolean | true when you attached a written individualized assessment. Required where the rule says so. |
| assessmentText | string or null | The assessment text, printed with the pre-adverse notice. null when none. |
| medium | object | How the notices go out, for example {"email": true}. Mail-only delivery is not offered yet. |
| preNoticeSentAt | string (date-time) or null | When the pre-adverse notice was sent. null until it is. |
| postNoticeScheduledAt | string (date-time) | When the post-adverse notice goes (moves when paused and resumed). |
| postNoticeSentAt | string (date-time) or null | When the final notice was sent. null until the waiting period ends. |
| pausedAt | string (date-time) or null | When you paused it (a dispute, for example). null unless paused. |
| resumedAt | string (date-time) or null | When it was resumed after a pause. null unless resumed. |
| cancelledAt | string (date-time) or null | When you cancelled it. null unless cancelled. |
| cancelReason | string or null | report_revised when a dispute changed the report; otherwise what you sent. |
| disputeId | string or null | The dispute that paused it. |
| createdAt | string (date-time) | When it was started. |
| updatedAt | string (date-time) | When it last changed. |
Adverse actions on an order — GET /v1/fcra/orders/{order_id}/adverse-actions
Request
| Field | Type | Description |
|---|---|---|
| order_id required | string | Example "fo_ee0b34c5b52fd35b" |
Response
| Field | Type | Description |
|---|---|---|
| orderId | string | |
| adverseActions | array of AdverseAction |
| Status | Code | When |
|---|---|---|
| 401 | — | No valid X-API-Key (the body is { "detail": "…" }, a string). |
| 403 | fcra_not_enabled | This account has no active FCRA partner agreement. |
| 403 | fcra_not_on_trial | FCRA orders are not available on a trial account. |
| 404 | not_found | No such order or adverse action on this account. |
List adverse actions — GET /v1/fcra/adverse-actions
Newest first.
Request
| Field | Type | Description |
|---|---|---|
| status optional | string one of "pending", "paused", "complete", "cancelled" | |
| limit optional · default 100 | integer | 1 to 500. |
Response
| Field | Type | Description |
|---|---|---|
| adverseActions | array of AdverseAction |
| Status | Code | When |
|---|---|---|
| 401 | — | No valid X-API-Key (the body is { "detail": "…" }, a string). |
| 403 | fcra_not_enabled | This account has no active FCRA partner agreement. |
| 403 | fcra_not_on_trial | FCRA orders are not available on a trial account. |
Retrieve an adverse action — GET /v1/fcra/adverse-actions/{aa_id}
Request
| Field | Type | Description |
|---|---|---|
| aa_id required | string | Example "fa_1b2c3d4e5f607182" |
Response
The body is the AdverseAction object. An adverse action on an order: the pre-adverse notice sent, the waiting period, the post-adverse notice scheduled or sent, and what paused or cancelled it.
| Status | Code | When |
|---|---|---|
| 401 | — | No valid X-API-Key (the body is { "detail": "…" }, a string). |
| 403 | fcra_not_enabled | This account has no active FCRA partner agreement. |
| 403 | fcra_not_on_trial | FCRA orders are not available on a trial account. |
| 404 | not_found | No such order or adverse action on this account. |
Pause the adverse-action clock — POST /v1/fcra/adverse-actions/{aa_id}/pause
Stops the clock with the time that is left. A dispute does this on its own.
Request
| Field | Type | Description |
|---|---|---|
| aa_id required | string | Example "fa_1b2c3d4e5f607182" |
Response
The body is the AdverseAction object. An adverse action on an order: the pre-adverse notice sent, the waiting period, the post-adverse notice scheduled or sent, and what paused or cancelled it.
| Status | Code | When |
|---|---|---|
| 401 | — | No valid X-API-Key (the body is { "detail": "…" }, a string). |
| 403 | fcra_not_enabled | This account has no active FCRA partner agreement. |
| 403 | fcra_not_on_trial | FCRA orders are not available on a trial account. |
| 403 | managed_tier_required | Your agreement names you as the CRA; run adverse action in your own flow. |
| 404 | not_found | No such order or adverse action on this account. |
| 409 | not_pausable | Not pending. |
Resume the adverse-action clock — POST /v1/fcra/adverse-actions/{aa_id}/resume
Restarts the clock with the time that was left when it paused.
Request
| Field | Type | Description |
|---|---|---|
| aa_id required | string | Example "fa_1b2c3d4e5f607182" |
Response
The body is the AdverseAction object. An adverse action on an order: the pre-adverse notice sent, the waiting period, the post-adverse notice scheduled or sent, and what paused or cancelled it.
| Status | Code | When |
|---|---|---|
| 401 | — | No valid X-API-Key (the body is { "detail": "…" }, a string). |
| 403 | fcra_not_enabled | This account has no active FCRA partner agreement. |
| 403 | fcra_not_on_trial | FCRA orders are not available on a trial account. |
| 403 | managed_tier_required | Your agreement names you as the CRA; run adverse action in your own flow. |
| 404 | not_found | No such order or adverse action on this account. |
| 409 | not_paused |
Cancel adverse action — POST /v1/fcra/adverse-actions/{aa_id}/cancel
No post-adverse notice goes; the order's adjudication clears.
Request
| Field | Type | Description |
|---|---|---|
| aa_id required | string | Example "fa_1b2c3d4e5f607182" |
| Field | Type | Description |
|---|---|---|
| reason optional · default "client_cancelled" | string | Kept on the adverse action. |
Response
The body is the AdverseAction object. An adverse action on an order: the pre-adverse notice sent, the waiting period, the post-adverse notice scheduled or sent, and what paused or cancelled it.
| Status | Code | When |
|---|---|---|
| 401 | — | No valid X-API-Key (the body is { "detail": "…" }, a string). |
| 403 | fcra_not_enabled | This account has no active FCRA partner agreement. |
| 403 | fcra_not_on_trial | FCRA orders are not available on a trial account. |
| 403 | managed_tier_required | Your agreement names you as the CRA; run adverse action in your own flow. |
| 404 | not_found | No such order or adverse action on this account. |
| 409 | not_cancellable | Already complete or cancelled. |
The notices sent for an adverse action — GET /v1/fcra/adverse-actions/{aa_id}/notices
The pre- and post-adverse notices, and whether the provider took each.
Request
| Field | Type | Description |
|---|---|---|
| aa_id required | string | Example "fa_1b2c3d4e5f607182" |
Response
| Field | Type | Description |
|---|---|---|
| notices | array of Notice |
| Status | Code | When |
|---|---|---|
| 401 | — | No valid X-API-Key (the body is { "detail": "…" }, a string). |
| 403 | fcra_not_enabled | This account has no active FCRA partner agreement. |
| 403 | fcra_not_on_trial | FCRA orders are not available on a trial account. |
| 404 | not_found | No such order or adverse action on this account. |
The waiting period by use location
The federal Act sets no number of days; the practice is five business days, and no adverse action here waits less. Several states and cities set their own minimums and require a written individualized assessment before an employment decision on a criminal record. The engine applies the longest period that applies to the order’s use location and purpose; GET /v1/fcra/adverse-rules lists every rule with its citation. The rules in force today:
| Use location | Purpose | Minimum | Written assessment |
|---|---|---|---|
| California | employment | 5 business days | yes |
| Los Angeles, CA | employment | 5 business days | yes |
| San Francisco, CA | employment | 7 days | yes |
| New York City, NY | employment | 5 business days | yes (Article 23-A analysis) |
| New York City, NY | tenant screening | 5 business days | yes |
| New York (state) | employment | 5 business days | yes (Article 23-A factors) |
| Philadelphia, PA | employment | 10 business days | yes |
| Illinois; Chicago | employment | 5 business days | yes |
| Seattle, WA | employment | 2 business days (the five-business-day floor applies) | yes |
| Washington (state); District of Columbia; New Jersey; Minnesota | employment | 5 business days | D.C. yes; others no |
| Everywhere else | any | 5 business days (default waitingDays 7 calendar days) | no |
The AdverseRule object — what the use location requires
The adverse-action rule the use location and purpose add: business days to wait and whether a written individualized assessment is required. The engine applies the longest period that applies.
Returned or accepted by GET /v1/fcra/orders/{order_id}/adverse-items, POST /v1/fcra/orders/{order_id}/adverse-actions, GET /v1/fcra/orders/{order_id}/adverse-actions, GET /v1/fcra/adverse-actions, GET /v1/fcra/adverse-actions/{aa_id}, POST /v1/fcra/adverse-actions/{aa_id}/pause, POST /v1/fcra/adverse-actions/{aa_id}/resume, POST /v1/fcra/adverse-actions/{aa_id}/cancel.
| Field | Type | Description |
|---|---|---|
| state | string | The two-letter state the rule belongs to. |
| city | string or null | The city the rule is for; null for a state-wide rule. |
| purpose | string | The permissible purpose it applies to, usually employment or tenant_screening. |
| version | string | The rules version. |
| waitingBusinessDays | integer | Business days (Monday–Friday) the consumer gets to respond. |
| individualizedAssessment | boolean | Whether a written individualized assessment must go with the pre-adverse notice. |
| citation | string | The statute or ordinance, for your records and the notice. |
| note | string | What the rule requires in plain words. |
| alsoApplies | array of object | Other rules that apply with a shorter period. |
| alsoApplies[].citation | string | A city ordinance that also applies at this use location. |
| alsoApplies[].waitingBusinessDays | integer | The city's waiting period, when longer than the state's. |
The adverse-action rules by use location — GET /v1/fcra/adverse-rules
Every jurisdiction rule the engine applies, with its citation.
Request
Response
| Field | Type | Description |
|---|---|---|
| version | string | |
| defaultWaitingDays | integer | Calendar days when no rule applies. |
| rules | array of object | |
| rules[].state | string | |
| rules[].city | string or null | |
| rules[].purpose | string | |
| rules[].waitingBusinessDays | integer | |
| rules[].individualizedAssessment | boolean | |
| rules[].citation | string | |
| rules[].note | string |
| Status | Code | When |
|---|---|---|
| 401 | — | No valid X-API-Key (the body is { "detail": "…" }, a string). |
| 403 | fcra_not_enabled | This account has no active FCRA partner agreement. |
| 403 | fcra_not_on_trial | FCRA orders are not available on a trial account. |
Disputes move the clock
No waiting period runs while a dispute on the order is open. A dispute opened while an adverse action is pending pauses it with the time that was left, and the consumer receives a receipt; an adverse action started while a dispute is open starts paused. Resuming is refused with 409 dispute_open until every dispute on the order is resolved. When the last open dispute is resolved verified, the action resumes. A dispute resolved modified, deleted or unable_to_verify changes what the report furnishes: the report is revised and the adverse action is cancelled with cancelReason: "report_revised", because the notice the consumer received no longer matches the report. Start a new one on the revised report if the decision still stands.
Record your decision — POST /v1/fcra/orders/{order_id}/adjudication
Sets adjudication on a complete order (engaged or cleared). Adverse action sets pre_adverse_action and post_adverse_action itself.
Request
| Field | Type | Description |
|---|---|---|
| order_id required | string | Example "fo_ee0b34c5b52fd35b" |
| Field | Type | Description |
|---|---|---|
| decision required | string one of "engaged", "cleared" | engaged (hired, housed, proceeded) or cleared (no action on the report). |
Response
The order.
The body is the Order object. An FCRA order: its status, its end user and purpose, every search it carries, and the consumer portal access code.
| Status | Code | When |
|---|---|---|
| 401 | — | No valid X-API-Key (the body is { "detail": "…" }, a string). |
| 403 | fcra_not_enabled | This account has no active FCRA partner agreement. |
| 403 | fcra_not_on_trial | FCRA orders are not available on a trial account. |
| 404 | not_found | No such order or adverse action on this account. |
| 409 | order_not_complete | |
| 409 | adverse_action_open | Cancel the open adverse action first. |
Report revisions
Revision 1 is the report at completion. Each dispute that changes it writes the next revision: a rebuilt report without the removed records (and with corrections attached), a re-rendered PDF, new hashes, and a receipt that signs the revision number. Every earlier revision stays fetchable — GET …/report?revision=N, GET /v1/fcra/receipts/{id}?revision=N — so whoever holds an older PDF can still verify it against the receipt that was issued for it. order.revised tells you when it happens.
Every revision of an order's report — GET /v1/fcra/orders/{order_id}/revisions
Revision 1 at completion, then one per dispute that changed the report. Fetch any revision's report with ?revision= and its receipt likewise.
Request
| Field | Type | Description |
|---|---|---|
| order_id required | string | Example "fo_ee0b34c5b52fd35b" |
Response
| Field | Type | Description |
|---|---|---|
| orderId | string | |
| revision | integer | The current revision. |
| revisions | array of ReportRevision |
| Status | Code | When |
|---|---|---|
| 401 | — | No valid X-API-Key (the body is { "detail": "…" }, a string). |
| 403 | fcra_not_enabled | This account has no active FCRA partner agreement. |
| 403 | fcra_not_on_trial | FCRA orders are not available on a trial account. |
| 404 | not_found | No such order or adverse action on this account. |
The ReportRevision object
One revision of an order's report: revision 1 at completion, a new one each time a dispute changes what the report furnishes. Each has its own hashes and its own receipt.
Returned or accepted by GET /v1/fcra/orders/{order_id}/revisions.
| Field | Type | Description |
|---|---|---|
| revision | integer | The revision number: 1 is the report as first completed, each later revision adds one. |
| reportSha256 | string | SHA-256 of the revision's JSON report, which the receipt signs. |
| pdfSha256 | string or null | SHA-256 of the revision's PDF. null when no PDF was produced. |
| disputeId | string or null | The dispute that caused it; null for revision 1. |
| createdAt | string (date-time) | When the revision was produced. |
Consumer contact and notices
Orders from the hosted consent flow carry the consumer’s e-mail and whether they asked for a copy. For an order placed through the API, set them with PATCH …/consumer before the order completes (the copy of the report goes out on completion) or before starting adverse action (the notices need an address). Every consumer e-mail — the copy, the two adverse notices, the dispute receipt and resolution — is recorded and listed under GET …/notices with whether the provider took it.
Where the consumer's notices go — PATCH /v1/fcra/orders/{order_id}/consumer
For an API order: the consumer's e-mail for notices and the copy of the report.
Request
| Field | Type | Description |
|---|---|---|
| order_id required | string | Example "fo_ee0b34c5b52fd35b" |
| Field | Type | Description |
|---|---|---|
| email optional | string or null | Where the consumer's notices and copy go. null clears it. |
| phone optional | string or null | The consumer's phone. null clears it. |
| copyRequested optional | boolean or null | Send the portal link and access code when the order completes. |
| locale optional | string or null one of "en", "es" | en or es for the consumer's notices. null keeps the default. |
Response
| Field | Type | Description |
|---|---|---|
| orderId | string | |
| consumer | object | |
| consumer.email | string or null | |
| consumer.phone | string or null | |
| consumer.copyRequested | boolean | |
| consumer.locale | string |
| Status | Code | When |
|---|---|---|
| 401 | — | No valid X-API-Key (the body is { "detail": "…" }, a string). |
| 403 | fcra_not_enabled | This account has no active FCRA partner agreement. |
| 403 | fcra_not_on_trial | FCRA orders are not available on a trial account. |
| 404 | not_found | No such order or adverse action on this account. |
Every consumer e-mail for an order — GET /v1/fcra/orders/{order_id}/notices
The copy of the report, the adverse-action notices and the dispute receipts sent for this order.
Request
| Field | Type | Description |
|---|---|---|
| order_id required | string | Example "fo_ee0b34c5b52fd35b" |
Response
| Field | Type | Description |
|---|---|---|
| orderId | string | |
| notices | array of Notice |
| Status | Code | When |
|---|---|---|
| 401 | — | No valid X-API-Key (the body is { "detail": "…" }, a string). |
| 403 | fcra_not_enabled | This account has no active FCRA partner agreement. |
| 403 | fcra_not_on_trial | FCRA orders are not available on a trial account. |
| 404 | not_found | No such order or adverse action on this account. |
Test FCRA orders on the sandbox server
With a test key (os_test_…) every account is a sandbox FCRA partner on the sandbox server, with the same last-name rules. Register an end user, then place orders against it; nothing is billed. An order finishes right after the 202: read it once with GET /v1/fcra/orders/{orderId}.
- Base URL
https://sandbox.offendersearch.appNothttps://api.offendersearch.app, which takes live keys only.- Test key
- In the dashboard, Developers → API keys → Create test key. Test keys begin
os_test_; send yours in theX-API-Keyheader.
curl -X POST "https://sandbox.offendersearch.app/v1/fcra/end-users" \
-H "X-API-Key: $OFFENDERSEARCH_TEST_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Sample Staffing LLC",
"permissiblePurposes": [
"employment"
],
"certification": {
"text": "End user certifies it will use reports only for employment purposes.",
"version": "v1",
"certifiedAt": "2026-10-01T12:00:00Z"
}
}'curl -X POST "https://sandbox.offendersearch.app/v1/fcra/orders" \
-H "X-API-Key: $OFFENDERSEARCH_TEST_KEY" \
-H "Content-Type: application/json" \
-d '{
"endUserId": "{endUserId}",
"permissiblePurpose": "employment",
"consent": {
"obtainedAt": "2026-10-01T12:00:00Z",
"method": "esign"
},
"subject": {
"firstName": "Pat",
"lastName": "Records",
"dob": "1980-01-01"
},
"searches": [
{
"type": "sex_offender"
},
{
"type": "criminal"
}
]
}'Try it here
Pick a scenario, edit the request, and run it against the sandbox from this page. The explorer accepts os_test_ keys only and never reaches the live host, so nothing here is billed; the “production” code it copies is for your own backend with a live key.
Copy this request as code
Sandbox code uses your test key. Production code calls the live host and is billed per call; run it from your backend with an os_live_… key.
curl -X POST https://sandbox.offendersearch.app/v1/fcra/end-users \
-H "X-API-Key: $OFFENDERSEARCH_TEST_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "Sample Staffing LLC", "permissiblePurposes": [ "employment" ], "certification": { "text": "End user certifies it will use reports only for employment purposes.", "version": "v1", "certifiedAt": "2026-10-01T12:00:00Z" } }'Every test name: FCRA API sandbox ordersPostman collectionFCRA API sandbox