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

# Entity Deep Check

> Deep check: extended PEP/RCA exposure screening, the Dutch insolvency
register on every tier, adverse media on the extended tier, an
Italian credit report on the credit tier.

`pep_extended` is the source the base check does not return. /v1/entity/check
queries the same OpenSanctions collection but filters to sanctions/enforcement
datasets and reduces the answer to a boolean (app/services/sanctions.py); the
role.pep/role.rca detail is fetched and discarded. This endpoint keeps it.

`insolvency_records` is the Centraal Insolventieregister (NL only; for any other
country the field says `applicable: false`). It is queried by `kvk_number` when
the body carries one (exact), else by `entity_name` (trade-name search).

`credit_report` is an Openapi.com credit score, Italy only, available when
OPENAPI_CREDIT_API_KEY is configured -- see /health. For any other country, or
a supported one with no `credit_report_identifier` (VAT number, tax code or
company ID) in the body, the field says `applicable: false` rather than being
omitted or erroring, the same pattern `insolvency_records` uses for non-NL, and
the `credit` tier's premium is never billed for it (app/middleware/x402.py
probes the country before pricing the call).

Three tiers, resolved from X-Response-Quality by the x402 middleware: `fresh`
(default; the `deep` tier, $0.88) returns pep_extended and insolvency_records;
`enhanced` (the `extended` tier, $1.71) adds `adverse_media` from dilisense;
`credit` ($2.45, Italy only, available when enabled) adds `credit_report`
instead. There is no cache-only branch, so `cached` is quoted, charged and
served as `fresh`. If a source of the requested tier cannot be reached the
answer is a 503 (`pep_source_unavailable`, `insolvency_source_unavailable`,
`adverse_media_source_unavailable` or `credit_report_source_unavailable`),
never a fabricated clean screen, and the x402 gate settles only on a 2xx so the
call is not charged.



## OpenAPI

````yaml /api-reference/openapi.json post /v1/entity/deep-check
openapi: 3.1.0
info:
  title: Limitguard.ai
  description: >-
    Lead validation API: the company behind each lead checked against the NL and
    BE business registers, EU VAT and sanctions lists, plus company, KYB and
    agent wallet checks for developers and AI agents
  version: 0.1.0
servers:
  - url: https://api.limitguard.ai
security: []
paths:
  /v1/entity/deep-check:
    post:
      summary: Entity Deep Check
      description: >-
        Deep check: extended PEP/RCA exposure screening, the Dutch insolvency

        register on every tier, adverse media on the extended tier, an

        Italian credit report on the credit tier.


        `pep_extended` is the source the base check does not return.
        /v1/entity/check

        queries the same OpenSanctions collection but filters to
        sanctions/enforcement

        datasets and reduces the answer to a boolean
        (app/services/sanctions.py); the

        role.pep/role.rca detail is fetched and discarded. This endpoint keeps
        it.


        `insolvency_records` is the Centraal Insolventieregister (NL only; for
        any other

        country the field says `applicable: false`). It is queried by
        `kvk_number` when

        the body carries one (exact), else by `entity_name` (trade-name search).


        `credit_report` is an Openapi.com credit score, Italy only, available
        when

        OPENAPI_CREDIT_API_KEY is configured -- see /health. For any other
        country, or

        a supported one with no `credit_report_identifier` (VAT number, tax code
        or

        company ID) in the body, the field says `applicable: false` rather than
        being

        omitted or erroring, the same pattern `insolvency_records` uses for
        non-NL, and

        the `credit` tier's premium is never billed for it
        (app/middleware/x402.py

        probes the country before pricing the call).


        Three tiers, resolved from X-Response-Quality by the x402 middleware:
        `fresh`

        (default; the `deep` tier, $0.88) returns pep_extended and
        insolvency_records;

        `enhanced` (the `extended` tier, $1.71) adds `adverse_media` from
        dilisense;

        `credit` ($2.45, Italy only, available when enabled) adds
        `credit_report`

        instead. There is no cache-only branch, so `cached` is quoted, charged
        and

        served as `fresh`. If a source of the requested tier cannot be reached
        the

        answer is a 503 (`pep_source_unavailable`,
        `insolvency_source_unavailable`,

        `adverse_media_source_unavailable` or
        `credit_report_source_unavailable`),

        never a fabricated clean screen, and the x402 gate settles only on a 2xx
        so the

        call is not charged.
      operationId: entity_deep_check_v1_entity_deep_check_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DeepCheckRequest'
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeepCheckResponse'
        '422':
          description: Validation error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '503':
          description: >-
            A source of the requested tier is unavailable; payment is not
            settled
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
        - APIKeyHeader: []
components:
  schemas:
    DeepCheckRequest:
      properties:
        entity_name:
          type: string
          maxLength: 500
          minLength: 1
          title: Entity Name
          description: Legal entity or person name
        country:
          type: string
          maxLength: 2
          minLength: 2
          title: Country
          description: ISO 3166-1 alpha-2 country code
        kvk_number:
          anyOf:
            - type: string
            - type: 'null'
          title: Kvk Number
          description: >-
            Dutch KVK number (8 digits); enables an exact insolvency-register
            lookup
        credit_report_identifier:
          anyOf:
            - type: string
              maxLength: 32
            - type: 'null'
          title: Credit Report Identifier
          description: >-
            VAT number, tax code or company ID for the `credit` tier's provider
            (Italy only today); without it the tier still runs but credit_report
            comes back applicable: false, same as an unsupported country
      additionalProperties: false
      type: object
      required:
        - entity_name
        - country
      title: DeepCheckRequest
      description: >-
        Request for POST /v1/entity/deep-check.


        Takes entity fields rather than an ``entity_id`` from a prior check: the
        audit

        trail is keyed by sha256(entity_name) and is one-way, so an id could not
        be

        resolved back to the name the screens have to query. ``kvk_number`` is
        optional

        and only consulted by the insolvency source: the Centraal

        Insolventieregister keys ``searchUndertaking`` on the KvK number, which
        is an

        exact lookup where a trade-name search is a fuzzy one.
        ``credit_report_identifier``

        is only consulted by the `credit` tier's source: Openapi.com's Italian

        credit-score lookup keys on a VAT number, tax code or company ID rather
        than a

        name, and reports back in `identifier_type` which one it matched.
    DeepCheckResponse:
      properties:
        entity_name:
          type: string
          title: Entity Name
        country:
          type: string
          title: Country
        quality:
          type: string
          title: Quality
          description: >-
            deep (fresh), extended (enhanced) or credit; see
            DEEP_CHECK_TIER_NAMES. `credit` only resolves while
            OPENAPI_CREDIT_API_KEY is configured.
          default: deep
        sources_returned:
          items:
            type: string
          type: array
          title: Sources Returned
          description: Sources actually run; equals EnhancedCheckHint.adds
        pep_extended:
          $ref: '#/components/schemas/PepScreenResult'
        adverse_media:
          anyOf:
            - $ref: '#/components/schemas/AdverseMediaResult'
            - type: 'null'
          description: >-
            Populated only on a tier whose adds include `adverse_media`. None
            means the tier did not include it -- never that a screen ran and
            found nothing.
        insolvency_records:
          anyOf:
            - $ref: '#/components/schemas/InsolvencyRecordsResult'
            - type: 'null'
          description: >-
            Dutch Centraal Insolventieregister screen; on every tier.
            `applicable: false` (never null) when `country` is not NL.
        credit_report:
          anyOf:
            - $ref: '#/components/schemas/CreditReportResult'
            - type: 'null'
          description: >-
            Populated only on the `credit` tier. None means the tier did not
            include it -- never that a screen ran and found no credit risk.
            `applicable: false` inside it (never omission) means the tier was
            requested but the country has no provider or no identifier was sent.
        processing_time_ms:
          type: integer
          minimum: 0
          title: Processing Time Ms
        disclaimers:
          items:
            type: string
          type: array
          title: Disclaimers
        sandbox:
          type: boolean
          title: Sandbox
          default: false
        version:
          type: string
          title: Version
          default: '1.0'
      type: object
      required:
        - entity_name
        - country
        - sources_returned
        - pep_extended
        - processing_time_ms
      title: DeepCheckResponse
      description: >-
        Response from /v1/entity/deep-check.


        ``sources_returned`` is built from payment.DEEP_CHECK_TIER_ADDS[tier] --
        the same

        table enhanced_check_hint advertises -- so what was promised and what
        was delivered

        are one value. A name may only join that table together with the field
        that fills

        it on that tier.
    ErrorResponse:
      properties:
        type:
          type: string
          title: Type
          default: about:blank
        title:
          type: string
          title: Title
        status:
          type: integer
          title: Status
        detail:
          anyOf:
            - type: string
            - type: 'null'
          title: Detail
        instance:
          anyOf:
            - type: string
            - type: 'null'
          title: Instance
      type: object
      required:
        - title
        - status
      title: ErrorResponse
      description: RFC 7807 Problem Details response.
    PepScreenResult:
      properties:
        screened:
          type: boolean
          title: Screened
          description: True when OpenSanctions was actually queried
        pep_exposure:
          type: boolean
          title: Pep Exposure
          description: True when at least one role.pep/role.rca match cleared threshold
        match_count:
          type: integer
          minimum: 0
          title: Match Count
        matches:
          items:
            $ref: '#/components/schemas/PepMatch'
          type: array
          title: Matches
        truncated:
          type: boolean
          title: Truncated
          description: True when matches were capped
          default: false
        retrieved_at:
          type: string
          title: Retrieved At
          description: ISO 8601 UTC timestamp of the query
      type: object
      required:
        - screened
        - pep_exposure
        - match_count
        - retrieved_at
      title: PepScreenResult
      description: >-
        Result of the `pep_extended` source. `screened` is never False on a 200.


        There is no code path that returns this model without having queried

        OpenSanctions: app/services/pep.py raises rather than fabricating a
        clean screen,

        and the router turns that into a 503 so the payment is never settled.
    AdverseMediaResult:
      properties:
        screened:
          type: boolean
          title: Screened
          description: True when dilisense was actually queried
        adverse_media_found:
          type: boolean
          title: Adverse Media Found
          description: True when the vendor reported at least one news exposure
        match_count:
          type: integer
          minimum: 0
          title: Match Count
          description: Total exposures reported (total_hits)
        category_hits:
          additionalProperties:
            type: integer
          type: object
          title: Category Hits
          description: Exposures per dilisense category
        articles:
          items:
            $ref: '#/components/schemas/AdverseMediaArticle'
          type: array
          title: Articles
        truncated:
          type: boolean
          title: Truncated
          description: True when articles were capped below match_count
          default: false
        retrieved_at:
          type: string
          title: Retrieved At
          description: ISO 8601 UTC timestamp of the query
      type: object
      required:
        - screened
        - adverse_media_found
        - match_count
        - retrieved_at
      title: AdverseMediaResult
      description: >-
        Result of the `adverse_media` source. `screened` is never False on a
        200.


        Mirrors PepScreenResult: app/services/adverse_media.py raises rather
        than

        fabricating a clean screen, and the router turns that into a 503 so the
        payment

        is never settled. A negative means no *indexed reporting* matched,

        not that no wrongdoing exists; `screened` and `adverse_media_found` are
        separate

        fields so a caller can tell "looked, found nothing" from "did not look".
    InsolvencyRecordsResult:
      properties:
        screened:
          type: boolean
          title: Screened
          description: True when the register was actually queried
        applicable:
          type: boolean
          title: Applicable
          description: False when `country` is outside the register's jurisdiction (NL)
        jurisdiction:
          type: string
          title: Jurisdiction
          description: Jurisdiction the register covers
          default: NL
        query_by:
          anyOf:
            - type: string
            - type: 'null'
          title: Query By
          description: kvk_number or name; None when not applicable
        found:
          type: boolean
          title: Found
          description: True when at least one insolvency proceeding was listed
        match_count:
          anyOf:
            - type: integer
              minimum: 0
            - type: 'null'
          title: Match Count
          description: >-
            Identifiers the search returned; None when the register reported too
            many to list
        records:
          items:
            $ref: '#/components/schemas/InsolvencyRecord'
          type: array
          title: Records
          description: Up to 5 expanded cases
        truncated:
          type: boolean
          title: Truncated
          description: True when more cases exist than are returned
        retrieved_at:
          type: string
          title: Retrieved At
          description: ISO 8601 UTC timestamp of the query
      type: object
      required:
        - screened
        - applicable
        - found
        - truncated
        - retrieved_at
      title: InsolvencyRecordsResult
      description: >-
        Result of the `insolvency_records` source.


        Unlike PepScreenResult and AdverseMediaResult, `screened` CAN be False
        on a 200:

        the register covers the Netherlands only, so for any other `country` the
        source

        is not consulted and the row says so with `applicable: false`. That is a

        different fact from a clean negative and must never be read as one. When

        `applicable` is True, `screened` is always True: every other failure
        raises and

        the router answers 503, so the caller is not charged.


        A negative result (`found: false`) means the register listed no
        insolvency

        proceeding for the KvK number or trade name at query time. Exception
        code 3

        ("too many results") is reported as `found: true, truncated: true,

        match_count: null` with no records: matches exist but the register will
        not

        list them until the query is narrowed (send `kvk_number`).


        Register conditions: no replica is kept and a successful screen is
        cached for at

        most 24 hours (app/config.py::cache_insolvency_ttl), inside the
        six-month

        destruction rule the subscription imposes.
    CreditReportResult:
      properties:
        screened:
          type: boolean
          title: Screened
          description: True when the provider was actually queried
        applicable:
          type: boolean
          title: Applicable
          description: >-
            False when `country` has no registered provider (Italy only today)
            or no credit_report_identifier was supplied -- a different fact from
            a clean negative, and never to be read as one
        risk_score:
          anyOf:
            - type: string
            - type: 'null'
          title: Risk Score
          description: >-
            Normalised verdict: green, yellow, red, or unknown; None when not
            applicable
        risk_band_available:
          type: boolean
          title: Risk Band Available
          description: True when the provider returned an assessment rather than grey/ND
          default: false
        provider:
          anyOf:
            - type: string
            - type: 'null'
          title: Provider
          description: Identifier of the provider queried; None when not applicable
        country:
          type: string
          title: Country
          description: ISO 3166-1 alpha-2 country that was requested
        organization_name:
          anyOf:
            - type: string
            - type: 'null'
          title: Organization Name
          description: Company name as held by the provider
        identifier_type:
          anyOf:
            - type: string
            - type: 'null'
          title: Identifier Type
          description: 'Which identifier resolved the lookup: vat, tax or company_id'
        retrieved_at:
          type: string
          title: Retrieved At
          description: ISO 8601 UTC timestamp of the query
      type: object
      required:
        - screened
        - applicable
        - country
        - retrieved_at
      title: CreditReportResult
      description: >-
        Result of the `credit_report` source, sold on the `credit` deep-check
        tier. `screened` is never False while `applicable` is True.


        Mirrors InsolvencyRecordsResult, not AdverseMediaResult: coverage is a
        single

        country (Italy), so "we do not cover this country" is a 200 with

        `applicable: false` from app/services/credit_report.py, the same pattern
        the

        insolvency register uses for non-NL -- never a raise, because that would
        be a

        paid 503 for a caller who explicitly opted into this tier. A supported
        country

        whose screen fails for any other reason (unset key, vendor outage,
        unparseable

        verdict) still raises CreditReportUnavailable, and the router turns that
        into a

        503 so the payment is never settled.


        A green score is the provider's assessment of the company at query time,
        not a

        guarantee of solvency and not a recommendation to extend credit.
        `risk_score` is

        a normalised value from a closed set (green / yellow / red / unknown),
        not the raw

        vendor string, and is None exactly when `applicable` is False;
        `risk_band_available`

        is False when the provider declined to assess (its documented grey/ND
        answer, e.g.

        a closed company), which is a different fact from a low-risk verdict.
    PepMatch:
      properties:
        caption:
          type: string
          title: Caption
          description: Matched entity display name
        schema_type:
          type: string
          title: Schema Type
          description: FollowTheMoney schema, e.g. Person
        topics:
          items:
            type: string
          type: array
          title: Topics
          description: Risk topics, e.g. role.pep, role.rca
        datasets:
          items:
            type: string
          type: array
          title: Datasets
        score:
          type: number
          maximum: 1
          minimum: 0
          title: Score
          description: Match confidence
        countries:
          items:
            type: string
          type: array
          title: Countries
        birth_date:
          anyOf:
            - type: string
            - type: 'null'
          title: Birth Date
      type: object
      required:
        - caption
        - schema_type
        - topics
        - score
      title: PepMatch
      description: >-
        One OpenSanctions PEP/RCA match, projected to the fields we stand
        behind.
    AdverseMediaArticle:
      properties:
        headline:
          type: string
          title: Headline
          description: Article headline as indexed by the vendor
        source_link:
          type: string
          title: Source Link
          description: URL of the article
        category:
          type: string
          title: Category
          description: dilisense exposure category, e.g. financial_crime
        published_at:
          anyOf:
            - type: string
            - type: 'null'
          title: Published At
          description: ISO 8601 timestamp
        language:
          anyOf:
            - type: string
            - type: 'null'
          title: Language
          description: ISO 639-1 language code
        snippet:
          anyOf:
            - type: string
            - type: 'null'
          title: Snippet
          description: Bounded plain-text excerpt
      type: object
      required:
        - headline
        - source_link
        - category
      title: AdverseMediaArticle
      description: >-
        One adverse-media article, projected to the fields we stand behind.


        Field names follow the dilisense `checkIndividual` article object
        (headline,

        source_link, timestamp, language, body). `snippet` is the body with its
        ``<p>``

        markup stripped and bounded; `category` is the news-exposure bucket
        dilisense

        filed the article under.
    InsolvencyRecord:
      properties:
        publication_id:
          type: string
          title: Publication Id
          description: publicatieKenmerk; the register's identifier for the case
        insolvency_number:
          anyOf:
            - type: string
            - type: 'null'
          title: Insolvency Number
          description: insolventienummer, e.g. F.13/24/123
        court:
          anyOf:
            - type: string
            - type: 'null'
          title: Court
          description: 'behandelendeInstantieCode: the court handling the case'
        subject_type:
          anyOf:
            - type: string
            - type: 'null'
          title: Subject Type
          description: >-
            legal_entity or natural_person, as the register classifies the
            insolvent party
        latest_publication:
          anyOf:
            - $ref: '#/components/schemas/InsolvencyPublication'
            - type: 'null'
      type: object
      required:
        - publication_id
      title: InsolvencyRecord
      description: >-
        One insolvency case from the Centraal Insolventieregister.


        Projected from the getCase document to the fields we stand behind; the
        raw

        document is never echoed. Absent elements are None, not fabricated.
    InsolvencyPublication:
      properties:
        code:
          anyOf:
            - type: string
            - type: 'null'
          title: Code
          description: publicatieSoortCode from the register
        description:
          anyOf:
            - type: string
            - type: 'null'
          title: Description
          description: publicatieOmschrijving from the register
        date:
          anyOf:
            - type: string
            - type: 'null'
          title: Date
          description: publicatieDatum as published (YYYY-MM-DD)
      type: object
      title: InsolvencyPublication
      description: >-
        The most recent publication on an insolvency case, as the register lists
        it.
  securitySchemes:
    APIKeyHeader:
      type: apiKey
      in: header
      name: X-API-Key

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.