FCRA Partner API · v1.0.0

Registering end users

Every order names an end user. Register each one once, with its certification and the purposes it holds, and the orders follow.

What you’ll build

An end user is the employer, landlord or other business a report is for. You register it with the permissible purposes it holds and your certification text, receive an eu_ id, and name that id on every order for that business. You will create one, list and read it, change its purposes, suspend and reinstate it, and see the two refusals that protect the purpose chain: 403 fcra_purpose_not_allowed and 422 end_user_suspended.

Vetting end users and holding their certifications stays with you; the API records what you certify, per end user and per order, in the evidence record.

Before you start

  • A test key against https://sandbox.offendersearch.app; every test account may use all four purposes there.
  • Required fields: name (1–200), permissiblePurposes[] (at least one of employment, tenant_screening, consumer_written_instructions, legitimate_business_need), certification with text (10–8,000 characters), version (1–50) and certifiedAt (a date-time not in the future). Optional: externalId (≤ 200), address (line1, city, state as two letters, postalCode), certification.certifiedBy.
  • Request bodies are strict: an unknown field is a 422 with detail as an array.
Purposes are checked twice. An end user may hold only purposes your agreement allows (403 fcra_purpose_not_allowed on create and on PATCH). An order may then state only a purpose its end user holds and your agreement still allows. Keep allowedPurposes from GET /v1/fcra/partner as the list you offer.

Step by step

  1. Register the end user. POST /v1/fcra/end-users → 201 with status active. Store id against your customer record; externalId carries your own key back.
  2. List and read. GET /v1/fcra/end-users returns every end user on the account (no pagination); GET /v1/fcra/end-users/{end_user_id} returns one or 404 not_found.
  3. Change purposes. PATCH /v1/fcra/end-users/{end_user_id} with permissiblePurposes replaces the list. A purpose outside your agreement is 403 fcra_purpose_not_allowed.
  4. Suspend and reinstate. PATCH with status: "suspended"; new orders naming it are 422 end_user_suspended. status: "active" reinstates it.
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": "Northwind Staffing LLC",
    "externalId": "EU-4821",
    "address": { "line1": "1 Example Way", "city": "Springfield", "state": "IL", "postalCode": "62701" },
    "permissiblePurposes": ["employment"],
    "certification": {
      "text": "Northwind Staffing LLC certifies that it will request and use consumer reports only for employment purposes, has made the required disclosures and obtained written authorization from each consumer, and will comply with its obligations under the FCRA and applicable state law.",
      "version": "v3",
      "certifiedAt": "2026-10-02T14:00:00Z",
      "certifiedBy": "compliance@your-cra.example"
    }
  }'
201 Created
{
  "id": "eu_0b44acbeefeaa7d7",
  "name": "Northwind Staffing LLC",
  "externalId": "EU-4821",
  "address": { "line1": "1 Example Way", "city": "Springfield", "state": "IL", "postalCode": "62701" },
  "permissiblePurposes": ["employment"],
  "certification": {
    "text": "Northwind Staffing LLC certifies that it will request and use consumer reports only for employment purposes, …",
    "version": "v3",
    "certifiedAt": "2026-10-02T14:00:00+00:00",
    "certifiedBy": "compliance@your-cra.example"
  },
  "status": "active",
  "createdAt": "2026-10-25T14:12:40.207113+00:00",
  "updatedAt": "2026-10-25T14:12:40.207113+00:00"
}
403 — a purpose outside your agreement
{
  "detail": {
    "code": "fcra_purpose_not_allowed",
    "message": "Your partner agreement does not cover ['tenant_screening']"
  }
}
422 — an order naming a suspended end user
{
  "detail": { "code": "end_user_suspended", "message": "This end user is suspended." }
}

Reading the result

FieldValuesWhat it decides
ideu_ + 16 hexThe endUserId on every order for this business.
statusactive, suspendedWhether new orders may name it. Existing orders are unaffected by a suspension.
permissiblePurposessubset of the fourThe purposes an order for this end user may state. The order’s permissiblePurpose must be in this list.
certificationtext, version, certifiedAt, certifiedByWhat you certified and when. Bump version when your certification text changes.
externalIdyour string or nullRound-trips your own customer key.
updatedAtdate-timeMoves on every PATCH, even an empty one.

Edge cases and pitfalls

  • `certifiedAt` in the future (more than five minutes ahead) is a 422 array entry. Send the time the certification was actually signed.
  • `state` must be two letters and is upper-cased; it is not checked against a list of states.
  • A `403 fcra_purpose_not_allowed` on an end user is not written to the evidence record; the same refusal on an order is. Fix the purpose list, do not retry blindly.
  • PATCH replaces `permissiblePurposes`, it does not merge. Send the full new list.
  • One end user per business, not per order. Re-registering the same business creates a second eu_ id; use externalId to find the existing one in GET /v1/fcra/end-users.
  • Suspension is reversible; deletion does not exist. Keep suspended end users for the orders that reference them.

Production checklist

  • Register each end user once; store eu_ id ↔ your customer id.
  • Offer only allowedPurposes from GET /v1/fcra/partner in your UI.
  • Version your certification text; re-certify (new version, new certifiedAt) when it changes.
  • Suspend end users whose certification lapses; handle 422 end_user_suspended at order time.
  • Which purposes an end user may lawfully hold is for you and your counsel to determine; the API enforces only your agreement’s list.

Product overview