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

# Recipe: Company Verification Integration

> A practical end-to-end recipe for creating a company verification, sending the representative into the hosted flow, and handling webhook outcomes.

This recipe shows the recommended company-verification integration pattern.

## What you will build

1. Create a company verification from your server
2. Store the public company verification ID
3. Send the representative to the hosted link
4. Handle progress and decision webhooks
5. Reconcile the result in your own system

## Step 1: Create the company verification

```bash theme={null}
curl -X POST "https://server.heliumid.io/api/v1/company-verifications" \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{
    "vendorData": "business_12345",
    "meta": {
      "applicationId": "app_67890"
    }
  }'
```

Store:

* `data.verificationId` as the public company verification ID
* `data.link`
* your own `vendorData`

## Step 2: Send the representative to the hosted flow

Use `data.link` exactly as returned.

For company verifications, the hosted URL contains:

* `processId` for the internal company verification ID
* `hostedToken` for secure access to the hosted flow

Do not rebuild this URL manually.

## Step 3: Listen for company webhooks

Progress events:

* `company_verification.submitted`
* `company_verification.liveness_completed`
* `company_verification.under_review`

Decision events:

* `company_verification.successful`
* `company_verification.failed`

## Step 4: Reconcile IDs correctly

Company verification uses both a public and internal ID.

* create-response `verificationId` = public company verification ID
* webhook `companyVerificationId` = internal company verification ID
* webhook `externalId` = public company verification ID

For most customer-facing systems, `externalId` is the most useful long-term reference.

## Step 5: Apply review logic

Recommended logic:

* when you receive `company_verification.submitted`, mark the case as awaiting review
* when you receive `company_verification.under_review`, mark the case as in review
* when you receive `company_verification.successful`, mark the business as approved
* when you receive `company_verification.failed`, mark the business as rejected and store the reason

## Environment behavior

* in **test**, customer admins can move company verifications through review and terminal states for integration testing
* in **live**, Helium ID controls final terminal decisions

See [Test vs Live Behavior](/technical/test-vs-live).

## Minimal Node.js handler example

```javascript theme={null}
app.post("/webhooks/helium", express.raw({ type: "*/*" }), (req, res) => {
  const rawBody = req.body.toString("utf8");
  const event = JSON.parse(rawBody);

  if (event.event === "company_verification.submitted") {
    const { externalId, vendorData } = event.data;
    // Mark the business case as submitted
  }

  if (event.event === "company_verification.successful") {
    const { externalId, vendorData } = event.data;
    // Mark the business as approved
  }

  if (event.event === "company_verification.failed") {
    const { externalId, vendorData, reason } = event.data;
    // Mark the business as rejected
  }

  res.status(200).send("ok");
});
```

## Recommended stored fields

For each company verification, store:

* public `verificationId` from the create response
* internal `companyVerificationId` when it first arrives by webhook
* `externalId`
* `vendorData`
* current status
* latest webhook event
* raw webhook payload
* environment used

That makes it much easier to tie together the API response, dashboard workflow, and webhook stream.
