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

# Business verification

> Verify customer-provided business data against Canadian business registries

Business verification lets you confirm that a customer's business details match official Canadian registry records. Submit the data you have and get back field-level match results with an AI analyst summary.

## How it works

1. You submit business details (legal name, jurisdiction, registration number, and optionally address and people)
2. The API fetches fresh data from the relevant provincial or federal business registry
3. Each field is compared against the registry data with configurable similarity thresholds
4. An AI analyst summary is generated for compliance review

## Synchronous vs asynchronous

When a fresh registry lookup is required, `POST /verify` responds with **`202 Accepted`** and a `reportFetchId` instead of the full result:

```json theme={null}
{
  "pending": true,
  "reportFetchId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "status": "pending",
  "statusUrl": "/v1/verify/a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
```

Poll `GET /verify/{id}` (using the `reportFetchId`) until it returns the completed result. The poll endpoint always returns `200`; branch on the body:

* **Pending** — `{ "pending": true, "status": "pending" | "processing" | "waiting_for_registry" }` — keep polling.
* **Failed** — `{ "status": "failed", "error": "<reason>" }`.
* **Completed** — the full verification response (the shape shown under [Response](#response)).

When a recent cached registry report is available, `POST /verify` returns the completed result synchronously with `200`. Always branch on the HTTP status (or the presence of `pending: true`) rather than assuming `200`.

```python theme={null}
import requests, time

API_KEY = "cur_live_xxxxxxxxxxxx"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}

resp = requests.post(
    "https://api.getcurrent.ca/v1/verify",
    headers=HEADERS,
    json={"legalName": "Shopify Inc.", "jurisdiction": "ON", "registrationNumber": "2033076"},
)

result = resp.json()
if resp.status_code == 202:  # async — poll until complete
    poll_url = f"https://api.getcurrent.ca{result['statusUrl']}"
    while True:
        result = requests.get(poll_url, headers=HEADERS).json()
        if result.get("status") == "failed":
            raise RuntimeError(result["error"])
        if not result.get("pending"):
            break  # completed
        time.sleep(3)

print(result["results"]["status"])
```

## Request

```bash theme={null}
curl -X POST https://api.getcurrent.ca/v1/verify \
  -H "Authorization: Bearer cur_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "legalName": "Shopify Inc.",
    "jurisdiction": "ON",
    "registrationNumber": "2033076"
  }'
```

### Required fields

| Field                | Type   | Description                                              |
| -------------------- | ------ | -------------------------------------------------------- |
| `legalName`          | string | Legal name of the business to verify                     |
| `jurisdiction`       | string | Canadian jurisdiction code or full name                  |
| `registrationNumber` | string | Registration number from the provincial/federal registry |

<Note>
  These three become **optional** when you reference a stored business record
  with `businessId` or `businessExternalId` (see below) — they're hydrated from
  the record.
</Note>

### Optional fields

| Field                | Type   | Description                                                                                                                                                                                                                                                                                                                      |
| -------------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `businessId`         | string | Verify one of your stored business records by our id. Hydrates the identity fields (and address/people) from the record, so those become optional. Unknown/foreign id → `404`.                                                                                                                                                   |
| `businessExternalId` | string | Same as `businessId`, but reference the record by **your own** id on it (its `external_id`). Unknown id → `404` (never creates). If both ids are given they must point at the same record, else `400`.                                                                                                                           |
| `address`            | object | Address to verify (`street`, `city`, `province`, `postalCode`, `country`)                                                                                                                                                                                                                                                        |
| `people`             | array  | People to verify (each with `name` and `role`). People matching is on by default and affects the result `status`; control it via `matching.people` (`enabled: false` to skip, `impactsVerification: false` to keep it informational).                                                                                            |
| `externalId`         | string | Your own reference id for this verification (e.g. a CRM record id). Recorded as metadata on the verification **result** so you can find verifications by your own identifiers — it is **not** a business lookup and never modifies the business record. To reference a stored business by your own id, use `businessExternalId`. |
| `matching`           | object | Per-field threshold overrides (see below)                                                                                                                                                                                                                                                                                        |

### Jurisdictions

Accepts codes or full names: `AB`, `BC`, `MB`, `NB`, `NL`, `NS`, `NT`, `NU`, `ON`, `PE`, `QC`, `SK`, `YT`, `FED` (or "Ontario", "British Columbia", "Federal", etc.)

## Matching thresholds

Matching is governed by your account's verification settings; a per-request `matching` object overrides them for that call. If you haven't customized your settings, the defaults are:

| Field                | Default threshold | Behavior                                            |
| -------------------- | ----------------- | --------------------------------------------------- |
| `legalName`          | `0.95`            | Fuzzy match (normalization applied)                 |
| `registrationNumber` | `1.0`             | Exact match                                         |
| `address`            | `0.95`            | Fuzzy match                                         |
| `people`             | `0.95`            | Enabled by default, and affects the result `status` |

A threshold of `1.0` requires an exact (normalized) match; lower values allow proportionally fuzzier matches. Override any subset per request:

```json theme={null}
{
  "matching": {
    "legalName": { "threshold": 0.85 },
    "registrationNumber": { "threshold": 1.0 },
    "address": { "threshold": 0.85 },
    "people": {
      "enabled": true,
      "threshold": 0.85,
      "impactsVerification": false,
      "requiredMatchLevel": "all_matched"
    },
    "normalization": { "enabled": true }
  }
}
```

When `normalization.enabled` is `true` (the default), values are normalized before comparison — corporate suffixes are stripped, abbreviations expanded, postal codes standardized, etc. Set to `false` for strict character-for-character comparison.

## Response

```json theme={null}
{
  "meta": {
    "verificationId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "verifiedAt": "2024-01-15T10:30:00Z",
    "duration": 24318,
    "submitted": { ... },
    "matching": { ... }
  },
  "results": {
    "status": "verified",
    "fields": {
      "legalName": {
        "status": "matched",
        "score": 1.0,
        "provided": "Shopify Inc.",
        "registry": "SHOPIFY INC."
      },
      "registrationNumber": {
        "status": "matched",
        "score": 1.0,
        "provided": "2033076",
        "registry": "2033076"
      },
      "status": {
        "status": "not_submitted",
        "score": 0,
        "provided": null,
        "registry": "Active"
      },
      "businessNumber": {
        "status": "not_submitted",
        "score": 0,
        "provided": null,
        "registry": null
      },
      "entityType": {
        "status": "not_submitted",
        "score": 0,
        "provided": null,
        "registry": "Corporation"
      },
      "address": {
        "status": "not_submitted",
        "score": 0,
        "fields": {
          "street": null,
          "city": null,
          "province": null,
          "postalCode": null,
          "country": null
        }
      },
      "people": {
        "status": "not_submitted",
        "impactsVerification": true,
        "matches": []
      }
    },
    "analystSummary": "The business name and registration number match..."
  },
  "registryData": {
    "legalName": "SHOPIFY INC.",
    "registrationNumber": "2033076",
    "jurisdiction": "Ontario",
    "status": "Active",
    "addresses": [ ... ],
    "people": [ ... ]
  }
}
```

`results.fields` always includes `legalName`, `registrationNumber`, `status`, `businessNumber`, `entityType`, and `address`; a field you didn't submit comes back with `status: "not_submitted"` (its `registry` value is still populated when the registry has one). `address` is always an object (with a nested `fields` breakdown), never `null`. `people` is present whenever people matching is enabled (the default) — even with no people submitted, where it reports `not_submitted` with an empty `matches` array — and is omitted entirely only when you disable it (`matching.people.enabled: false`).

### Result status

| Status         | Meaning                                         |
| -------------- | ----------------------------------------------- |
| `verified`     | All checked fields meet their thresholds        |
| `not_verified` | One or more fields failed their threshold check |

### Field match status

Scalar identity fields (`legalName`, `registrationNumber`, `status`, `businessNumber`, `entityType`):

| Status          | Meaning                                   |
| --------------- | ----------------------------------------- |
| `matched`       | Score meets or exceeds the threshold      |
| `not_matched`   | Score is below the threshold              |
| `not_submitted` | The field was not provided in the request |

`address` can additionally be **`partial_match`** (some components matched, others didn't). The `people` block uses `all_matched | partial_match | no_matches | not_submitted`, and each entry in its `matches` array uses `matched | partial_match | not_matched`.

### People matching

People matching is **on by default** — you don't need to set `enabled: true`. When you submit people, they're compared against the registry and, by default, the result affects the overall `status`. Control it via `matching.people`: set `enabled: false` to skip it entirely (the `people` field is then omitted), or `impactsVerification: false` to keep it informational (reported but not affecting `status`).

Each submitted person is compared against registry directors/officers. The `people` result includes a unified `matches` array containing both submitted and registry-only people:

* Submitted people not found in the registry have `registry: null`
* Registry people not in your submitted list have `provided: null`

## Common patterns

### Verify a stored business record

Reference a business you've already stored — its legal name, jurisdiction,
registration number (and address/people) are hydrated from the record. Use our
id (`businessId`) or your own id on the record (`businessExternalId`).

```json theme={null}
{
  "businessId": "11111111-1111-4111-8111-111111111111"
}
```

```json theme={null}
{
  "businessExternalId": "acct_1Nxxx"
}
```

Supply any field alongside the reference to override it for this verification
only (the stored record is never modified).

### Verify with address

```json theme={null}
{
  "legalName": "Shopify Inc.",
  "jurisdiction": "ON",
  "registrationNumber": "2033076",
  "address": {
    "street": "150 Elgin St",
    "city": "Ottawa",
    "province": "Ontario",
    "postalCode": "K2P 1L4"
  },
  "matching": {
    "legalName": { "threshold": 0.85 },
    "address": { "threshold": 0.80 }
  }
}
```

### Verify with people

```json theme={null}
{
  "legalName": "Shopify Inc.",
  "jurisdiction": "ON",
  "registrationNumber": "2033076",
  "people": [
    { "name": "Tobias Lutke", "role": "Director" }
  ],
  "matching": {
    "people": {
      "enabled": true,
      "threshold": 0.85,
      "impactsVerification": true
    }
  }
}
```
