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

# Start an entity's KYB

> Start business verification (KYB) for an entity — the same lane flows
the app runs, selected by `method`. **This spends credits** (or bills
the customer) on the emailing lanes.

- `automated` (default) emails the entity's contact a secure link to
  upload the entity document, which you then review ("org-led").
  Charges.
- `contact_led` emails the contact to complete the whole flow. Charges.
  Requires the `kyb_extra_methods` feature — otherwise `403
  feature_disabled`.
- `manual` arms the record for an officer to collect/upload the document
  (company), or manages a trust/partnership by hand. No charge, no
  email. Trust and partnership entities support **only** `manual`.

Payer follows the entity record's billing default unless `payer`
overrides it; the customer-paid lanes arm payment-pending and email the
pay link.

Requires the `verification:write` scope. Include an `Idempotency-Key`
header to make retries safe for 24 hours.


Start business verification (KYB) for an entity — the same lane flows the
app runs, selected by `method`. Unlike ingest, the emailing lanes **spend
credits** (or bill the customer), so this needs the separate
`verification:write` scope.

## Lanes

* **`automated`** (default, "org-led") — emails the entity's contact a
  secure link to upload the entity document, which you then review.
  Charges. Returns the link as `verification_link`.
* **`contact_led`** — emails the contact to complete the whole flow
  themselves. Charges. Requires the `kyb_extra_methods` feature — otherwise
  you get `403 feature_disabled`.
* **`manual`** — arms the record for an officer to collect/upload the
  document (company), or to manage a trust/partnership by hand. No charge,
  no email.

<Note>
  Trust and partnership entities support **only** `manual` — they have no
  emailing lane.
</Note>

## Who pays

`payer` is optional and works exactly as for [KYC](/api-reference/customers/kyc):
omit to honour the entity record's default, or set `payer: customer` to
arm payment-pending and email the pay link. Manual lanes never charge, so
`payer` has no effect there.

## Errors worth handling

* **`402 insufficient_credits`** — no credits for an org-paid emailing
  lane; nothing armed or charged.
* **`403 feature_disabled`** — `contact_led` requested while the feature is
  off for your org.
* **`409 conflict`** — a verification has already been started for this
  entity.
* **`422 validation_failed`** — a precondition is missing (e.g. no contact
  person with an email for an emailing lane).

Include an `Idempotency-Key` header so a retried start is not run twice.


## OpenAPI

````yaml POST /entities/{id}/kyb
openapi: 3.1.0
info:
  title: Instant Compliance API
  version: 1.0.0
  summary: External integration API for Instant Compliance.
  description: |
    The Instant Compliance v1 API lets your systems push customers into
    Instant Compliance and pull their verification / AML status back out.
    Designed for server-to-server use (CRMs, Zapier, internal back-office
    tools).

    **Base URL:** `https://app.instantcompliance.ai/api/v1`

    **Authentication:** Bearer API key — `Authorization: Bearer ic_live_…`
    Issue keys from **Settings → Developers** in your Instant Compliance
    organisation.

    **Scope:** individual customers (`INDIVIDUAL` and `SOLE_TRADER`, KYC)
    live on `/customers`; entity customers (companies, trusts,
    partnerships, SMSFs — KYB) live on `/entities`.
  contact:
    name: Instant Compliance Support
    email: support@instantcompliance.ai
    url: https://instantcompliance.ai
  license:
    name: Proprietary
servers:
  - url: https://app.instantcompliance.ai/api/v1
    description: Production
security:
  - bearerAuth: []
tags:
  - name: Customers
    description: |
      Create, read, and update individual customer records ingested through
      the external API.
  - name: Entities
    description: |
      Create, read, and update entity customer records (companies, trusts,
      partnerships, SMSFs). Entities verify via KYB instead of KYC; the API
      ingests the record and reports status — verification is started by
      your back-office team in-app.
  - name: Designated services
    description: |
      Read-only catalog of the designated-service codes accepted when
      creating customers.
  - name: Groups
    description: |
      Create group workspaces (multi-party deals/matters — e.g. one per
      property for real-estate integrators) and discover the group
      templates available to your organisation. Requires the Groups
      feature to be enabled for your organisation.
paths:
  /entities/{id}/kyb:
    parameters:
      - in: path
        name: id
        required: true
        schema:
          type: string
        description: |
          Entity identifier. Accepts either Instant Compliance's UUID or your
          own `external_id`.
    post:
      tags:
        - Entities
      summary: Start an entity's KYB verification
      description: |
        Start business verification (KYB) for an entity — the same lane flows
        the app runs, selected by `method`. **This spends credits** (or bills
        the customer) on the emailing lanes.

        - `automated` (default) emails the entity's contact a secure link to
          upload the entity document, which you then review ("org-led").
          Charges.
        - `contact_led` emails the contact to complete the whole flow. Charges.
          Requires the `kyb_extra_methods` feature — otherwise `403
          feature_disabled`.
        - `manual` arms the record for an officer to collect/upload the document
          (company), or manages a trust/partnership by hand. No charge, no
          email. Trust and partnership entities support **only** `manual`.

        Payer follows the entity record's billing default unless `payer`
        overrides it; the customer-paid lanes arm payment-pending and email the
        pay link.

        Requires the `verification:write` scope. Include an `Idempotency-Key`
        header to make retries safe for 24 hours.
      operationId: startEntityKyb
      parameters:
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: false
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/StartKybRequest'
            example:
              method: automated
      responses:
        '200':
          description: |
            The entity record after arming, plus `verification_link` when a
            portal link was generated (the emailing lanes).
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Entity'
                  - type: object
                    properties:
                      verification_link:
                        type: string
                        format: uri
                        description: Shareable portal link (emailing lanes only).
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '403':
          $ref: '#/components/responses/FeatureDisabledOrScope'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '422':
          $ref: '#/components/responses/ValidationFailed'
        '429':
          $ref: '#/components/responses/RateLimited'
      security:
        - bearerAuth: []
components:
  parameters:
    IdempotencyKey:
      in: header
      name: Idempotency-Key
      required: false
      schema:
        type: string
        maxLength: 255
      description: |
        Caller-supplied unique key for safe retries. Repeat the same key
        within 24 hours and we replay the original response instead of
        repeating the side effect. Reusing the key with a *different*
        request body returns **409 idempotency_conflict**.
  schemas:
    StartKybRequest:
      type: object
      additionalProperties: false
      description: Options for starting an entity's KYB. All fields optional.
      properties:
        method:
          type: string
          enum:
            - automated
            - contact_led
            - manual
          default: automated
          description: |
            `automated` (org-led) and `contact_led` email the contact and
            charge; `manual` arms for officer upload / trust-partnership
            handling and does not charge. Trust and partnership entities support
            only `manual`.
        payer:
          $ref: '#/components/schemas/Payer'
        customMessage:
          type: string
          maxLength: 2000
          description: Optional note included in the verification email.
        eddCheckTypes:
          type: array
          items:
            $ref: '#/components/schemas/EddCheckType'
          description: Optional enhanced due-diligence add-ons (emailing lanes).
    Entity:
      type: object
      required:
        - id
        - type
        - name
        - origin
        - kyb_status
        - aml
        - added_via
        - created_at
        - updated_at
      properties:
        id:
          type: string
          format: uuid
          description: Instant Compliance customer UUID (entities are customers too).
        external_id:
          type: string
          nullable: true
        type:
          $ref: '#/components/schemas/EntityType'
        name:
          type: string
          description: The entity's legal name.
        origin:
          $ref: '#/components/schemas/EntityOrigin'
        abn:
          type: string
          nullable: true
        acn:
          type: string
          nullable: true
        country_of_formation:
          type: string
          nullable: true
          description: |
            ISO 3166-1 alpha-3. `AUS` for Australian entities; the country
            of formation for international entities.
        registration_number:
          type: string
          nullable: true
          description: Registry number recorded for international entities.
        kyb_status:
          $ref: '#/components/schemas/KycStatus'
        kyb_started_at:
          type: string
          format: date-time
          nullable: true
        kyb_completed_at:
          type: string
          format: date-time
          nullable: true
        contact:
          $ref: '#/components/schemas/EntityContact'
        aml:
          $ref: '#/components/schemas/AmlBlock'
        added_via:
          $ref: '#/components/schemas/AddedVia'
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      example:
        id: 7c9e6679-7425-40de-944b-e07fc1f90ae7
        external_id: crm-ent-311
        type: COMPANY
        name: Acme Holdings Pty Ltd
        origin: AUSTRALIAN
        abn: '12345678901'
        acn: '123456789'
        country_of_formation: AUS
        registration_number: null
        kyb_status: IN_PROGRESS
        kyb_started_at: '2026-06-23T01:00:00Z'
        kyb_completed_at: null
        contact:
          id: 550e8400-e29b-41d4-a716-446655440000
          external_id: crm-7741
          full_name: Jane Doe
          email: jane@example.com
          kyc_status: PENDING
          kyc_required: true
        aml:
          status: CLEAR
          screened_at: '2026-06-23T01:12:00Z'
          last_reviewed_at: null
          flags:
            pep: false
            sanctions: false
            adverse_media: false
            terrorism: false
        added_via: INTEGRATION
        created_at: '2026-06-22T22:14:00Z'
        updated_at: '2026-06-23T01:12:05Z'
    Payer:
      type: string
      enum:
        - organization
        - customer
      description: |
        Who pays for the check. Omit to honour the customer record's own
        billing default. `customer` arms the check payment-pending and emails a
        pay link — the customer pays by card at the portal.
    EddCheckType:
      type: string
      enum:
        - SOURCE_OF_FUNDS
        - SOURCE_OF_WEALTH
        - BIOMETRIC_VERIFICATION
      description: An enhanced due-diligence add-on check.
    EntityType:
      type: string
      enum:
        - COMPANY
        - TRUST
        - PARTNERSHIP
        - SMSF
        - OTHER
      description: |
        Entity customer types accepted by `/entities`. `SMSF` is treated
        as a type of trust and `OTHER` as a company for verification
        purposes, but the type you post round-trips back unchanged.
        Immutable after creation.
    EntityOrigin:
      type: string
      enum:
        - AUSTRALIAN
        - INTERNATIONAL
      description: |
        Where the entity is formed. `AUSTRALIAN` (the default) uses
        ABN/ACN identifiers; `INTERNATIONAL` uses `countryOfFormation` +
        `registrationNumber`. Immutable after creation.
    KycStatus:
      type: string
      enum:
        - NOT_STARTED
        - PENDING
        - IN_PROGRESS
        - VERIFIED
        - FAILED
        - NOT_REQUIRED
        - AWAITING_RESUBMISSION
    EntityContact:
      type: object
      nullable: true
      required:
        - id
        - full_name
        - kyc_status
        - kyc_required
      description: The entity's current contact person, or `null` when none is set.
      properties:
        id:
          type: string
          format: uuid
        external_id:
          type: string
          nullable: true
        full_name:
          type: string
        email:
          type: string
          format: email
          nullable: true
        kyc_status:
          $ref: '#/components/schemas/KycStatus'
        kyc_required:
          type: boolean
          description: >-
            Whether the contact's own KYC is intended to run with the entity's
            KYB.
    AmlBlock:
      type: object
      required:
        - status
        - flags
      properties:
        status:
          $ref: '#/components/schemas/AmlStatus'
        screened_at:
          type: string
          format: date-time
          nullable: true
        last_reviewed_at:
          type: string
          format: date-time
          nullable: true
        flags:
          type: object
          required:
            - pep
            - sanctions
            - adverse_media
            - terrorism
          properties:
            pep:
              type: boolean
            sanctions:
              type: boolean
            adverse_media:
              type: boolean
            terrorism:
              type: boolean
    AddedVia:
      type: string
      description: How the record entered Instant Compliance.
      enum:
        - ADMIN_MANUAL
        - AI_EXTRACTED
        - CONTACT_PORTAL
        - BULK_IMPORT
        - INTEGRATION
        - SYSTEM
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              enum:
                - unauthorized
                - forbidden_scope
                - not_found
                - validation_failed
                - conflict
                - insufficient_credits
                - rate_limited
                - idempotency_conflict
                - feature_disabled
                - internal
            message:
              type: string
            details:
              type: object
              additionalProperties: true
    AmlStatus:
      type: string
      enum:
        - NOT_SCREENED
        - IN_PROGRESS
        - CLEAR
        - NEEDS_REVIEW
        - RESOLVED
  responses:
    Unauthorized:
      description: Missing, invalid, expired, or revoked API key.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: unauthorized
              message: Invalid or revoked API key.
    InsufficientCredits:
      description: |
        The organisation does not hold enough credits to start this
        verification. No check is armed and nothing is charged. Top up and
        retry, or start the check as a customer-paid one.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: insufficient_credits
              message: Insufficient credits to start this verification.
    FeatureDisabledOrScope:
      description: |
        API key lacks the required scope, or the Groups feature is not
        enabled for the organisation.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: feature_disabled
              message: >-
                The Groups feature is not enabled for this organisation. Contact
                support to enable it.
              details:
                feature: Groups
    NotFound:
      description: No customer matching the supplied id in this organisation.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: not_found
              message: Customer not found.
    Conflict:
      description: |
        The record is not in a state the request can act on — most often a
        verification has already been started for it.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: conflict
              message: KYB verification has already been started for this customer.
    ValidationFailed:
      description: Request payload failed schema validation.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: validation_failed
              message: Invalid customer payload.
              details:
                issues:
                  email:
                    - Must be a valid email address.
    RateLimited:
      description: Burst or daily rate limit exceeded for this API key.
      headers:
        Retry-After:
          schema:
            type: integer
          description: Seconds to wait before retrying.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: rate_limited
              message: Rate limit exceeded. Slow down and retry shortly.
              details:
                limit: 60
                window_seconds: 60
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API Key
      description: |
        Bearer API key issued from **Settings → Developers** in your
        Instant Compliance organisation. Format: `ic_live_…`.

````