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

# Send a beneficial owner's verification

> Issue (or re-issue) the owner's identity-verification link via the same
core the app uses. **This spends a credit** (or bills the customer) on
the same model as KYC/KYB start: `organization` pays now and the check
is settled; `customer` arms payment-pending and pays at the portal.
`deliverEmail: false` returns the link instead of emailing it.

Reusing a link never rotates the owner's token, so previously issued
links keep working. A verified owner returns **409 conflict**.

Requires `verification:write`. Include an `Idempotency-Key` header to
make retries safe.


Issue (or re-issue) the owner's identity-verification link via the same core the
app uses. **This spends a credit** (or bills the customer) on the same model as
[KYC](/api-reference/customers/kyc) / [KYB](/api-reference/entities/kyb) start:

* `payer: organization` (or the record default) — a credit is spent now and the
  check is settled.
* `payer: customer` — the owner is armed payment-pending and pays at the portal.
* `deliverEmail: false` — the link is returned in `verification_link` instead of
  emailed.

Reusing a link never rotates the owner's token, so previously issued links keep
working. A verified owner returns `409 conflict`; an org-paid send with no
credit returns `402 insufficient_credits` (nothing armed or charged). Requires
the `verification:write` scope.


## OpenAPI

````yaml POST /entities/{id}/ubos/{uboId}/kyc
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}/ubos/{uboId}/kyc:
    parameters:
      - in: path
        name: id
        required: true
        schema:
          type: string
        description: Entity identifier (UUID or your `external_id`).
      - in: path
        name: uboId
        required: true
        schema:
          type: string
          format: uuid
        description: The beneficial owner's id (from the add / list responses).
    post:
      tags:
        - Entities
      summary: Send a beneficial owner's verification link
      description: |
        Issue (or re-issue) the owner's identity-verification link via the same
        core the app uses. **This spends a credit** (or bills the customer) on
        the same model as KYC/KYB start: `organization` pays now and the check
        is settled; `customer` arms payment-pending and pays at the portal.
        `deliverEmail: false` returns the link instead of emailing it.

        Reusing a link never rotates the owner's token, so previously issued
        links keep working. A verified owner returns **409 conflict**.

        Requires `verification:write`. Include an `Idempotency-Key` header to
        make retries safe.
      operationId: sendEntityUboKyc
      parameters:
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: false
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SendUboKycRequest'
            example:
              payer: organization
      responses:
        '200':
          description: The owner after arming, plus their verification link.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Ubo'
                  - type: object
                    properties:
                      verification_link:
                        type: string
                        format: uri
                        description: The owner's portal verification link.
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '403':
          $ref: '#/components/responses/ForbiddenScope'
        '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:
    SendUboKycRequest:
      type: object
      additionalProperties: false
      description: >-
        Options for sending a beneficial owner's verification link. All fields
        optional.
      properties:
        payer:
          $ref: '#/components/schemas/Payer'
        email:
          type: string
          format: email
          maxLength: 255
          description: |
            Where to email the link. Defaults to the owner's recorded email;
            required (here or on file) unless `deliverEmail` is false.
        deliverEmail:
          type: boolean
          description: >-
            When false, the link is returned in `verification_link` instead of
            emailed.
    Ubo:
      type: object
      description: >-
        A beneficial owner. Never includes link tokens, applicant ids, or
        payment fields.
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
        holder_type:
          type: string
        role_type:
          oneOf:
            - $ref: '#/components/schemas/UboRoleType'
            - type: 'null'
        role_types:
          type: array
          items:
            $ref: '#/components/schemas/UboRoleType'
        percentage_held:
          type: number
          nullable: true
        kyc_required:
          type: boolean
          description: False for excluded / recorded-only parties that are never checked.
        kyc_status:
          $ref: '#/components/schemas/KycStatus'
        kyc_email:
          type: string
          nullable: true
        linked_customer:
          type: object
          nullable: true
          properties:
            id:
              type: string
              format: uuid
            external_id:
              type: string
              nullable: true
        added_via:
          type: string
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
    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.
    UboRoleType:
      type: string
      description: Typed trust-party / ownership role.
      enum:
        - TRUSTEE
        - CORPORATE_TRUSTEE
        - SETTLOR
        - APPOINTOR
        - GUARDIAN
        - PROTECTOR
        - BENEFICIARY_NAMED
        - BENEFICIARY_CLASS
        - BENEFICIARY_EXCLUDED
        - UNIT_HOLDER
        - MEMBER
        - DIRECTOR
        - SHAREHOLDER
        - OTHER_CONTROLLER
        - OTHER
    KycStatus:
      type: string
      enum:
        - NOT_STARTED
        - PENDING
        - IN_PROGRESS
        - VERIFIED
        - FAILED
        - NOT_REQUIRED
        - AWAITING_RESUBMISSION
    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
  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.
    ForbiddenScope:
      description: API key lacks the required scope.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: forbidden_scope
              message: This API key does not have the required scope. customers:write
              details:
                required_scope: customers:write
    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_…`.

````