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

# End-to-End Onboarding

> Walk through a full company onboarding lifecycle via the API: create an entity, open a case, run checks, review alerts, and close the case.

# End-to-End Onboarding

This guide walks you through a complete company onboarding lifecycle using the Zenoo CLM API. By the end you will have created an entity, opened an onboarding case, executed compliance checks, reviewed generated alerts, and closed the case.

## Prerequisites

* A valid API key (see [Authentication](/getting-started/authentication))
* Base URL: `https://api.zenoo.com/v1`

## What happens during onboarding

When you create an onboarding case, Zenoo automatically:

1. Creates verification requirements based on entity type and role
2. Executes API-based checks (screening, registry, identity)
3. Generates alerts for any hits (PEP, sanctions, adverse media)
4. Calculates a 4-dimension risk score

<Steps>
  <Step title="Create a company entity">
    Register the company you want to onboard. The response includes the entity token used in all subsequent calls.

    <CodeGroup>
      ```bash curl theme={null}
      curl -X POST https://api.zenoo.com/v1/entities \
        -H "Authorization: Bearer your-api-key" \
        -H "Content-Type: application/json" \
        -d '{
          "type": "company",
          "name": "Acme Holdings Ltd",
          "registration_number": "12345678",
          "country": "GB",
          "incorporation_date": "2015-03-15",
          "industry": "Financial Services",
          "directors": [
            {
              "first_name": "Jane",
              "last_name": "Smith",
              "date_of_birth": "1980-05-20",
              "nationality": "GB",
              "role": "Director"
            }
          ],
          "ubos": [
            {
              "first_name": "John",
              "last_name": "Doe",
              "date_of_birth": "1975-11-10",
              "nationality": "GB",
              "ownership_percentage": 75,
              "role": "UBO"
            }
          ]
        }'
      ```

      ```python Python theme={null}
      import requests

      response = requests.post(
          "https://api.zenoo.com/v1/entities",
          headers={
              "Authorization": "Bearer your-api-key",
              "Content-Type": "application/json",
          },
          json={
              "type": "company",
              "name": "Acme Holdings Ltd",
              "registration_number": "12345678",
              "country": "GB",
              "incorporation_date": "2015-03-15",
              "industry": "Financial Services",
              "directors": [
                  {
                      "first_name": "Jane",
                      "last_name": "Smith",
                      "date_of_birth": "1980-05-20",
                      "nationality": "GB",
                      "role": "Director",
                  }
              ],
              "ubos": [
                  {
                      "first_name": "John",
                      "last_name": "Doe",
                      "date_of_birth": "1975-11-10",
                      "nationality": "GB",
                      "ownership_percentage": 75,
                      "role": "UBO",
                  }
              ],
          },
      )
      entity = response.json()
      print(entity["token"])  # ent_abc123
      ```

      ```javascript Node.js theme={null}
      const response = await fetch("https://api.zenoo.com/v1/entities", {
        method: "POST",
        headers: {
          Authorization: "Bearer your-api-key",
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          type: "company",
          name: "Acme Holdings Ltd",
          registration_number: "12345678",
          country: "GB",
          incorporation_date: "2015-03-15",
          industry: "Financial Services",
          directors: [
            {
              first_name: "Jane",
              last_name: "Smith",
              date_of_birth: "1980-05-20",
              nationality: "GB",
              role: "Director",
            },
          ],
          ubos: [
            {
              first_name: "John",
              last_name: "Doe",
              date_of_birth: "1975-11-10",
              nationality: "GB",
              ownership_percentage: 75,
              role: "UBO",
            },
          ],
        }),
      });
      const entity = await response.json();
      console.log(entity.token); // ent_abc123
      ```
    </CodeGroup>

    **Response:**

    ```json theme={null}
    {
      "token": "ent_abc123",
      "type": "company",
      "name": "Acme Holdings Ltd",
      "status": "active",
      "created_at": "2026-02-16T10:00:00Z",
      "related_entities": [
        { "token": "ent_dir456", "name": "Jane Smith", "role": "Director" },
        { "token": "ent_ubo789", "name": "John Doe", "role": "UBO" }
      ]
    }
    ```
  </Step>

  <Step title="Create an onboarding case">
    Open an onboarding case linked to the entity. Zenoo automatically creates verification requirements and begins executing API-based checks.

    <CodeGroup>
      ```bash curl theme={null}
      curl -X POST https://api.zenoo.com/v1/cases \
        -H "Authorization: Bearer your-api-key" \
        -H "Content-Type: application/json" \
        -d '{
          "type": "Onboarding",
          "entity_token": "ent_abc123",
          "priority": "Medium",
          "external_reference": "YOUR-REF-2026-0042"
        }'
      ```

      ```python Python theme={null}
      response = requests.post(
          "https://api.zenoo.com/v1/cases",
          headers={
              "Authorization": "Bearer your-api-key",
              "Content-Type": "application/json",
          },
          json={
              "type": "Onboarding",
              "entity_token": "ent_abc123",
              "priority": "Medium",
              "external_reference": "YOUR-REF-2026-0042",
          },
      )
      case = response.json()
      print(case["token"])  # cas_xyz789
      ```

      ```javascript Node.js theme={null}
      const caseRes = await fetch("https://api.zenoo.com/v1/cases", {
        method: "POST",
        headers: {
          Authorization: "Bearer your-api-key",
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          type: "Onboarding",
          entity_token: "ent_abc123",
          priority: "Medium",
          external_reference: "YOUR-REF-2026-0042",
        }),
      });
      const caseData = await caseRes.json();
      console.log(caseData.token); // cas_xyz789
      ```
    </CodeGroup>

    **Response:**

    ```json theme={null}
    {
      "token": "cas_xyz789",
      "type": "Onboarding",
      "status": "New",
      "priority": "Medium",
      "entity_token": "ent_abc123",
      "due_date": "2026-03-02T10:00:00Z",
      "created_at": "2026-02-16T10:01:00Z"
    }
    ```

    <Info>
      The `due_date` is automatically calculated from SLA configuration based on case type and priority. An Onboarding/Medium case defaults to 14 calendar days.
    </Info>
  </Step>

  <Step title="List checks created for the case">
    Zenoo auto-creates checks based on entity type and role. List them to track progress.

    <CodeGroup>
      ```bash curl theme={null}
      curl -X GET "https://api.zenoo.com/v1/cases/cas_xyz789/checks" \
        -H "Authorization: Bearer your-api-key"
      ```

      ```python Python theme={null}
      response = requests.get(
          "https://api.zenoo.com/v1/cases/cas_xyz789/checks",
          headers={"Authorization": "Bearer your-api-key"},
      )
      checks = response.json()
      for check in checks["data"]:
          print(f"{check['type']} - {check['status']}")
      ```

      ```javascript Node.js theme={null}
      const checksRes = await fetch(
        "https://api.zenoo.com/v1/cases/cas_xyz789/checks",
        { headers: { Authorization: "Bearer your-api-key" } }
      );
      const checks = await checksRes.json();
      checks.data.forEach((c) => console.log(`${c.type} - ${c.status}`));
      ```
    </CodeGroup>

    **Response:**

    ```json theme={null}
    {
      "data": [
        { "token": "chk_001", "type": "PEP Screening", "category": "Screening", "entity": "Acme Holdings Ltd", "status": "In Progress" },
        { "token": "chk_002", "type": "Sanctions Screening", "category": "Screening", "entity": "Acme Holdings Ltd", "status": "In Progress" },
        { "token": "chk_003", "type": "Company Registry", "category": "Company", "entity": "Acme Holdings Ltd", "status": "Queued" },
        { "token": "chk_004", "type": "PEP Screening", "category": "Screening", "entity": "Jane Smith", "status": "Queued" },
        { "token": "chk_005", "type": "PEP Screening", "category": "Screening", "entity": "John Doe", "status": "Queued" },
        { "token": "chk_006", "type": "Identity Verification", "category": "Identity", "entity": "John Doe", "status": "Pending" }
      ],
      "meta": { "total": 6 }
    }
    ```
  </Step>

  <Step title="Wait for checks to complete">
    Checks execute asynchronously. Use webhooks (recommended) or poll the case status.

    **Option A: Webhook**

    Configure a webhook endpoint to receive `check.completed` and `check.failed` events. See [Webhook Events](/data-model/webhook-events).

    **Option B: Poll**

    <CodeGroup>
      ```bash curl theme={null}
      curl -X GET "https://api.zenoo.com/v1/cases/cas_xyz789" \
        -H "Authorization: Bearer your-api-key"
      ```

      ```python Python theme={null}
      import time

      while True:
          response = requests.get(
              "https://api.zenoo.com/v1/cases/cas_xyz789",
              headers={"Authorization": "Bearer your-api-key"},
          )
          case = response.json()
          if case["checks_summary"]["pending"] == 0:
              break
          time.sleep(10)
      ```

      ```javascript Node.js theme={null}
      async function waitForChecks(caseToken) {
        while (true) {
          const res = await fetch(
            `https://api.zenoo.com/v1/cases/${caseToken}`,
            { headers: { Authorization: "Bearer your-api-key" } }
          );
          const data = await res.json();
          if (data.checks_summary.pending === 0) return data;
          await new Promise((r) => setTimeout(r, 10000));
        }
      }
      ```
    </CodeGroup>
  </Step>

  <Step title="Review alerts generated">
    After checks complete, any screening hits generate alerts that require analyst review.

    <CodeGroup>
      ```bash curl theme={null}
      curl -X GET "https://api.zenoo.com/v1/cases/cas_xyz789/alerts" \
        -H "Authorization: Bearer your-api-key"
      ```

      ```python Python theme={null}
      response = requests.get(
          "https://api.zenoo.com/v1/cases/cas_xyz789/alerts",
          headers={"Authorization": "Bearer your-api-key"},
      )
      alerts = response.json()
      for alert in alerts["data"]:
          print(f"{alert['category']} - {alert['status']} (score: {alert['priority_score']})")
      ```

      ```javascript Node.js theme={null}
      const alertsRes = await fetch(
        "https://api.zenoo.com/v1/cases/cas_xyz789/alerts",
        { headers: { Authorization: "Bearer your-api-key" } }
      );
      const alerts = await alertsRes.json();
      alerts.data.forEach((a) =>
        console.log(`${a.category} - ${a.status} (score: ${a.priority_score})`)
      );
      ```
    </CodeGroup>

    **Response:**

    ```json theme={null}
    {
      "data": [
        {
          "token": "alt_alert01",
          "type": "Screening",
          "category": "PEP Match",
          "title": "PEP Match: John Doe",
          "status": "Open",
          "priority": "High",
          "priority_score": 78,
          "match_score": 92,
          "entity_name": "John Doe",
          "sla_due_date": "2026-02-18T10:00:00Z"
        }
      ],
      "meta": { "total": 1 }
    }
    ```
  </Step>

  <Step title="Resolve each alert">
    Review the alert details and resolve it with an action and justification.

    <CodeGroup>
      ```bash curl theme={null}
      curl -X POST https://api.zenoo.com/v1/alerts/alt_alert01/resolve \
        -H "Authorization: Bearer your-api-key" \
        -H "Content-Type: application/json" \
        -d '{
          "action": "Approve",
          "notes": "PEP match confirmed as former local councillor (2010-2014). Low risk position, no current exposure. EDD not required."
        }'
      ```

      ```python Python theme={null}
      response = requests.post(
          "https://api.zenoo.com/v1/alerts/alt_alert01/resolve",
          headers={
              "Authorization": "Bearer your-api-key",
              "Content-Type": "application/json",
          },
          json={
              "action": "Approve",
              "notes": "PEP match confirmed as former local councillor (2010-2014). Low risk position, no current exposure. EDD not required.",
          },
      )
      print(response.json()["status"])  # Resolved
      ```

      ```javascript Node.js theme={null}
      const resolveRes = await fetch(
        "https://api.zenoo.com/v1/alerts/alt_alert01/resolve",
        {
          method: "POST",
          headers: {
            Authorization: "Bearer your-api-key",
            "Content-Type": "application/json",
          },
          body: JSON.stringify({
            action: "Approve",
            notes:
              "PEP match confirmed as former local councillor (2010-2014). Low risk position, no current exposure. EDD not required.",
          }),
        }
      );
      const resolved = await resolveRes.json();
      console.log(resolved.status); // Resolved
      ```
    </CodeGroup>

    **Response:**

    ```json theme={null}
    {
      "token": "alt_alert01",
      "status": "Resolved",
      "resolution_action": "Approve",
      "resolved_at": "2026-02-16T11:30:00Z"
    }
    ```

    <Warning>
      A case cannot be closed while it has open alerts. Resolve or escalate every alert before closing.
    </Warning>
  </Step>

  <Step title="Close the case">
    Once all alerts are resolved, close the case with a summary.

    <CodeGroup>
      ```bash curl theme={null}
      curl -X POST https://api.zenoo.com/v1/cases/cas_xyz789/close \
        -H "Authorization: Bearer your-api-key" \
        -H "Content-Type: application/json" \
        -d '{
          "resolution_notes": "Company verified. Registry check passed. One PEP match on UBO (former local councillor) reviewed and approved. Risk tier: Medium."
        }'
      ```

      ```python Python theme={null}
      response = requests.post(
          "https://api.zenoo.com/v1/cases/cas_xyz789/close",
          headers={
              "Authorization": "Bearer your-api-key",
              "Content-Type": "application/json",
          },
          json={
              "resolution_notes": "Company verified. Registry check passed. One PEP match on UBO (former local councillor) reviewed and approved. Risk tier: Medium.",
          },
      )
      print(response.json()["status"])  # Closed
      ```

      ```javascript Node.js theme={null}
      const closeRes = await fetch(
        "https://api.zenoo.com/v1/cases/cas_xyz789/close",
        {
          method: "POST",
          headers: {
            Authorization: "Bearer your-api-key",
            "Content-Type": "application/json",
          },
          body: JSON.stringify({
            resolution_notes:
              "Company verified. Registry check passed. One PEP match on UBO (former local councillor) reviewed and approved. Risk tier: Medium.",
          }),
        }
      );
      const closed = await closeRes.json();
      console.log(closed.status); // Closed
      ```
    </CodeGroup>

    **Response:**

    ```json theme={null}
    {
      "token": "cas_xyz789",
      "status": "Closed",
      "risk_tier": "Medium",
      "risk_score": 45,
      "completed_at": "2026-02-16T11:35:00Z",
      "checks_summary": { "total": 6, "passed": 5, "referred": 1, "failed": 0 }
    }
    ```
  </Step>
</Steps>

## Next steps

* [Alert Review](/use-cases/alert-review). Triage and resolve alerts in bulk via the API.
* [Case Lifecycle Guide](/guides/case-lifecycle). Understand all status transitions and SLA rules.
* [Check Orchestration Guide](/guides/check-orchestration). Learn how checks are auto-created and executed.
* [Webhook Events](/data-model/webhook-events). Set up real-time notifications for case and check events.
