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

> ## Agent Instructions
> HEVN accounts are non-custodial in both products. Self-serve (the General tab): the person who owns the email holds the only key and signs for themselves. Whitelabel (the Whitelabel and REST API tabs): the integrator's customer creates and owns their account through Sign in with HEVN, a HEVN-hosted popup on the integrator's site; the integrator's backend holds a developer key, operates linked accounts and books their payouts, and the account holder approves every payout in that popup. The developer key signs only for the integrator's own wallet; it never signs a client's money.
> Use HEVN's terms exactly. A rail is a bank route a client can request. A virtual account (bnk_) is an opened rail. Account details are what a payer needs in order to wire money, and arrive in a field named requisites. A client is a customer's own account linked to the integrator through Sign in with HEVN (POST /dapi/v1/connect/sessions, then POST /dapi/v1/clients/link); there is no API call that creates one. The business behind it is the integrator's customer. A contact is a saved destination; a beneficiary is the party at the far end of a fiat payout. Every departure of money is a payout, to a bank account or to a wallet alike.
> Never name a banking partner. Say 'a licensed banking partner'.
> There are no published fee rates, spreads or minimums. Prices come from a quote on a specific payment; direct pricing questions to HEVN rather than inventing numbers.
> The whitelabel API is at /dapi/v1 and takes a developer-key session plus an X-Hevn-Account header. Developer keys have an IP allowlist and no scopes. Remote transfers are at /api/v1/remote_spend_limit and take a remote transfer key (rsl_) in X-Api-Key, bounded by an onchain spend permission the account holder grants. They are different credentials and neither works on the other surface. The HEVN CLI is discontinued.

# KYB fields

> Every field of the KYB document, its accepted values, the document slots, and how to read a missing[] path.

Every field of the KYB document, with its accepted values. The document is the body of `PUT /dapi/v1/client/kyb` and the `document` block of `GET /dapi/v1/client/kyb`; both use the same shape, and both take the client id in `X-Hevn-Account` rather than in a path. [Onboarding](https://docs.gethevn.com/whitelabel/onboarding.md) is the flow that fills it.

"Required" below means completion is refused without it — the field appears in `missing[]` until it is set. Everything under "Optional detail" is accepted, never demanded by the gate, and routinely asked for by a reviewer instead: sending what you already hold is how an RFI is avoided rather than answered.

## `company`

| Field | Type | Required | Notes |
| - | - | - | - |
| `legalName` | string, 1–200 | yes | The registered name. Unique across HEVN; it is also the client's account name. |
| `tradeName` | string, 1–200 | no | The name the business trades under, if different. |
| `country` | ISO 3166-1 alpha-2 | yes | The jurisdiction of incorporation. Widens the required document slots. |
| `registrationNumber` | string, 1–200 | no | The company number in its own register. |
| `taxId` | string, 1–200 | US only | A US company owes its EIN as `XX-XXXXXXX`. A value that is not in that shape counts as missing. |
| `phone` | E.164 | yes | Satisfied by the account phone as well — see [onboarding](https://docs.gethevn.com/whitelabel/onboarding.md#two-phone-numbers). |
| `email` | string, 1–200 | no | A compliance mailbox. HEVN does not write to it. |
| `address` | object | yes | See below. |
| `entityType` | enum | yes | |
| `incorporationDate` | `YYYY-MM-DD` | no | |
| `websites` | array of strings | no | |
| `expectedMonthlyVolumeUsd` | decimal string, ≥ 0 | yes | Major units, for example `"250000"`. |
| `businessDescription` | string, 1–4000 | yes | What the company sells, in a sentence a reviewer can act on. |
| `businessType` | enum | yes | |
| `businessIndustry` | 6 digits | no | An industry classification code, for example `"424990"`. |
| `verifierRole` | enum | no | The relationship of the person who filled this in to the company. |
| `sourceOfFunds` | enum | yes | Where the money the client will move comes from. |
| `purposeOfFunds` | enum | yes | What it will be used for. |
| `flowOfFunds` | string, 1–4000 | yes | How money reaches the company and where it goes, in plain sentences. |

### `company` — optional detail

None of these appears in `missing[]`. All of them are read by a reviewer.

| Field | Type | Notes |
| - | - | - |
| `entityTypeDescription` | string, 1–200 | The legal form in words, when `entityType` is `other`. |
| `industry` | string, 1–200 | The industry in words, alongside the `businessIndustry` code. |
| `productsServices` | array of strings, 1–200 each | What the company sells, itemised. |
| `linkedinUrl` | string, 1–2000 | The company's public LinkedIn page. |
| `operatingCountries` | array of ISO 3166-1 alpha-2 | Where it trades, as distinct from where it is registered. |
| `primaryTargetMarket` | enum | Who it sells to. |
| `publicListed` | boolean | Whether the company is listed. |
| `institutionalInvestors` | boolean | Whether institutional investors fund or own it. |
| `isRegulated` | boolean | Whether it holds a licence or sits under a regulator. |
| `regulatoryLicenseType` | string, 1–200 | The licence it holds, in words — for example `Electronic Money Institution`. Some partner banks need it when `isRegulated` is `true`. |
| `regulatorCountry` | ISO 3166-1 alpha-2 | Country of the authority that licenses it. Some partner banks need it when `isRegulated` is `true`. |
| `verifiesCustomerIdentity` | boolean | Whether it verifies the identity of its own customers. Some partner banks need it when `isRegulated` is `true`. |
| `hasTransactionMonitoring` | boolean | Whether it monitors its customers' transactions. Some partner banks need it when `isRegulated` is `true`. |
| `estimatedAnnualRevenue` | decimal, ≥ 0 | Annual revenue in USD. |
| `revenueCovers` | enum | How much of operating expense that revenue covers. |
| `txPerMonth` | enum | Expected transaction count per month. |
| `expectedCryptoMonthlyVolumeUsd` | decimal, ≥ 0 | The digital-asset share of `expectedMonthlyVolumeUsd`. |
| `expectedMonthlyAchUsd` | decimal, ≥ 0 | The ACH share. |
| `expectedMonthlyWireUsd` | decimal, ≥ 0 | The wire share. |
| `depositMethods` | array of strings, 1–200 each | How and from where the account will be funded. |
| `usesBlockchain` | boolean | Whether blockchain or digital assets are used in operations. |
| `cryptoIndustrySubtype` | enum | The digital-asset business model, when there is one. |
| `hasUsBank` | boolean | Whether the company already holds a US payment account. |
| `deniedUsBank` | boolean | Whether a US institution has declined or closed one. |
| `hasIntermediateEntityOwnership` | boolean | Whether another legal entity sits between the company and a beneficial owner. See [complex ownership](#complex-ownership). |
| `hasPep` | boolean | Whether the company, an owner or a controller is a politically exposed person. |
| `bizAdverse` | array of strings, 1–4000 each | Adverse information about the company, declared up front. |
| `ownersAdverse` | array of strings, 1–4000 each | The same for its owners and controllers. |
| `sanctionedCountryOperations` | boolean | Whether it operates in or serves sanctioned jurisdictions. |
| `highRiskActivities` | array of enum | Higher-risk activities it performs. |
| `handlesCustomerFunds` | boolean | Whether it receives, holds or transfers funds for its own customers. |
| `actingAsIntermediary` | boolean | Whether it sits between the payer and the ultimate beneficiary. |
| `moneyServicesDescription` | string, 1–4000 | The money-services activity, when there is any. |
| `complianceScreening` | string, 1–4000 | How it screens its own customers and transactions. |
| `sourceOfFundsDetails` | string, 1–4000 | The `sourceOfFunds` answer, explained. |
| `purposeOfFundsDetails` | string, 1–4000 | The `purposeOfFunds` answer, explained. |
| `contactInfo` | string, 1–4000 | Any further contact or operational detail. |
| `identityDocuments` | array of `{type, number, issuingCountry}` | Identification issued **to the company**, where the jurisdiction issues any. Metadata only — see below. |

### `identityDocuments`

Both `company` and `people[]` take this array. It carries the metadata off an identity document; the file itself is still a `POST /dapi/v1/documents` upload filed into a `documents[]` slot, and neither replaces the other.

| Field | Type |
| - | - |
| `type` | enum |
| `number` | string, 1–200, exactly as printed |
| `issuingCountry` | ISO 3166-1 alpha-2 |

### `company.address` and `people[].address`

Both addresses take the same object. Four of its fields are required; `state` and `addressLine2` are not.

| Field | Type | Required |
| - | - | - |
| `streetAddress` | string, 1–200 | yes |
| `addressLine2` | string, 1–200 | no |
| `city` | string, 1–200 | yes |
| `state` | string, 1–200 | no |
| `zip` | string, 1–200 | yes |
| `country` | ISO 3166-1 alpha-2 | yes |

Write `state` as the ISO 3166-2 subdivision including its country prefix — `US-IL`, not `IL` and not `Illinois`.

## `people[]`

At least one person is required: a document with an empty roster reports `people` as missing. Give each person at least one role — `ownershipPercentage`, `hasControl`, `isDirector` or `isSigner` — or they are in the graph without being anything in it.

| Field | Type | Required | Notes |
| - | - | - | - |
| `key` | 1–64 of `A-Z a-z 0-9 . _ : -` | `key` or `id` | Your own stable handle for this person. HEVN derives their id from it, which is what makes the write idempotent. |
| `id` | UUID | `key` or `id` | Addresses a person who already exists in the client's graph. Takes precedence over `key`. A person with neither is refused. |
| `firstName` | string, 1–200 | no | |
| `middleName` | string, 1–200 | no | |
| `lastName` | string, 1–200 | no | |
| `dateOfBirth` | `YYYY-MM-DD` | no | |
| `email` | string, 1–200 | no | |
| `phone` | E.164 | yes | |
| `address` | object | yes | |
| `taxIdCountry` | ISO 3166-1 alpha-2 | yes | The country whose tax authority holds this person's number. Declared, never derived from the address. |
| `taxId` | string, 1–200 | US only | A US tax resident owes an SSN as `XXX-XX-XXXX`. |
| `ownershipPercentage` | decimal string, > 0 and ≤ 100 | no | |
| `hasControl` | boolean | no | |
| `isDirector` | boolean | no | |
| `isSigner` | boolean | no | |
| `documents` | array of `{slot, uploadId}` | yes | One `proof_of_address` per person. |

These six are optional and, like the company's, are read rather than demanded:

| Field | Type | Notes |
| - | - | - |
| `title` | string, 1–200 | The office held, for example `Director`. |
| `birthCountry` | ISO 3166-1 alpha-2 | Country of birth. |
| `nationalities` | array of ISO 3166-1 alpha-2 | Every nationality held. |
| `country` | ISO 3166-1 alpha-2 | Country of residence. Distinct from `taxIdCountry`, which is declared, and from `address.country`. |
| `linkedinUrl` | string, 1–2000 | The person's public LinkedIn profile. |
| `identityDocuments` | array of `{type, number, issuingCountry}` | Passport or ID metadata, as above. |

## Enums

Send one of the listed members. An unlisted value is refused at the boundary with `422 invalid_enum_value`, carrying `details.field` and the accepted set in `details.allowed` — nothing is written.

> [accordion] entityType
>
> `llc` · `corporation` · `s_corporation` · `c_corporation` · `partnership` · `limited_partnership` · `sole_proprietorship` · `nonprofit` · `trust` · `cooperative` · `dao` · `foundation` · `other`

> [accordion] businessType
>
> `technology` · `finance` · `healthcare` · `retail` · `e_commerce` · `manufacturing` · `real_estate` · `consulting` · `hospitality` · `education` · `transportation` · `entertainment` · `agriculture` · `construction` · `professional_services` · `crypto_web3` · `other`

> [accordion] sourceOfFunds
>
> `business_revenue` · `investment` · `loan` · `personal_savings` · `third_party_funds` · `grant` · `other`

> [accordion] purposeOfFunds
>
> `operations` · `payroll` · `vendor_payments` · `investment` · `treasury_management` · `international_transfers` · `other`

> [accordion] verifierRole
>
> `officer` · `employer` · `accountant` · `agent`

> [accordion] cryptoIndustrySubtype
>
> `protocol` · `exchange` · `investment` · `lender` · `market_maker` · `saas` · `miner`

> [accordion] primaryTargetMarket
>
> `retail` · `commercial` · `government` · `other`

> [accordion] revenueCovers
>
> `all_operating_expenses` · `most` · `some` · `minimal`

> [accordion] txPerMonth
>
> `<10` · `10-50` · `50-200` · `200-1,000` · `1,000+`
>
> These members are not identifiers. Send them exactly as printed, punctuation included.

> [accordion] highRiskActivities
>
> `MONEY_SERVICES` · `LENDING_BANKING` · `OTC_FX_CRYPTO_BROKERAGE` · `HOLD_CLIENT_FUNDS` · `INVESTMENT_SERVICES` · `SAFE_DEPOSIT_BOX` · `PRECIOUS_METALS_STONES_JEWELRY` · `NICOTINE_TOBACCO` · `MARIJUANA` · `PHARMACEUTICALS` · `THIRD_PARTY_PAYMENT_PROCESSING` · `ADULT_ENTERTAINMENT` · `WEAPONS_FIREARMS_EXPLOSIVES` · `GAMBLING`
>
> The one upper-case enum in the API.

> [accordion] identityDocuments\[].type
>
> `passport` · `id_card` · `drivers_license` · `driver_license` · `residence_permit` · `government_id` · `state_or_provincial_id` · `visa`

Two of these break the `snake_case` rule the rest of the API keeps: `highRiskActivities` is upper-case and `txPerMonth` carries digits and punctuation. Match them character for character.

## Document slots

A slot is a named place a document goes. You upload a file, get a `doc_…` id back, and file it into a slot with `{"slot": "...", "uploadId": "doc_..."}` — on the document's own `documents[]` for company papers, on a person's `documents[]` for theirs.

Every client needs these five on the company:

| Slot | What it is |
| - | - |
| `certificate_of_incorporation` | The registrar's proof the company exists. |
| `corporate_structure` | The ownership chart, down to the people. |
| `director_structure` | Who the directors are. |
| `proof_of_address` | A recent document showing the company's registered address. |
| `source_of_funds` | Evidence behind the `sourceOfFunds` answer. |

The jurisdiction adds to that list:

| `company.country` | Extra slot |
| - | - |
| `US` | `tax_identification_document` — the IRS letter that assigned the EIN. |
| `AE` | `vat_registration` — the FTA VAT/TRN registration certificate. |

And every person needs one:

| Slot | What it is |
| - | - |
| `proof_of_address` | A recent document showing where that person lives. |

Other slots exist and are accepted — `passport_front`, `national_id`, `articles_of_association`, `bank_statement`, `ubo_declaration`, `power_of_attorney` and more — and a reviewer may ask for one in an RFI. Send an unknown slot and the write answers `422 document_type_unsupported` with the full accepted list in `details.allowed`.

## Reading a `missing[]` path

Every entry is a path into the document you sent. Fix it there and write again.

| Path | Means |
| - | - |
| `company.flowOfFunds` | A company field is empty. |
| `company.address.zip` | A required address field is empty. |
| `people` | The roster is empty. Add at least one person. |
| `people[0].taxIdCountry` | A field on the first person in the document is empty. |
| `people[0].documents.proof_of_address` | That person's slot has nothing in it. |
| `documents.certificate_of_incorporation` | A company slot has nothing in it. |
| `graph.entities.<uuid>.phone` | The gap belongs to an entity the flat document does not own. |

The index in `people[0]` is the person's position in the `people` array of `GET /dapi/v1/client/kyb`, not the order you happened to send. Read the document back and index into that.

## Complex ownership

The flat document models one company owned directly by people; `hasIntermediateEntityOwnership` is where you declare that it does not. A chain with holding companies in it is written through HEVN's entity-graph routes, which are outside this API and available on request. The two models coexist: the flat document only ever replaces the people it created, and never touches an entity added another way — a write that would drop one answers `409 kyb_roster_conflict` with `details.entityIds`. Gaps belonging to those entities are the `graph.entities.<uuid>.<field>` rows above.

> [card] [Next: Errors](https://docs.gethevn.com/whitelabel/reference/errors.md)
>
> The envelope, and every slug the API can answer with.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.