Skip to main content

Company Verification

Verify a company end-to-end with registry checks, director screening, and UBO screening. This guide covers submitting company data, retrieving results, and interpreting the compliance report.

What Company Verification checks

When you submit a company for verification, Zenoo orchestrates four check types:
  1. Company Registry Verification. Legal name, registration number, incorporation status, registered address, directors, and shareholders from official registries.
  2. Company Screening (WorldCheck). PEP, sanctions, and adverse media screening on the company entity itself.
  3. Director Screening (WorldCheck). Individual screening for each director you provide or that the registry returns.
  4. UBO Screening (WorldCheck). Individual screening for each beneficial owner.

Data tiers

You can submit three levels of data. More data produces better matching and richer risk scoring.
Providing Standard tier or above is recommended for production. Minimum tier works for testing but produces less accurate risk scoring.
The bare minimum to run a registry check and company screening.
{
  "company_name": "Acme Holdings Ltd",
  "registration_number": "12345678",
  "country": "GB"
}
Adds external reference for idempotency, financial data, and entity identifiers.
{
  "company_name": "Acme Holdings Ltd",
  "registration_number": "12345678",
  "country": "GB",
  "company_type": "Private Limited Company (Ltd)",
  "incorporation_date": "2015-03-15",
  "industry": "Financial Services",
  "address_line_1": "123 High Street",
  "city": "London",
  "postcode": "EC1A 1BB",
  "external_reference": "YOUR-REF-2026-0042",
  "annual_revenue": 5000000,
  "employee_count": 45,
  "sic_codes": ["64110", "64205"],
  "status": "Active",
  "entity_id": "ent-abc-123",
  "directors": [
    {
      "first_name": "Jane",
      "last_name": "Smith",
      "date_of_birth": "1980-05-20",
      "nationality": "GB",
      "role": "Director",
      "entity_id": "ent-dir-456"
    }
  ],
  "ubos": [
    {
      "first_name": "John",
      "last_name": "Doe",
      "date_of_birth": "1975-11-10",
      "nationality": "GB",
      "ownership_percentage": 75,
      "role": "UBO",
      "entity_id": "ent-ubo-789"
    }
  ]
}

Field reference

FieldTypeRequiredDescription
company_namestringYesLegal name of the company
registration_numberstringYesOfficial registration or incorporation number
countrystringYesISO 3166-1 alpha-2 country code (e.g. GB, US, DE)
company_typestringNoLegal entity type (e.g. Private Limited Company (Ltd))
incorporation_datestringNoDate of incorporation in YYYY-MM-DD format
industrystringNoIndustry classification or description
address_line_1stringNoRegistered office street address
citystringNoRegistered office city
postcodestringNoRegistered office postal code
external_referencestringNoYour internal reference ID. Enables idempotency.
annual_revenuenumberNoAnnual revenue in base currency units
employee_countnumberNoNumber of employees
sic_codesstring[]NoStandard Industrial Classification codes
statusstringNoCompany status (e.g. Active, Dissolved)
entity_idstringNoYour internal entity identifier
directorsobject[]NoArray of director objects (see below)
ubosobject[]NoArray of beneficial owner objects (see below)
Director and UBO fields:
FieldTypeRequiredDescription
first_namestringYesFirst name
last_namestringYesLast name
date_of_birthstringNoDate of birth in YYYY-MM-DD format. Strongly recommended for screening accuracy.
nationalitystringNoISO 3166-1 alpha-2 country code
rolestringNoRole in the company (e.g. Director, UBO, Secretary)
ownership_percentagenumberNoBeneficial ownership percentage (UBOs only)
entity_idstringNoYour internal entity identifier
1

Submit company data

Results are returned directly in the response body. Add the X-SYNC-TIMEOUT header to set the maximum wait time in milliseconds.
curl -X POST \
  "https://instance.prod.onboardapp.io/api/gateway/execute/{project_hash}/api" \
  -H "Content-Type: application/json" \
  -H "X-API-KEY: your-api-key" \
  -H "X-SYNC-TIMEOUT: 60000" \
  -d '{
    "company_name": "Acme Holdings Ltd",
    "registration_number": "12345678",
    "country": "GB",
    "company_type": "Private Limited Company (Ltd)",
    "incorporation_date": "2015-03-15",
    "industry": "Financial Services",
    "address_line_1": "123 High Street",
    "city": "London",
    "postcode": "EC1A 1BB",
    "external_reference": "YOUR-REF-2026-0042",
    "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"
      }
    ]
  }'

Async mode

If you prefer non-blocking execution, call the /init endpoint without the X-SYNC-TIMEOUT header.
curl -X POST \
  "https://instance.prod.onboardapp.io/api/gateway/execute/{project_hash}/init" \
  -H "Content-Type: application/json" \
  -H "X-API-KEY: your-api-key" \
  -d '{
    "company_name": "Acme Holdings Ltd",
    "registration_number": "12345678",
    "country": "GB",
    "external_reference": "YOUR-REF-2026-0042",
    "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"
      }
    ]
  }'
Response:
{
  "tokens": {
    "pull": "eyJhbGciOiJIUzI1NiJ9.pull-token...",
    "start": "eyJhbGciOiJIUzI1NiJ9.start-token..."
  }
}
Store the pull token immediately. It is the only way to retrieve results. If you lose it, you must reinitiate the verification.
2

Retrieve results

Sync mode

Results are returned directly in the response body. Skip to the next step.

Async mode: poll for results

curl -X GET \
  "https://instance.prod.onboardapp.io/api/gateway/sharable-payload/{pull_token}"
StatusMeaning
200 with JSON bodyResults are ready
204 No ContentStill processing, retry after a delay
404Invalid or expired token
Polling strategy:
  • First 2 minutes: poll every 10 seconds
  • After 2 minutes: poll every 30 seconds
  • Typical completion time: 30 seconds to 5 minutes

Async mode: webhook notification

Configure a webhook endpoint to receive a verification.completed event when processing finishes. See Webhooks Guide for setup instructions.You can use both strategies together: webhooks for real-time notification, polling as a fallback.
3

Interpret the compliance report

A complete Company Verification response contains six sections: company details, screening results, beneficial owners, directors, risk assessment, and checks summary.
{
  "case_reference": "AML-2026-0042",
  "external_reference": "YOUR-REF-2026-0042",
  "processing_status": "complete",
  "overall_verdict": "Refer",
  "risk_tier": "Medium",
  "completed_at": "2026-01-15T14:32:00Z",

  "company": {
    "legal_name": "Acme Holdings Limited",
    "registration_number": "12345678",
    "jurisdiction": "GB",
    "company_status": "Active",
    "company_type": "Private Limited Company",
    "incorporation_date": "2015-03-15",
    "registered_address": "123 High Street, London, EC1A 1BB",
    "verification_status": "Verified",
    "verified_at": "2026-01-15T14:30:15Z"
  },

  "screening": {
    "pep_status": "No Hit",
    "sanctions_status": "No Hit",
    "adverse_media_status": "Hit",
    "adverse_media_count": 2,
    "screening_provider": "WorldCheck",
    "screening_completed_at": "2026-01-15T14:30:20Z"
  },

  "beneficial_owners": [
    {
      "name": "John Doe",
      "date_of_birth": "1975-11-10",
      "nationality": "GB",
      "ownership_percentage": 75,
      "pep_status": "No Hit",
      "sanctions_status": "No Hit",
      "adverse_media_status": "No Hit",
      "identity_verified": false
    }
  ],

  "directors": [
    {
      "name": "Jane Smith",
      "date_of_birth": "1980-05-20",
      "role": "Director",
      "pep_status": "No Hit",
      "sanctions_status": "No Hit",
      "adverse_media_status": "No Hit"
    }
  ],

  "risk_assessment": {
    "overall_score": 45,
    "tier": "Medium",
    "factors": [
      {
        "factor": "Adverse Media",
        "severity": "Medium",
        "detail": "2 adverse media articles found for company"
      }
    ]
  },

  "checks_summary": {
    "total": 5,
    "passed": 4,
    "referred": 1,
    "failed": 0,
    "checks": [
      {
        "type": "Company Registration",
        "status": "Pass",
        "provider": "Registry"
      },
      {
        "type": "Company Screening",
        "status": "Refer",
        "provider": "WorldCheck",
        "matches": 2
      },
      {
        "type": "Director Screening (Jane Smith)",
        "status": "Pass",
        "provider": "WorldCheck"
      },
      {
        "type": "UBO Screening (John Doe)",
        "status": "Pass",
        "provider": "WorldCheck"
      },
      {
        "type": "Directors Verification",
        "status": "Pass",
        "provider": "Registry"
      }
    ]
  },

  "compliance_metadata": {
    "cdd_completed": true,
    "cdd_completed_at": "2026-01-15T14:32:00Z",
    "edd_required": false,
    "reviewed_by": "system"
  }
}
Key fields to check:
  • overall_verdict. The top-level recommendation: Pass, Refer, or Fail.
  • risk_tier. Risk classification: Low, Medium, or High.
  • screening.*_status. Whether any screening category returned a match.
  • checks_summary.checks[]. Status of each individual check.
Store the case_reference in your database. You will need it for support queries, audit trails, and linking future updates.
4

Decision logic

Use the overall_verdict and risk_tier together to drive your onboarding workflow.
VerdictRisk TierRecommended Action
PassLowAuto-approve. Proceed with onboarding.
PassMediumAuto-approve with enhanced monitoring.
ReferMediumRoute to compliance analyst for manual review.
ReferHighRoute to senior compliance officer. Consider EDD.
FailAnyReject. Escalate to compliance team.
If sanctions_status is "Hit" on any entity (company, director, or UBO), halt onboarding immediately and escalate. Processing sanctioned entities may violate legal obligations in your jurisdiction.

How checks are orchestrated

When you submit a company for verification, the check framework automatically creates, executes, and tracks every verification requirement. Here is the orchestration flow: For Company Verification, all four check types (registry, company screening, director screening, UBO screening) are API-based and auto-execute immediately after case creation. You do not need to trigger them manually. Checks that return Refer or Fail automatically generate alerts in the case management system. Alerts for sanctions hits are always marked Critical priority.

Verdict mapping

The full Company Verification verdict mapping combines overall_verdict and risk_tier to determine the appropriate action across all scenarios:
VerdictRisk TierRecommended Action
PassLowAuto-approve. Proceed with onboarding.
PassMediumAuto-approve with enhanced monitoring. Schedule periodic re-screening.
ReferLowQuick manual review. Likely a minor data issue.
ReferMediumManual review required. Assign to a compliance analyst.
ReferHighSenior compliance review. Consider enhanced due diligence (EDD).
FailLowInvestigate the specific failure. May be a data quality issue.
FailMediumReject or request corrected information.
FailHighReject. Escalate to compliance team for review.

Auto-approve criteria

You can safely auto-approve a Company Verification when ALL of the following are true:
  • overall_verdict is "Pass".
  • risk_tier is "Low".
  • sanctions_status is "No Hit" on ALL entities (company, directors, UBOs).
  • pep_status is "No Hit" on ALL entities.
  • adverse_media_status is "No Hit".
decision-handler.js
function canAutoApprove(result) {
  if (result.overall_verdict !== "Pass") return false;
  if (result.risk_tier !== "Low") return false;

  // Check all screening statuses
  const screening = result.screening || {};
  if (screening.pep_status !== "No Hit") return false;
  if (screening.sanctions_status !== "No Hit") return false;
  if (screening.adverse_media_status !== "No Hit") return false;

  // Check directors and UBOs
  const entities = [
    ...(result.directors || []),
    ...(result.beneficial_owners || [])
  ];
  for (const entity of entities) {
    if (entity.pep_status !== "No Hit") return false;
    if (entity.sanctions_status !== "No Hit") return false;
  }

  return true;
}
Any other combination should go to manual review. Do not attempt to auto-approve verifications that do not meet every criterion above.

Idempotency

Always include external_reference in production requests to prevent duplicate verifications. If you submit the same reference twice, Zenoo returns the existing case tokens without creating a duplicate.
{
  "company_name": "Acme Holdings Ltd",
  "registration_number": "12345678",
  "country": "GB",
  "external_reference": "YOUR-REF-2026-0042"
}

Country codes

Use ISO 3166-1 alpha-2 codes for all country fields. Common codes:
CountryCode
United KingdomGB (not UK)
United StatesUS
IrelandIE
GermanyDE
FranceFR
NetherlandsNL
SwitzerlandCH
The country field determines which registry Zenoo queries and which screening jurisdiction applies.
Using UK instead of GB will return an error. Always use the ISO 3166-1 alpha-2 standard code GB for United Kingdom.

Next steps

  • Person Verification. Verify directors and UBOs individually with document and biometric checks.
  • Screening. Run standalone screening for ongoing monitoring.
  • Sync vs Async. Choose the right execution model for your integration.