> ## 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.

# Track KYB status

Verification is asynchronous. Bridge reviews the submission after the representative completes the hosted flow, and can revoke an endorsement later. Your app can poll for status or subscribe to webhooks. See Bridge's [customer status lifecycle](https://apidocs.bridge.xyz/platform/customers/customers/api) for how Bridge derives each status.

Before tracking status, [create a KYB link for the organization](/kyc-kyb/kyb).

## Fetch by API

<View title="REST API" icon="terminal">
  To read an organization's current KYB status, make a `GET` request to:

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

  The endpoint accepts the following query parameter:

  <ParamField query="provider" type="'bridge'">
    Only return status for this provider. If omitted, the response includes every provider the
    organization has been verified with.
  </ParamField>

  Below is a sample cURL command for this request:

  ```bash theme={"system"}
  curl --request GET 'https://api.privy.io/v1/organizations/xxxxx/kyb?provider=bridge' \
    -u "<your-privy-app-id>:<your-privy-app-secret>" \
    -H "privy-app-id: <your-privy-app-id>"
  ```

  The response is an array with one entry per provider. Privy fetches status from Bridge on every
  request, so revoked endorsements are reflected immediately.

  <ResponseField name="provider" type="'bridge'">
    Provider that verified the organization.
  </ResponseField>

  <ResponseField name="environment" type="'production' | 'sandbox'">
    Bridge environment the business customer belongs to.
  </ResponseField>

  <ResponseField name="status" type="string">
    Top-level status of the business customer, as reported by Bridge. A customer is `active` once any
    endorsement is approved.
  </ResponseField>

  <ResponseField name="tos" type="object">
    Terms of service state.

    <Expandable title="properties" defaultOpen>
      <ResponseField name="tos.status" type="string">
        Status of terms of service acceptance.
      </ResponseField>

      <ResponseField name="tos.link" type="string">
        URL to accept the terms of service. Present while acceptance is pending.
      </ResponseField>
    </Expandable>
  </ResponseField>

  <ResponseField name="kyb" type="object">
    Verification state.

    <Expandable title="properties" defaultOpen>
      <ResponseField name="kyb.status" type="string">
        Status of the organization's verification.
      </ResponseField>

      <ResponseField name="kyb.link" type="string">
        URL to complete verification. Present while verification is outstanding.
      </ResponseField>

      <ResponseField name="kyb.rejection_reasons" type="string[]">
        [Reasons](https://apidocs.bridge.xyz/platform/customers/customers/rejection_reasons) Bridge
        rejected the submission.
      </ResponseField>
    </Expandable>
  </ResponseField>

  <ResponseField name="endorsements" type="object[]">
    Endorsements requested for the organization.

    <Expandable title="properties" defaultOpen>
      <ResponseField name="endorsements[].name" type="string">
        Name of the
        [endorsement](https://apidocs.bridge.xyz/platform/customers/customers/endorsements), such as
        `base` or `sepa`.
      </ResponseField>

      <ResponseField name="endorsements[].status" type="string">
        Status of the endorsement, as reported by Bridge.
      </ResponseField>

      <ResponseField name="endorsements[].missing" type="string[] | null">
        Requirements Bridge is still waiting on. `null` when the endorsement is complete.
      </ResponseField>
    </Expandable>
  </ResponseField>

  <ResponseField name="capabilities" type="object">
    Status of each capability the business customer can use.

    <Expandable title="properties" defaultOpen>
      <ResponseField name="capabilities.payin_crypto" type="string">
        Whether the organization can deposit crypto.
      </ResponseField>

      <ResponseField name="capabilities.payout_crypto" type="string">
        Whether the organization can receive crypto payouts.
      </ResponseField>

      <ResponseField name="capabilities.payin_fiat" type="string">
        Whether the organization can deposit fiat.
      </ResponseField>

      <ResponseField name="capabilities.payout_fiat" type="string">
        Whether the organization can receive fiat payouts.
      </ResponseField>
    </Expandable>
  </ResponseField>

  <ResponseField name="requirements_due" type="string[]">
    Requirements the organization must still satisfy, such as linking a bank account.
  </ResponseField>

  <ResponseField name="future_requirements_due" type="string[]">
    Requirements the organization will need to satisfy in the future.
  </ResponseField>

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

## Webhooks

Privy emits an `organization.kyb.updated` [webhook](/api-reference/webhooks/overview) whenever an organization's verification state changes at Bridge, re-emitting Bridge's [customer webhooks](https://apidocs.bridge.xyz/platform/additional-information/webhooks/structure) as a Privy event. The payload carries a full state snapshot in `data` and a `changes` diff of the fields that moved, so your app can react to a specific transition without storing prior state.

<Info>
  Webhooks can be tested at no cost in development environments. To enable webhooks in production,
  upgrade to the Enterprise plan in the Privy Dashboard.
</Info>

<Expandable title="organization.kyb.updated attributes" defaultOpen="true">
  <ResponseField name="type" type="'organization.kyb.updated'" required>
    Type of the webhook event.
  </ResponseField>

  <ResponseField name="organization_id" type="string" required>
    ID of the Privy organization whose verification state changed.
  </ResponseField>

  <ResponseField name="provider" type="'bridge'" required>
    Provider that reported the change.
  </ResponseField>

  <ResponseField name="environment" type="'production' | 'sandbox'" required>
    Bridge environment the business customer belongs to.
  </ResponseField>

  <ResponseField name="data" type="object" required>
    Full snapshot of the organization's verification state at the time of the event.

    <Expandable title="properties" defaultOpen>
      <ResponseField name="data.status" type="string" required>
        Top-level status of the business customer, as reported by Bridge.
      </ResponseField>

      <ResponseField name="data.tos" type="object" required>
        Terms of service state, containing `status`.
      </ResponseField>

      <ResponseField name="data.kyb" type="object" required>
        Verification state, containing `status`.
      </ResponseField>

      <ResponseField name="data.endorsements" type="object[]" required>
        Endorsements for the organization. Each entry contains `name`, `status`, and `missing`,
        which is `null` when the endorsement is complete.
      </ResponseField>

      <ResponseField name="data.capabilities" type="object" required>
        Status of `payin_crypto`, `payout_crypto`, `payin_fiat`, and `payout_fiat`.
      </ResponseField>
    </Expandable>
  </ResponseField>

  <ResponseField name="changes" type="object" required>
    Fields that changed, keyed by dot-notation path. Each value is a `[previous, current]` tuple.
    Privy omits events where no meaningful verification field changed.
  </ResponseField>
</Expandable>

<Accordion title="Example: base endorsement approved">
  ```json theme={"system"}
  {
    "type": "organization.kyb.updated",
    "organization_id": "xxxxx",
    "provider": "bridge",
    "environment": "sandbox",
    "data": {
      "status": "active",
      "tos": {
        "status": "approved"
      },
      "kyb": {
        "status": "active"
      },
      "endorsements": [
        {
          "name": "base",
          "status": "approved",
          "missing": null
        }
      ],
      "capabilities": {
        "payin_crypto": "active",
        "payout_crypto": "active",
        "payin_fiat": "pending",
        "payout_fiat": "pending"
      }
    },
    "changes": {
      "endorsements.base.status": ["incomplete", "approved"],
      "capabilities.payin_crypto": ["pending", "active"]
    }
  }
  ```
</Accordion>

If an endorsement is incomplete, read `data.endorsements[].missing` for the requirements Bridge is still waiting on, then create a new KYB link for the organization to resolve them.

## Next steps

<CardGroup cols={2}>
  <Card title="Handling webhook events" icon="webhook" href="/user-management/users/webhooks/handling-events">
    Configure an endpoint to receive Privy webhook events
  </Card>

  <Card title="KYC" icon="user-check" href="/kyc-kyb/kyc">
    Verify an individual user
  </Card>
</CardGroup>
