---
title: codespar_kyc
description: Identity verification, or open a payments account. Persona, Sift, Konduto and Truora for checks; the licensed BaaS partner for onboarding, which verifies the consumer AND provisions the account that funds codespar_wallet.
---

import { Callout } from "fumadocs-ui/components/callout";

<MetaToolHeader tool="codespar_kyc" />

`check_type` selects the operation. `onboarding` and `onboarding-business` are special: they verify (background check plus documentoscopia) and provision a real payment account for the consumer, so that afterwards [`codespar_wallet`](/docs/concepts/meta-tools/wallet) and [`codespar_pay`](/docs/concepts/meta-tools/pay) work for the same `consumer_id`.

## Actions

<MetaToolActions tool="codespar_kyc" />

## Example

`check_type: "onboarding"` for a natural person (CPF). In sandbox, a `phoneNumber` ending in `1` auto-approves both gates.

<Split min={380}>
<SplitPane label="Call · tools/call">

```json title="arguments"
{
  "name": "codespar_kyc",
  "arguments": {
    "check_type": "onboarding",
    "consumer_id": "consumer_0000",
    "buyer": {
      "fullName": "Example Person",
      "document": "00000000000",
      "email": "person@example.com",
      "phoneNumber": "+5500000000001",
      "birthDate": "01-01-2000",
      "motherName": "Example Parent",
      "address": { "postalCode": "00000000", "street": "Example St", "number": "0", "city": "Example", "state": "SP" },
      "country": "BR"
    }
  }
}
```

</SplitPane>
<SplitPane label="Result · fields the tool document names">

```json title="result"
{
  "verification_id": "ver_0000"
}
```

Every `check_type` returns a `verification_id`. Poll completion with `check_type: "status"`, passing that id and the same `document_number`; for onboarding the status is `pending`, `documentscopy_pending` (with a `hosted_url` where the consumer finishes document capture), `approved` (with the funding source) or `rejected`.

</SplitPane>
</Split>

## When to use

- **Before a consumer can hold funds in live.** `onboarding` (CPF) or `onboarding-business` (CNPJ: PJ or MEI) opens the payment account that becomes the wallet's funding source. For a business the documentoscopia target is the responsible partner, `buyer.owner[0]`, not the company. In the test environment the sandbox wallet ships pre-connected and no onboarding is needed.
- **As a gate before a high-value charge or payout**, or when a regulated workflow demands proof of identity: `identity`, `document`, `risk-score`, `sanctions`.
- **To finish an onboarding**: poll `status` until it leaves `pending`; while it is `documentscopy_pending`, hand the consumer the `hosted_url`.

## Arguments

| Field | Type | Required | Description |
|---|---|---|---|
| `check_type` | `string` | Yes | `identity` \| `document` \| `risk-score` \| `sanctions` \| `onboarding` \| `onboarding-business` \| `status` |
| `buyer` | `object` | Yes | The subject. Verification: `{ name, document, country, email }`. `onboarding`: `{ fullName, document (CPF), email, phoneNumber (+55…), birthDate (DD-MM-YYYY), motherName, address, country }`. `onboarding-business`: `{ document (CNPJ, 14 characters, digits or letters), businessName, tradingName?, businessEmail, contactNumber, businessAddress (or address), owner: [...] }`, where `owner[]` is required and its first entry is the responsible partner (`ownerType` `REPRESENTANTE`, full PF data; their CPF is the documentoscopia target) |
| `verification_id` | `string` | With `status` | From a prior call. It names the proposal that verified the document, and it is the only thing that provisions a payment account: a status poll without it never binds an account |
| `document_number` | `string` | With `status` | CPF (or CNPJ for an `onboarding-business` proposal). Identifies the subject; it must be the same document the proposal verified and is never used to look an account up |
| `consumer_id` | `string` | No | Whose account or verification. Defaults to the session user (onboarding and status) |
| `metadata` | `object` | No | Provider-specific overrides |

## Errors and what to do

| Error | Cause | What to do |
|---|---|---|
| `invalid_args` | `buyer` not an object, `check_type` missing or unknown. | Fix the call against the Arguments table. |
| `document_ownership_unproven` | A `status` poll with only a `document_number` and no `verification_id`. A document an agent typed is not proof it is the consumer's; nothing is provisioned. | Pass the `verification_id` the onboarding call returned. |
| `onboarding_document_mismatch` | The `document_number` on a `status` poll is not the document the `verification_id`'s proposal verified. | Poll with the same document you onboarded. |
| `rejected` | The provider refused the verification or the onboarding. | Surface it; a rejected onboarding does not open an account. |

Measured 2026-09-09: the dispatch also accepts an undeclared `action: "status"` that the published schema does not name ([ent#1182](https://github.com/codespar/codespar-enterprise/issues/1182), open). Use `check_type: "status"`, which the schema declares.

## Money and mandate

No money moves on this tool. `onboarding` and `onboarding-business` create the payment account the consumer's wallet is funded from; the account is bound only through a `verification_id`, never through a document number alone, so an agent cannot attach someone's account by typing their CPF. Later spends from that account run under the consumer's signed [mandate](/docs/concepts/directed-pay).

## Related

- [`codespar_wallet`](/docs/concepts/meta-tools/wallet): the wallet the onboarded account funds
- [`codespar_pay`](/docs/concepts/meta-tools/pay): `dda_subscribe` needs the document verified here
- [SDK reference, verificationStatus](/docs/api/sdk/session#verificationstatustoolcallid-promiseverificationstatusresult)
- [Async settlement, the KYC sibling](/docs/api/sessions#async-settlement) and [SSE streaming](/docs/api/sessions#streaming-status)
- [Test mode](/docs/concepts/test-mode): the sandbox auto-approval rule

## Notes

**Rails, as previously documented.** `identity` and `document` route to Persona (default; `inquiry_template_id` stamped per tenant in `connection_metadata`); `risk-score` to Sift (INTL) or Konduto (BR fraud); `sanctions` to Sift or Truora; `onboarding` and `onboarding-business` to the licensed BaaS partner.

**Operator setup.** Persona: API key, and stamp `inquiry_template_id` in `connection_metadata` when connecting (per tenant, not passed at execute time; without it inquiry creation fails; the dashboard's Persona connect modal has an input for it). Sift and Konduto: HTTP Basic auth (API key as username, blank password). Truora: API key.

**Tracking from the SDK, as previously documented.** `session.verificationStatus(tool_call_id)` and `session.verificationStatusStream(tool_call_id, opts)` follow the same correlation chain as payments (`idempotency_key` ↔ `external_reference` via webhook) and return `approved`, `rejected`, `review`, `expired` or `pending`, in that poll-priority order: when several events landed for one `tool_call_id`, the highest-priority terminal state wins. There is no typed wrapper for the check itself; `session.execute("codespar_kyc", arguments)` takes the same arguments as the MCP call.

**Result shape (SDK), as previously documented.** `data: { verification_id, status, hosted_url: string | null, check_type }`; for `onboarding` the create call returns `hosted_url: null` and the document-capture link is surfaced by `status`. This revision did not re-verify that list against the runtime.
