> ## Documentation Index
> Fetch the complete documentation index at: https://documentation.theary.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Integration patterns

> Short examples for common Background Check API client scenarios.

# Integration patterns

<p>
  <a href="/assets/downloads/guides/integration-patterns.pdf" download="integration-patterns.pdf">Download this guide</a>
</p>

Each snippet focuses on the **differing parts** of a [Create order](/api-reference/endpoints/create-order) request. Combine with full field requirements from [Applicant](/api-reference/schemas/applicant), [Business context](/api-reference/schemas/business-context), [History](/api-reference/schemas/history), and [VerificationRequest](/api-reference/schemas/verification-request).

## Pattern index

| Pattern                               | Use when                                                      |
| ------------------------------------- | ------------------------------------------------------------- |
| Employment-only                       | You only need employment verification.                        |
| Education-only                        | You only need education verification.                         |
| Employment and education on one order | You need both supported search types in one request.          |
| Known contacts / skip broad research  | You already know the correct HR or registrar contact.         |
| Ban third-party vendors               | The client does not want specific third-party vendors used.   |
| Email-only outreach                   | You want to restrict outbound to email.                       |
| Manual review                         | You want inbound responses held for human review.             |
| Per-search webhook routing            | You need event routing that differs by search type or target. |

## Employment-only

```json theme={null}
{
  "applicant": { "...": "..." },
  "businessContext": {
    "entityName": "Acme Corp",
    "appliedJobTitle": "Engineer",
    "worksiteCity": "Austin",
    "worksiteState": "TX",
    "proposedSalary": 120000
  },
  "searchTypes": [{ "searchType": "EMPLOYMENT" }],
  "history": {
    "employment": [
      {
        "employerName": "Acme Corp",
        "position": "Engineer",
        "startDate": "2020-01-01",
        "endDate": "2023-06-30"
      }
    ]
  }
}
```

## Education-only

```json theme={null}
{
  "applicant": { "...": "..." },
  "businessContext": {
    "entityName": "State University",
    "appliedJobTitle": "Research Assistant",
    "proposedSalary": 0
  },
  "searchTypes": [{ "searchType": "EDUCATION" }],
  "history": {
    "education": [
      {
        "institutionName": "State University",
        "qualification": "BS Computer Science",
        "fieldOfStudy": "CS",
        "graduationDate": "2018-05-15",
        "institutionContactEmail": "registrar@example.edu"
      }
    ]
  }
}
```

## Employment and education on one order

```json theme={null}
{
  "searchTypes": [{ "searchType": "EMPLOYMENT" }, { "searchType": "EDUCATION" }],
  "history": {
    "employment": [{ "...": "..." }],
    "education": [{ "...": "..." }]
  }
}
```

(Include complete `applicant` and `businessContext` as for a single-type order.)

## Known contacts / skip broad research

Use `defaultSearchConfig` or per-search `searchConfig` with `research.skipResearch: true` and seed `outbound.contactHints`. See [Search config](/api-reference/schemas/search-config).

```json theme={null}
{
  "defaultSearchConfig": {
    "research": { "skipResearch": true },
    "outbound": {
      "contactHints": [{ "email": "hr@employer.com", "priority": "HIGH" }]
    }
  }
}
```

## Ban third-party vendors

Use `thirdPartyBan` when a client does not want searches routed to specific third-party providers. Values are canonical vendor codes; see [Third-party ban](/guides/third-party-ban) for the full supported list.

### Ban one vendor for one search

```json theme={null}
{
  "searchTypes": [
    {
      "searchType": "EMPLOYMENT",
      "searchConfig": {
        "thirdPartyBan": ["TALX_WORK_NUMBER"]
      }
    }
  ]
}
```

### Ban multiple vendors order-wide

```json theme={null}
{
  "defaultSearchConfig": {
    "thirdPartyBan": [
      "TALX_WORK_NUMBER",
      "NSCH"
    ]
  }
}
```

### Ban wins over third-party deferral

```json theme={null}
{
  "defaultSearchConfig": {
    "thirdPartyBan": ["TALX_WORK_NUMBER"],
    "outbound": {
      "thirdPartyDeferral": true,
      "thirdPartyDeferralHours": 72
    }
  }
}
```

When a banned vendor is detected, third-party routing is suppressed and manual/outbound handling continues.

## Email-only outreach

```json theme={null}
{
  "defaultSearchConfig": {
    "channels": {
      "email": true,
      "voice": false,
      "fax": false,
      "preferredChannel": "EMAIL"
    }
  }
}
```

## Manual review (inbound)

```json theme={null}
{
  "searchTypes": [
    {
      "searchType": "EMPLOYMENT",
      "searchConfig": { "inbound": { "requireManualReview": true } }
    }
  ]
}
```

## Per-search webhook routing

Use [WebhookTarget](/api-reference/schemas/webhook-target) objects under `closeoutEndpoints` and `fallbackEndpoint` (string URL, single object, or array). Example: send employment closeouts to one URL and everything else to a fallback:

```json theme={null}
{
  "webhookConfig": {
    "enabled": true,
    "secret": "shared-or-per-target-secret",
    "closeoutEndpoints": {
      "EMPLOYMENT": [
        {
          "url": "https://client.example/webhooks/employment",
          "events": ["verification.completed", "verification.notification"]
        }
      ]
    },
    "fallbackEndpoint": [
      {
        "url": "https://client.example/webhooks/other",
        "events": ["verification.action_required", "verification.notification"],
        "searchTypes": ["EDUCATION"]
      }
    ]
  }
}
```

## Release-form upload

Provide a signed release PDF in `applicant.signedReleaseFileUrl` using one of:

* **HTTPS URL** — host the PDF at a stable public URL
* **GCS upload** (recommended for larger files) — presigned upload flow below
* **Inline base64** — raw base64 or `data:application/pdf;base64,...` (max 10MB); uploaded to cloud storage at order creation

### GCS upload flow

1. `GET /files/release-form/generate-upload-url` → `signedUrl`, `fileUri`
2. `PUT` PDF to `signedUrl` with `Content-Type: application/pdf`
3. Set `applicant.signedReleaseFileUrl` to `fileUri` (`gs://...`)

[Generate upload URL](/api-reference/endpoints/generate-upload-url) · [Signed release file](/api-reference/schemas/applicant#signed-release-file)

## Batch create caveats

`POST /background-check/v1/batches` accepts `{ "orders": [ ...VerificationRequestDto ] }` and creates each order in parallel via the same path as single-order creation. The response includes a synthetic `batchId` and per-order `verificationOrderId` / `searchIds` in `orders`.

**Validation / creation errors:** if **any** order fails validation or throws during `createOrder`, the whole HTTP request fails with an error (you do not get a 200 with mixed success/failure).

**Partial success risk:** if the server fails **after** some orders were created (timeout, connection drop), you can be left with **some** orders already persisted. Persist every returned `verificationOrderId` as soon as you receive the response and reconcile with [List orders](/api-reference/endpoints/list-orders).

**Not implemented:** listing batches, fetching a batch by id, and deleting a batch return placeholder payloads; track orders with [List orders](/api-reference/endpoints/list-orders), [Get order](/api-reference/endpoints/get-order), and [Get order searches](/api-reference/endpoints/get-order-searches).

## Webhook idempotency

Deliveries may retry. Deduplicate with the **`X-Event-Id`** header (unique per delivery) and your own **`externalSearchId`** when you set it on searches. Acknowledge with a **2xx** response; see [Webhook events](/api-reference/webhooks/events) and [Webhook integration](/api-reference/guides/webhook-integration).
