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

# Headless KYB

> Submit an organization's verification data from your server and own the KYB interface

With headless KYB, your app's server submits an [organization](/organizations/overview)'s verification data to Privy, and Privy forwards it to Bridge. No hosted Bridge link is involved, so your app owns the interface end to end.

Use [hosted KYB](/kyc-kyb/kyb) instead when Bridge should collect the business data and its owners' documents.

At a high level, headless KYB involves three steps:

<Steps>
  <Step title="Accept terms of service">
    An authorized representative accepts Bridge's terms of service, which produces an agreement ID.
  </Step>

  <Step title="Submit verification data">
    Your app's server submits the business data, its owners, and that agreement ID.
  </Step>

  <Step title="Track status">
    Bridge reviews the submission asynchronously. Your app polls status or consumes webhooks.
  </Step>
</Steps>

Before verifying organizations, [register a Bridge API key with Privy](/kyc-kyb/setup) and enable server-side flows for the environment the requests target.

<Tip>
  Bridge reviews business customers manually, so KYB usually takes longer than KYC for an
  individual. Bridge may also require the organization's associated persons to complete their own
  verification.
</Tip>

## Accept terms of service

Bridge requires a signed terms of service agreement before it will create or update a customer. Generate an acceptance link with [`POST /v1/organizations/{organization_id}/kyb/tos`](/kyc-kyb/kyb-tos), pass it to your frontend, and keep the agreement ID Bridge returns when the representative accepts.

Pass that ID as `client_agreement_id` on the submission. Privy stores it, so later submissions for the same organization may omit it and Privy replays the stored one.

## Submit verification data

<View title="NodeJS" icon="node-js">
  Use the `submit` method from the `kyb` resource on `organizations()`.

  ```ts {skip-check} theme={"system"}
  import {PrivyClient} from '@privy-io/node';

  const privy = new PrivyClient({
    appId: process.env.PRIVY_APP_ID!,
    appSecret: process.env.PRIVY_APP_SECRET!
  });

  const status = await privy.organizations().kyb.submit('<organization-id>', {
    provider: 'bridge',
    environment: 'sandbox',
    endorsements: ['base'],
    client_agreement_id: '<agreement-id-from-tos-acceptance>',
    data: {
      business_legal_name: 'Acme, Inc.',
      business_type: 'llc',
      business_description: 'Online marketplace for industrial supplies.',
      email: 'finance@example.com',
      incorporation_date: '2019-04-02',
      primary_website: 'https://example.com',
      registered_address: {
        street_line_1: '123 Market Street',
        city: 'San Francisco',
        subdivision: 'CA',
        postal_code: '94103',
        country: 'USA'
      },
      account_purpose: 'treasury_management',
      source_of_funds: 'sales_of_goods_and_services',
      high_risk_activities: ['none_of_the_above'],
      associated_persons: [
        {
          first_name: 'Alex',
          last_name: 'Doe',
          email: 'alex@example.com',
          date_of_birth: '1990-01-31',
          residential_address: {
            street_line_1: '123 Market Street',
            city: 'San Francisco',
            subdivision: 'CA',
            postal_code: '94103',
            country: 'USA'
          },
          identifying_information: [
            {
              type: 'ssn',
              issuing_country: 'USA',
              number: '000-00-0000'
            }
          ],
          has_ownership: true,
          has_control: true,
          is_signer: true,
          title: 'Chief Executive Officer',
          ownership_percentage: 100
        }
      ]
    }
  });

  // status.kyb.status is Bridge's verification status
  // status.requirements_due lists what Bridge is still waiting on
  ```
</View>

<View title="REST API" icon="terminal">
  To submit KYB data for an organization, make a `POST` request to:

  ```bash theme={"system"}
  https://api.privy.io/v1/organizations/{organization_id}/kyb/submit
  ```

  See the [API reference](/api-reference/fiat/kyb/submit) for the full request and response schema.

  In the body of the request, include the following fields:

  <ParamField body="provider" type="'bridge'" required>
    Provider to verify the organization with.
  </ParamField>

  <ParamField body="environment" type="'production' | 'sandbox'">
    Bridge environment to use. Defaults to `production`.
  </ParamField>

  <ParamField body="endorsements" type="string[]">
    [Endorsements](https://apidocs.bridge.xyz/platform/customers/customers/endorsements) to request
    from Bridge. Each endorsement unlocks a set of rails and regions.
  </ParamField>

  <ParamField body="client_agreement_id" type="string">
    Identifier of the Bridge terms of service agreement the representative accepted, between 1 and
    1024 characters. Privy replays the stored agreement ID when this is omitted.
  </ParamField>

  <ParamField body="data" type="object" required>
    Verification data for the business. Must include at least one field. Every field is optional
    because Bridge accepts partial submissions, but Bridge grants no endorsement until enough data has
    arrived.
  </ParamField>

  Below is a sample cURL command for this request:

  ```bash theme={"system"}
  curl --request POST https://api.privy.io/v1/organizations/xxxxx/kyb/submit \
    -u "<your-privy-app-id>:<your-privy-app-secret>" \
    -H "privy-app-id: <your-privy-app-id>" \
    -H 'Content-Type: application/json' \
    -d '{
      "provider": "bridge",
      "environment": "sandbox",
      "endorsements": ["base"],
      "client_agreement_id": "<agreement-id-from-tos-acceptance>",
      "data": {
        "business_legal_name": "Acme, Inc.",
        "business_type": "llc",
        "business_description": "Online marketplace for industrial supplies.",
        "email": "finance@example.com",
        "incorporation_date": "2019-04-02",
        "primary_website": "https://example.com",
        "registered_address": {
          "street_line_1": "123 Market Street",
          "city": "San Francisco",
          "subdivision": "CA",
          "postal_code": "94103",
          "country": "USA"
        },
        "account_purpose": "treasury_management",
        "source_of_funds": "sales_of_goods_and_services",
        "high_risk_activities": ["none_of_the_above"],
        "associated_persons": [
          {
            "first_name": "Alex",
            "last_name": "Doe",
            "email": "alex@example.com",
            "date_of_birth": "1990-01-31",
            "residential_address": {
              "street_line_1": "123 Market Street",
              "city": "San Francisco",
              "subdivision": "CA",
              "postal_code": "94103",
              "country": "USA"
            },
            "identifying_information": [
              {
                "type": "ssn",
                "issuing_country": "USA",
                "number": "000-00-0000"
              }
            ],
            "has_ownership": true,
            "has_control": true,
            "is_signer": true,
            "title": "Chief Executive Officer",
            "ownership_percentage": 100
          }
        ]
      }
    }'
  ```

  The response is the organization's full KYB status snapshot, in the same shape as [track KYB
  status](/kyc-kyb/kyb-status).

  ```json theme={"system"}
  {
    "provider": "bridge",
    "environment": "sandbox",
    "status": "under_review",
    "tos": {
      "status": "approved"
    },
    "kyb": {
      "status": "under_review"
    },
    "endorsements": [
      {
        "name": "base",
        "status": "incomplete",
        "missing": ["kyc_approval"]
      }
    ],
    "capabilities": {
      "payin_crypto": "pending",
      "payout_crypto": "pending",
      "payin_fiat": "pending",
      "payout_fiat": "pending"
    },
    "requirements_due": ["id_verification"],
    "future_requirements_due": []
  }
  ```
</View>

Unlike KYC, Privy does not fall back to a stored email for a business customer. Send `email` explicitly on the first submission.

## Business data fields

`data` mirrors Bridge's business customer payload. Values that Bridge defines, such as `business_type` and `account_purpose`, are passed through unchanged, so the [Bridge customer API reference](https://apidocs.bridge.xyz/platform/customers/customers/api) is the source of truth for accepted values.

<AccordionGroup>
  <Accordion title="Identity and naming">
    | Field                                | Type       | Description                                                                |
    | ------------------------------------ | ---------- | -------------------------------------------------------------------------- |
    | `business_legal_name`                | `string`   | Registered legal name as filed with government authorities.                |
    | `business_trade_name`                | `string`   | Public trading name (DBA), if different from the legal name.               |
    | `transliterated_business_legal_name` | `string`   | Latin-1 transliteration of the legal name. Required for non-Latin-1 names. |
    | `transliterated_business_trade_name` | `string`   | Latin-1 transliteration of the trade name. Required for non-Latin-1 names. |
    | `business_description`               | `string`   | Short summary of what the business does.                                   |
    | `business_type`                      | `string`   | Legal structure of the business, such as `llc`.                            |
    | `business_industry`                  | `string[]` | 2022 NAICS codes for the industries the business operates in.              |
    | `email`                              | `string`   | Primary business email address.                                            |
    | `phone`                              | `string`   | Business phone number in E.164 format.                                     |
    | `incorporation_date`                 | `string`   | Date of incorporation in `YYYY-MM-DD` format.                              |
    | `is_dao`                             | `boolean`  | Whether the business is a decentralized autonomous organization.           |
  </Accordion>

  <Accordion title="Web presence">
    | Field             | Type       | Description                                                                        |
    | ----------------- | ---------- | ---------------------------------------------------------------------------------- |
    | `primary_website` | `string`   | Primary website. If omitted, a `proof_of_nature_of_business` document is required. |
    | `other_websites`  | `string[]` | Additional websites and social handles.                                            |
  </Accordion>

  <Accordion title="Addresses">
    | Field                               | Type     | Description                                                                            |
    | ----------------------------------- | -------- | -------------------------------------------------------------------------------------- |
    | `registered_address`                | `object` | Address the business is registered at.                                                 |
    | `physical_address`                  | `object` | Physical operating address. Cannot be a PO box.                                        |
    | `transliterated_registered_address` | `object` | Latin-1 transliteration of the registered address. Required for non-Latin-1 addresses. |
    | `transliterated_physical_address`   | `object` | Latin-1 transliteration of the physical address. Required for non-Latin-1 addresses.   |

    Each address takes `street_line_1` (at least 4 characters), `street_line_2`, `city`, `subdivision` (ISO 3166-2, required for US addresses), `postal_code`, and `country` (ISO 3166-1 alpha-3).
  </Accordion>

  <Accordion title="Ownership and structure">
    | Field                                 | Type       | Description                                                                                                                   |
    | ------------------------------------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------- |
    | `ownership_threshold`                 | `number`   | Ownership percentage, between 5 and 25, at which a person is treated as a beneficial owner.                                   |
    | `has_material_intermediary_ownership` | `boolean`  | Whether an intermediate entity owner holds 25% or more of the business.                                                       |
    | `publicly_traded_listings`            | `object[]` | Public exchange listings, each with `market_identifier_code` (ISO 10383), `stock_number` (ISIN without dashes), and `ticker`. |
    | `associated_persons`                  | `object[]` | Beneficial owners, control persons, and signers. See [associated persons](#associated-persons).                               |
  </Accordion>

  <Accordion title="Financial and risk profile">
    | Field                                  | Type       | Description                                                                                    |
    | -------------------------------------- | ---------- | ---------------------------------------------------------------------------------------------- |
    | `estimated_annual_revenue_usd`         | `string`   | Estimated annual revenue bucket, such as `1000000_9999999`. Required for high-risk businesses. |
    | `expected_monthly_payments_usd`        | `number`   | Expected monthly payment volume in USD. Required for high-risk businesses.                     |
    | `source_of_funds`                      | `string`   | Primary source of funds, such as `sales_of_goods_and_services`.                                |
    | `source_of_funds_description`          | `string`   | Free-text detail on the source of funds. Required for high-risk businesses.                    |
    | `account_purpose`                      | `string`   | Primary purpose of the account, such as `treasury_management`.                                 |
    | `account_purpose_other`                | `string`   | Free-text purpose. Required when `account_purpose` is `other`.                                 |
    | `acting_as_intermediary`               | `boolean`  | Whether the business moves funds on behalf of third parties.                                   |
    | `operates_in_prohibited_countries`     | `boolean`  | Whether the business operates in prohibited jurisdictions.                                     |
    | `high_risk_activities`                 | `string[]` | High-risk activities the business engages in.                                                  |
    | `high_risk_activities_explanation`     | `string`   | Explanation of those activities. Required unless the only value is `none_of_the_above`.        |
    | `conducts_money_services`              | `boolean`  | Whether the business conducts money services.                                                  |
    | `conducts_money_services_using_bridge` | `boolean`  | Whether money services run through Bridge. Requires a `flow_of_funds` document when true.      |
    | `conducts_money_services_description`  | `string`   | Description of the money services conducted.                                                   |
    | `compliance_screening_explanation`     | `string`   | Description of the AML and sanctions screening controls in place.                              |
    | `has_foreign_tax_registration`         | `boolean`  | Whether the business is tax-registered outside its country of incorporation.                   |
  </Accordion>

  <Accordion title="Regulatory">
    | Field                | Type     | Description                                                                                                                                                                                                                    |
    | -------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
    | `regulated_activity` | `object` | Regulated activity details, if the business holds a license. Takes `regulated_activities_description`, `primary_regulatory_authority_country` (ISO 3166-1 alpha-3), `primary_regulatory_authority_name`, and `license_number`. |
  </Accordion>

  <Accordion title="Documents">
    | Field                     | Type       | Description                                                                                                                                                                     |
    | ------------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `identifying_information` | `object[]` | Business tax and registration identifiers, each with `type`, `issuing_country` (ISO 3166-1 alpha-3), and `number`.                                                              |
    | `documents`               | `object[]` | Supporting documents, each with `purposes` (such as `business_formation`), `file` (a base64-encoded data URI), and `description`, required when `other` is one of the purposes. |
  </Accordion>
</AccordionGroup>

### Associated persons

Each entry in `associated_persons` is a beneficial owner, control person, or signer. At least one of `has_ownership`, `has_control`, or `is_signer` must be true, and the business must have at least one control person and one signer.

| Field                                | Type       | Description                                                                 |
| ------------------------------------ | ---------- | --------------------------------------------------------------------------- |
| `first_name`                         | `string`   | Legal first name. Required.                                                 |
| `middle_name`                        | `string`   | Legal middle name.                                                          |
| `last_name`                          | `string`   | Legal last name. Required.                                                  |
| `transliterated_first_name`          | `string`   | Latin-1 transliteration. Required for non-Latin-1 names.                    |
| `transliterated_middle_name`         | `string`   | Latin-1 transliteration. Required for non-Latin-1 names.                    |
| `transliterated_last_name`           | `string`   | Latin-1 transliteration. Required for non-Latin-1 names.                    |
| `email`                              | `string`   | Email address. Required.                                                    |
| `phone`                              | `string`   | Phone number in E.164 format.                                               |
| `date_of_birth`                      | `string`   | Date of birth in `YYYY-MM-DD` format. Must be 18 or older. Required.        |
| `residential_address`                | `object`   | Residential address. Cannot be a PO box. Required.                          |
| `transliterated_residential_address` | `object`   | Latin-1 transliteration of the address. Required for non-Latin-1 addresses. |
| `identifying_information`            | `object[]` | Identifying documents for this person. Required.                            |
| `has_ownership`                      | `boolean`  | Whether this person owns 25% or more of the business. Required.             |
| `has_control`                        | `boolean`  | Whether this person is a control person. Required.                          |
| `is_signer`                          | `boolean`  | Whether this person is a signer for the business. Required.                 |
| `is_director`                        | `boolean`  | Whether this person is a director.                                          |
| `title`                              | `string`   | Job title. Required when `has_control` is true.                             |
| `ownership_percentage`               | `number`   | Percentage of the business this person owns, between 0 and 100.             |
| `nationalities`                      | `string[]` | ISO 3166-1 alpha-3 codes for all nationalities held.                        |
| `place_of_birth`                     | `object`   | Place of birth, with `country` (ISO 3166-1 alpha-3) and `city`.             |
| `relationship_established_at`        | `string`   | Date the relationship with the business began, in `YYYY-MM-DD` format.      |
| `documents`                          | `object[]` | Supporting documents for this person, such as proof of address.             |

<Warning>
  Owners cannot be changed after the first submission; later submissions must omit
  `associated_persons` or repeat the existing owners.
</Warning>

<Note>
  Later submissions update the same Bridge customer. Omitted top-level fields are left untouched,
  including `email`; sending a different `email` replaces the address Bridge has on file, and since
  Bridge identifies customers by email, the old address stops resolving to this one. Nested objects
  such as an address are replaced whole. If a response never reached you, resubmit the identical
  data.
</Note>

<Warning>
  Bridge allows one customer per email address, across businesses and individuals alike. A
  submission whose email already has a Bridge customer returns `409` — Privy will not adopt an
  existing customer, since an email in a request body is not proof the organization owns it. Submit
  a different email, or contact [support@privy.io](mailto:support@privy.io) to link an existing
  Bridge customer to a Privy organization.
</Warning>

## Next steps

<CardGroup cols={2}>
  <Card title="Track KYB status" icon="magnifying-glass" href="/kyc-kyb/kyb-status">
    Poll an organization's verification status or subscribe to webhooks
  </Card>

  <Card title="Headless KYC" icon="user-check" href="/kyc-kyb/kyc-headless">
    Submit a user's verification data from your server
  </Card>
</CardGroup>
