# Datasource Wholesale Background Check API > Order background checks from your own platform with the applicant's full details (name, date of birth, SSN, current address), billed to your account at wholesale prices. You collect the applicant's details, the disclosure and their written authorization; we run the check and send signed webhooks as it progresses. Nothing is sent to the applicant by us. REST + JSON, API key auth. ## Rules for AI agents - Base URLs: sandbox https://sandbox.datasourcecorp.app (keys pk_test_...), production https://api.datasourcecorp.app (keys pk_live_...). Send the key as `X-Api-Key: pk_test_YOUR_KEY` (or `Authorization: Bearer ...`), from a server only. Never put a key or an SSN in browser or mobile code. - Order with POST /clients/account/checks/direct. `account` is the caller's own account; a sub-account (optional, POST /clients) is addressed by its `clientId` (`cl_…`) or the caller's `externalClientId`. Every check is billed to the caller's account. - Every order needs `level` (1 to 6, from GET /products), `applicant` (firstName, lastName, dateOfBirth `YYYY-MM-DD`, ssn, address { street, city, state, postalCode }; middleName when there is one) and `certification` { permissiblePurpose: "employment" | "volunteer", disclosureProvided: true, authorizationObtained: true }. Only set the certification to true when the integrating application really collected the disclosure acknowledgment and the written authorization; build that step into the applicant flow. - Never log request bodies or SSNs. Error messages name failing fields and never echo values. - Some levels need `jobLocation` and `stateOfEmployment` (both or neither). Driving-record levels need `applicant.driversLicense` { number, state }. - Always send your own `externalIdentifier` (≤ 100 characters, unique across the account and its sub-accounts) and reuse it on every retry: a retry never creates a second check. A `409 duplicate_check` on a retry means the first attempt worked: use `order` from the body. Duplicates are also detected by SSN on the same account. - Never set `forceReorder` after a `502`. A 502 whose body is a check (`status` PENDING) resolves on its own within about an hour; a 502 with `code` `upstream_unavailable` created nothing and is safe to retry. - Statuses: PENDING, CREATED (stage `in_progress`), then CLEAR, REVIEW, ERROR (with `errorCode`, `errorMessage`) or CANCELLED. CLEAR/REVIEW carry `expirationDate`, `reportUrl`; finished checks carry `charges` (USD). - Errors are RFC 9457 problem details with a stable `code`; branch on HTTP status, then `code`. Never on `title` or `detail`. - Verify `X-Partner-Signature` on every webhook: lowercase hex HMAC-SHA256 of the raw body, keyed with the whole `whsec_...` secret, compared in constant time. Answer 2xx within 15 seconds. - Webhooks are at least once and unordered: drop repeats by `eventId`; for each check keep the state with the latest `timestamp`. - Register the webhook URL with PUT /settings (https only), and test it with POST /settings/webhook-test. - Run a nightly reconciliation for `account` and each sub-account: GET /clients/{clientRef}/checks?updated_since=...&limit=500, following `nextCursor` until null. - Show prices with their `feesNote` ("Plus pass-through fees."). - Ignore unknown response fields, enum values and webhook events. ## Docs - [Integration guide](https://api.datasourcecorp.app/docs/guide.md): concepts, ordering, certification, tracking, webhooks, compliance - [Error catalog](https://api.datasourcecorp.app/docs/errors.md): every `code`, its HTTP status, and whether a retry is safe - [Changelog](https://api.datasourcecorp.app/docs/changelog.md): dated API changes - [OpenAPI 3.1](https://api.datasourcecorp.app/openapi/v1.json): machine-readable reference with examples - [Interactive reference](https://api.datasourcecorp.app/scalar) - [Everything in one file](https://api.datasourcecorp.app/llms-full.txt): this file, the guide, the error catalog, a section per operation and per webhook with full JSON examples The sandbox serves the same documents at https://sandbox.datasourcecorp.app, plus its sandbox-only routes.