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

# Webhook Events Reference

> A reference for Helium ID webhook event names, destinations, and payload expectations across individual and company verification flows.

Helium ID uses webhooks to notify your integration when verification progress changes or when a final outcome has been reached.

All webhook payloads use the same outer JSON shape:

```json theme={null}
{
  "event": "verification.successful",
  "data": {}
}
```

The `event` field tells you what happened. The `data` field contains the event payload.

If you want field-by-field payload definitions, see [Webhook Payload Schemas](/reference/webhook-payload-schemas).

## Webhook destinations

Each API key can be configured with two webhook destinations:

* **Events webhook URL** for progress updates
* **Decision webhook URL** for final outcomes

Progress events help you keep your UI or internal workflow in sync. Decision events tell you that a verification has reached a terminal result.

## Individual verification events

These events apply to sessions created with `POST /v1/verifications`.

| Event                                  | Destination      | Terminal? | Meaning                                                       |
| :------------------------------------- | :--------------- | :-------- | :------------------------------------------------------------ |
| `verification.started`                 | Events webhook   | No        | The end-user entered the hosted verification flow.            |
| `verification.selfie_uploaded`         | Events webhook   | No        | The end-user uploaded a selfie.                               |
| `verification.document_front_uploaded` | Events webhook   | No        | The end-user uploaded the front of their document.            |
| `verification.document_back_uploaded`  | Events webhook   | No        | The end-user uploaded the back of their document.             |
| `verification.processing_started`      | Events webhook   | No        | Helium ID started evaluating the submitted verification data. |
| `verification.biometrics_matched`      | Events webhook   | No        | The selfie and document face check matched.                   |
| `verification.successful`              | Decision webhook | Yes       | The verification was approved.                                |
| `verification.failed`                  | Decision webhook | Yes       | The verification was rejected.                                |

### Example individual decision payload

```json theme={null}
{
  "event": "verification.successful",
  "data": {
    "verificationId": "69d4f7657bcbe3b58b96b2f7",
    "vendorData": "user_12345",
    "statusCode": 2010,
    "docInfo": {
      "docType": "PASSPORT",
      "docNumber": "A1234567",
      "issueDate": "",
      "expiryDate": "2030-01-01",
      "issuingState": "GBR",
      "firstName": "JOHN",
      "lastName": "DOE",
      "middleName": "",
      "dob": "1990-01-01",
      "sex": "MALE"
    },
    "userSelfie": "https://example.com/selfie.jpg",
    "userIdBack": "",
    "userIdFront": "https://example.com/front.jpg"
  }
}
```

## Company verification events

These events apply to sessions created with `POST /v1/company-verifications`.

| Event                                     | Destination      | Terminal? | Meaning                                                                              |
| :---------------------------------------- | :--------------- | :-------- | :----------------------------------------------------------------------------------- |
| `company_verification.submitted`          | Events webhook   | No        | The representative completed the hosted flow and submitted the company verification. |
| `company_verification.liveness_completed` | Events webhook   | No        | The authorising-person liveness step completed.                                      |
| `company_verification.under_review`       | Events webhook   | No        | The company verification has moved into review.                                      |
| `company_verification.successful`         | Decision webhook | Yes       | The company verification was approved.                                               |
| `company_verification.failed`             | Decision webhook | Yes       | The company verification was rejected.                                               |

### Example company progress payload

```json theme={null}
{
  "event": "company_verification.submitted",
  "data": {
    "companyVerificationId": "69d4f7657bcbe3b58b96b2f7",
    "verificationId": "cv_0b5f6f4e0aab25d8c130ab21",
    "externalId": "cv_0b5f6f4e0aab25d8c130ab21",
    "vendorData": "business_12345",
    "status": "submitted",
    "reason": "",
    "submittedAt": "2026-08-18T12:00:00.000Z",
    "campaignId": "cmp_64ff2f3f4f31d4d5f2ab1234",
    "campaignVersion": 3,
    "companyProfile": {
      "business": {
        "legalName": "Acme Limited",
        "registrationNumber": "RC123456",
        "registrationType": "private_limited_company",
        "countryOfRegistration": "NGA",
        "businessBvn": "22334455667",
        "industry": "technology",
        "description": "Cross-border payments infrastructure",
        "website": "https://acme.example"
      },
      "contact": {
        "emails": {
          "general": "hello@acme.example",
          "representative": "jane@acme.example"
        },
        "phoneNumbers": {
          "general": "+2348000000000",
          "representative": "+2348111111111"
        },
        "addresses": {
          "registered": {
            "addressLine1": "12 Marina Road",
            "city": "Lagos",
            "state": "Lagos",
            "country": "NGA",
            "fullAddress": "12 Marina Road, Lagos, Lagos, NGA"
          }
        }
      },
      "authorisedRepresentative": {
        "firstName": "Jane",
        "lastName": "Doe",
        "fullName": "Jane Doe",
        "email": "jane@acme.example",
        "phoneNumber": "+2348111111111",
        "relationshipToBusiness": "Director",
        "isAuthorised": "yes"
      },
      "officers": [
        {
          "firstName": "Jane",
          "lastName": "Doe",
          "fullName": "Jane Doe",
          "role": "director",
          "email": "jane@acme.example"
        }
      ],
      "ownership": {
        "threshold": 25,
        "beneficialOwners": []
      }
    },
    "review": {
      "source": "mixed",
      "analysisStatus": "completed",
      "pendingInternalReview": true,
      "missingFields": [],
      "reviewFlags": [],
      "provisioning": {
        "ready": false,
        "pendingFields": []
      }
    }
  }
}
```

For company verification events, Helium ID includes a normalized `companyProfile` block and a `review` block so downstream systems such as banking or account-opening providers can consume the important business, contact, officer, ownership, and authority details without depending on raw internal form structures.

Those objects are part of the payload contract. What can vary is how complete the nested fields are at a given moment.

The example above shows `company_verification.submitted`, but `company_verification.successful` is sent with the same normalized payload shape. The main differences are the `event` name, the `status` value, and the review/readiness values that reflect the final approved state.

## How to decide which events to use

If you are building product logic:

* use the **events webhook** for progress tracking
* use the **decision webhook** for final approval or rejection handling

If you only care about final outcomes, you can listen to the decision webhook alone.

## Recommended storage on your side

To make webhook handling reliable, store:

* the webhook `event`
* the webhook `data`
* your own correlation key in `vendorData`
* the Helium ID verification identifier
* the API key environment used to create the verification

That will make retries, reconciliation, and support investigations much easier.

## Signature validation

Webhook payloads are signed with HMAC-SHA256 using your API key as the secret.

For implementation details, see [HMAC Authentication and Endpoint Security](/technical/hmac).
