openapi: 3.0.1
info:
  title: TrustFlow BFF Web API
  description: |
    Backend for Frontend (BFF) API for TrustFlow verification services — identity, death status, death details, personal details, bank account and sanctions screening, plus bulk (batch) identity verification and risk-assessment reads.

    ## Getting started for integrators

    ### 1. Access & authentication
    This API is fronted by the **Sanlam Layer7 API Gateway**. You do **not** call the raw AWS origin URLs directly — call the gateway host issued to you during onboarding and authenticate with **OAuth2 (client credentials)**:

    1. Request a client `id` / `secret` (an *Application* linked to this API) from the API Management team — **apim@sanlam.co.za**.
    2. Exchange them for a bearer token:
    ```
    curl -X POST {gatewayUrl}/auth/oauth/v2/token \
      --data-urlencode client_id={clientId} \
      --data-urlencode client_secret={clientSecret} \
      --data-urlencode grant_type=client_credentials
    ```
    3. Send the token on every request: `Authorization: Bearer {access_token}`.

    Gateway rejections surface as **401** (missing/invalid token) or **403** (insufficient permissions) before the request reaches the BFF.

    ### 2. Asynchronous verification flow
    Single verifications are **asynchronous**:

    1. `POST` a verification (e.g. `/v1/verifications/identity`) → **202 Accepted** with a `correlationId` and a `statusUrl`.
    2. Poll `GET /v1/verifications/status/{correlationId}` until `status` is `COMPLETED`, then read `outcome` (`SUCCEEDED` / `HARD_FAIL` / `SOFT_FAIL` / `SYSTEM_OUTAGE`) and `result`.

    Bulk identity verification is also asynchronous but returns results in pages: submit via `POST /v1/verifications/bulk/identity` (inline IDs, or a pre-uploaded CSV requested from `POST /v1/verifications/bulk/upload-url`), then poll `GET /v1/verifications/bulk/{correlationId}`.

    ### 3. Environments
    `dev` (development), `ppe` (pre-production) and `prd` (production).

    The **Servers** list in this reference shows the **direct AWS origin URLs**. They exist so the Sanlam Fintech team can exercise the service internally, and so tooling has a concrete base URL to render — they are **not** your integration endpoint and are not a supported integration path. Your base URL is the **environment-specific Layer7 gateway host** issued to you at onboarding, and every request must carry a bearer token as described above.

    Paths in this document are relative to whichever base URL you use, so the operation definitions are correct either way. The `statusUrl` returned on a `202` is likewise relative — resolve it against your gateway base URL, not against an origin URL.

    ### 4. Bulk verification limits and timing

    Bulk identity verification is passed through to the Department of Home Affairs' HANIS bulk service, whose operational limits apply to you directly:

    | Limit | Value |
    | --- | --- |
    | Request files per day | **9** across all callers of this environment |
    | ID numbers per file | 200 000 |
    | Processing window | **18:00–06:00 SAST** |
    | Results retained | **72 hours** after completion |

    **Files are not processed on submission.** DHA processes bulk files only between 18:00 and 06:00 SAST, so a batch submitted during the working day completes that evening rather than immediately — typically minutes after the window opens. Submitting earlier in the day does not make results arrive earlier.

    The daily cap is shared across every caller of an environment, not per consumer. Once it is reached, further submissions are rejected with **429** until midnight SAST; batches already submitted are unaffected.

    **Collect within 72 hours.** DHA deletes results 72 hours after completion, and they cannot be regenerated without submitting — and being charged for — the batch again.

    Re-submitting the same `requestReference` never creates a second batch: the original `correlationId` is returned with `status: DUPLICATE`. Submitting the same ID numbers under a *different* reference does create a second batch, and is charged again.

    ### Support
    API Management / onboarding: **apim@sanlam.co.za** · API owner: Sanlam Fintech – DigiSure PAS Pod (**digisure-pas-pod@sanlam.co.za**).
  contact:
    name: Sanlam Fintech - DigiSure PAS Pod
    email: digisure-pas-pod@sanlam.co.za
  version: 1.0.0
servers:
- url: https://4czlv0qxe2.execute-api.eu-west-1.amazonaws.com/dev
  description: "Development — direct AWS origin, internal testing only"
- url: https://n7074w9gp1.execute-api.eu-west-1.amazonaws.com/ppe
  description: "Pre-Production — direct AWS origin, internal testing only"
- url: https://1s6y0pplpk.execute-api.eu-west-1.amazonaws.com/prd
  description: "Production — direct AWS origin, internal testing only"
security:
- Layer7OAuth2: []
tags:
- name: Verification
  description: Operations related to identity and data verification
- name: Bulk Verification
  description: Operations related to batch/bulk verification processing
paths:
  /v1/verifications/bulk/identity:
    post:
      tags:
      - Bulk Verification
      summary: Bulk verify identities via DHA batch processing
      description: "Submits a batch of up to 200,000 South African ID numbers for\
        \ verification via the DHA batch processing system. Results are processed\
        \ asynchronously."
      operationId: bulkVerifyIdentity
      requestBody:
        description: Bulk identity verification request details
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BulkVerifyIdentityRequestDto'
        required: true
      responses:
        "202":
          description: Bulk verification request accepted
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BulkVerificationResponseDto'
        "400":
          description: Invalid request data
        "500":
          description: Internal server error
  /v1/verifications/bulk/{correlationId}:
    get:
      tags:
      - Bulk Verification
      summary: Get bulk verification results
      description: "Retrieves the status and a page of results for a DHA bulk verification\
        \ batch, identified by the correlation ID returned when the batch was submitted."
      operationId: getBulkResults
      parameters:
      - name: pageSize
        in: query
        description: Maximum number of records to return on this page
        schema:
          type: integer
          format: int32
        example: 500
      - name: pageToken
        in: query
        description: Opaque cursor from a previous response's nextPageToken
        schema:
          type: string
      - name: idNumber
        in: query
        description: Filter results to a single ID number within the batch
        schema:
          type: string
        example: 8001015009088
      - name: correlationId
        in: path
        description: Batch correlation ID
        required: true
        schema:
          type: string
          format: uuid
        example: 550e8400-e29b-41d4-a716-446655440000
      responses:
        "200":
          description: Batch status and results page retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BulkResultsResponseDto'
        "400":
          description: Invalid request parameters
        "404":
          description: Batch not found
        "500":
          description: Internal server error
  /v1/verifications/risk-assessment/evaluation/{evaluationId}:
    get:
      tags:
      - Verification
      summary: Get a risk assessment evaluation by id
      description: Proxies core's canonical evaluation route; the evaluation id equals
        the submitted command id (submit-and-poll contract). 404 while still processing
      operationId: getRiskAssessmentEvaluation
      parameters:
      - name: evaluationId
        in: path
        description: evaluationId path parameter
        required: true
        schema:
          type: string
          format: uuid
        example: 550e8400-e29b-41d4-a716-446655440000
      responses:
        "200":
          description: Get a risk assessment evaluation by id retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VerificationStatusResponseDto'
        "400":
          description: Invalid evaluationId format
        "404":
          description: Evaluation not found (it may still be processing)
        "500":
          description: Internal server error
  /v1/verifications/risk-assessment/{clientId}:
    get:
      tags:
      - Verification
      summary: Get latest risk assessment for a client
      description: "Proxies core's canonical risk-assessment record route: latest\
        \ DRA record (current risk, recommended action, override state) for the client"
      operationId: getRiskAssessmentRecord
      parameters:
      - name: clientId
        in: path
        description: clientId path parameter
        required: true
        schema:
          type: string
          format: uuid
        example: 550e8400-e29b-41d4-a716-446655440000
      responses:
        "200":
          description: Get latest risk assessment for a client retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VerificationStatusResponseDto'
        "400":
          description: Invalid clientId format
        "404":
          description: No DRA record found for client
        "500":
          description: Internal server error
  /v1/verifications/status/{correlationId}:
    get:
      tags:
      - Verification
      summary: Get verification status
      description: Retrieves the current status of a verification request by correlation
        ID
      operationId: getVerificationStatus
      parameters:
      - name: correlationId
        in: path
        description: Correlation ID of the verification request
        required: true
        schema:
          type: string
          format: uuid
        example: 550e8400-e29b-41d4-a716-446655440000
      responses:
        "200":
          description: Verification status retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VerificationStatusResponseDto'
        "400":
          description: Invalid correlation ID format
        "401":
          description: Caller could not be identified
        "404":
          description: "Verification request not found, or not submitted by the calling\
            \ tenant. The two are deliberately indistinguishable."
        "500":
          description: Internal server error
  /v1/verifications/bulk:
    get:
      tags:
      - Bulk Verification
      summary: List this tenant's bulk verification submissions
      description: "Returns the calling tenant's bulk submissions, newest first. Scoped\
        \ to the caller's own tenant; there is no parameter to widen it. Use the correlationId\
        \ from a row to fetch that batch's results."
      operationId: handleRequest
      responses:
        default:
          description: default response
          content:
            '*/*': {}
  /v1/verifications/bulk/upload-url:
    post:
      tags:
      - Bulk Verification
      summary: Request a presigned URL to upload a bulk verification CSV
      description: "Returns a presigned S3 PUT URL and an upload ID. Upload the CSV\
        \ of ID numbers to the URL, then submit the batch via POST /v1/verifications/bulk/identity\
        \ with the upload ID."
      operationId: requestBulkUploadUrl
      responses:
        "200":
          description: Presigned upload URL issued
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BulkUploadUrlResponseDto'
        "500":
          description: Internal server error
  /v1/verifications/sanctions:
    post:
      tags:
      - Verification
      summary: Screen parties against sanctions lists
      description: Screens provided parties against international and local sanctions
        lists via ORMS
      operationId: screenSanctions
      requestBody:
        description: Sanctions screening request details
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ScreenSanctionsRequestDto'
        required: true
      responses:
        "202":
          description: Sanctions screening request accepted
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VerificationResponseDto'
        "400":
          description: Invalid request data
        "500":
          description: Internal server error
  /v1/verifications/bank-account:
    post:
      tags:
      - Verification
      summary: Verify bank account via QLink
      description: Verifies that a bank account is valid and belongs to the specified
        ID holder
      operationId: verifyBankAccount
      requestBody:
        description: Bank account verification request details
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/VerifyBankAccountRequestDto'
        required: true
      responses:
        "202":
          description: Bank account verification request accepted
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VerificationResponseDto'
        "400":
          description: Invalid request data
        "500":
          description: Internal server error
  /v1/verifications/death-details:
    post:
      tags:
      - Verification
      summary: Verify death details via Astute (VOPD Type 2)
      description: "Returns the registered death detail (place and cause of death,\
        \ under-investigation status) for a deceased subject"
      operationId: verifyDeathDetails
      requestBody:
        description: Verify death details via Astute (VOPD Type 2) request details
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/VerifyDeathDetailsRequestDto'
        required: true
      responses:
        "202":
          description: Death details verification request accepted
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VerificationResponseDto'
        "400":
          description: Invalid request data
        "500":
          description: Internal server error
  /v1/verifications/death-status:
    post:
      tags:
      - Verification
      summary: Verify death status via DHA
      description: Verifies whether a South African ID holder is deceased according
        to DHA records
      operationId: verifyDeathStatus
      requestBody:
        description: Death status verification request details
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/VerifyDeathStatusRequestDto'
        required: true
      responses:
        "202":
          description: Death status verification request accepted
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VerificationResponseDto'
        "400":
          description: Invalid request data
        "500":
          description: Internal server error
  /v1/verifications/identity:
    post:
      tags:
      - Verification
      summary: Verify identity via DHA
      description: Verifies that a South African ID number is valid and exists in
        DHA records
      operationId: verifyIdentity
      requestBody:
        description: Identity verification request details
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/VerifyIdentityRequestDto'
        required: true
      responses:
        "202":
          description: Identity verification request accepted
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VerificationResponseDto'
        "400":
          description: Invalid request data
        "500":
          description: Internal server error
  /v1/verifications/personal-details:
    post:
      tags:
      - Verification
      summary: Verify personal details via Astute (VOPD)
      description: Verifies a subject's personal details against the VOPD record
      operationId: verifyPersonalDetails
      requestBody:
        description: Verify personal details via Astute (VOPD) request details
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/VerifyPersonalDetailsRequestDto'
        required: true
      responses:
        "202":
          description: Personal details verification request accepted
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VerificationResponseDto'
        "400":
          description: Invalid request data
        "500":
          description: Internal server error
components:
  schemas:
    BulkVerificationResponseDto:
      type: object
      properties:
        correlationId:
          type: string
          description: Correlation ID for tracking the bulk verification request
          format: uuid
          example: 550e8400-e29b-41d4-a716-446655440000
        batchRequestId:
          type: string
          description: DHA batch request ID for tracking with DHA
          example: b2210bd4-e9be-4e16-89b1-ca517bb10255
        idCount:
          type: integer
          description: Number of ID numbers submitted in the batch
          format: int32
          example: 50000
        status:
          type: string
          description: "Status of this REQUEST, not of the batch. `SUBMITTED` means\
            \ a new batch was created. `DUPLICATE` means this `requestReference` was\
            \ already used and the original `correlationId` is being returned — nothing\
            \ was resubmitted. In both cases the authoritative state of the batch\
            \ comes from `GET /v1/verifications/bulk/{correlationId}`, which may report\
            \ FAILED."
          example: SUBMITTED
          enum:
          - SUBMITTED
          - DUPLICATE
        estimatedAvailableAfter:
          type: string
          description: "Earliest time results could exist, ISO-8601. DHA processes\
            \ bulk files only between 18:00 and 06:00 SAST, so a batch submitted during\
            \ the working day completes that evening rather than immediately. Polling\
            \ before this timestamp cannot return anything — the batch is queued,\
            \ not being worked on."
          example: 2026-08-28T16:00:00Z
        pollingInterval:
          type: string
          description: Recommended interval for polling AFTER `estimatedAvailableAfter`
            has passed. Polling before then is pointless regardless of this value.
          example: 5 minutes
      description: Bulk verification request acceptance response
    BillingGroupsDto:
      type: object
      properties:
        names:
          type: boolean
          description: "Include names (first, middle, last)"
          default: true
        gender:
          type: boolean
          description: Include gender
          default: true
        birthDate:
          type: boolean
          description: Include birth date
          default: true
        birthCountry:
          type: boolean
          description: Include birth country
          default: true
        saCitizenStatus:
          type: boolean
          description: Include SA citizenship status
          default: true
        nationality:
          type: boolean
          description: Include nationality
          default: true
        idDocumentInfo:
          type: boolean
          description: Include ID document information
          default: true
        maritalStatus:
          type: boolean
          description: Include marital status
          default: true
        deathStatus:
          type: boolean
          description: Include death status
          default: true
      description: Selection of data fields to retrieve from DHA (each field incurs
        a cost)
    BulkVerifyIdentityRequestDto:
      type: object
      properties:
        idNumbers:
          type: array
          description: "List of South African ID numbers to verify (max 200,000).\
            \ Provide this or uploadId."
          items:
            type: string
            example: "8001015009088"
        uploadId:
          type: string
          description: Upload ID of a previously uploaded CSV of ID numbers. Provide
            this or idNumbers.
          example: 550e8400-e29b-41d4-a716-446655440000
        requestReference:
          type: string
          description: Optional reference for tracking purposes
          example: BATCH-REF-12345
        billingGroups:
          $ref: '#/components/schemas/BillingGroupsDto'
        metadata:
          type: object
          additionalProperties:
            type: string
            description: Optional metadata as key-value pairs
          description: Optional metadata as key-value pairs
      description: Bulk identity verification request for DHA batch processing
    BulkResultRecord:
      type: object
      properties:
        idNumber:
          type: string
        success:
          type: boolean
        errorCode:
          type: integer
          format: int32
        errorDescription:
          type: string
        firstName:
          type: string
        surname:
          type: string
        gender:
          type: string
        dateOfBirth:
          type: string
        birthCountryCode:
          type: string
        saCitizenStatus:
          type: string
        nationality:
          type: string
        idCardIssued:
          type: boolean
        idCardIssueDate:
          type: string
        idBookIssued:
          type: boolean
        idBookIssueDate:
          type: string
        idBlocked:
          type: boolean
        maritalStatus:
          type: string
        maidenName:
          type: string
        marriageDate:
          type: string
        divorceDate:
          type: string
        deceased:
          type: boolean
        dateOfDeath:
          type: string
        deathPlace:
          type: string
        causeOfDeath:
          type: string
      description: The verification records on this page
    BulkResultsResponseDto:
      type: object
      properties:
        correlationId:
          type: string
          description: Correlation ID returned when the batch was submitted
          example: 550e8400-e29b-41d4-a716-446655440000
        requestId:
          type: string
          description: DHA batch request ID (available once DHA has acknowledged the
            upload)
          example: b2210bd4-e9be-4e16-89b1-ca517bb10255
        status:
          type: string
          description: Current status of the batch job
          example: COMPLETE
          enum:
          - PENDING
          - COMPLETE
          - FAILED
        idCount:
          type: integer
          description: Total number of ID numbers submitted in the batch
          format: int32
          example: 50000
        createdAt:
          type: string
          description: Timestamp the batch was created (ISO-8601)
        completedAt:
          type: string
          description: "Timestamp the batch completed (ISO-8601), if complete"
        resultCount:
          type: integer
          description: Number of records on this page
          format: int32
          example: 500
        records:
          type: array
          description: The verification records on this page
          items:
            $ref: '#/components/schemas/BulkResultRecord'
        nextPageToken:
          type: string
          description: Opaque cursor for the next page; null when there are no further
            pages
          example: OTcwMTAxNDU2Nzg5MA
      description: A page of DHA bulk verification results with batch status
    VerificationStatusResponseDto:
      type: object
      properties:
        correlationId:
          type: string
          description: Correlation ID of the verification request
          format: uuid
          example: 550e8400-e29b-41d4-a716-446655440000
        status:
          type: string
          description: "Lifecycle state of the verification request — whether it has\
            \ finished, not whether it passed. A failed verification still reports\
            \ COMPLETED; read `outcome` for the answer."
          example: COMPLETED
          enum:
          - NOT_FOUND
          - PENDING
          - COMPLETED
          - TEMPORARILY_UNAVAILABLE
          - FAILED
        outcome:
          type: string
          description: "Whether the verification passed. SUCCEEDED means verified;\
            \ HARD_FAIL means it did not and retrying will not change that; SOFT_FAIL\
            \ means not cleared (e.g. the subject is deceased, or a sanctions screening\
            \ awaits an analyst decision); SYSTEM_OUTAGE means we could not perform\
            \ the check and the request may be retried. Absent on verifications recorded\
            \ before this field was introduced."
          example: SUCCEEDED
          enum:
          - SUCCEEDED
          - HARD_FAIL
          - SOFT_FAIL
          - SYSTEM_OUTAGE
        message:
          type: string
          description: "Human-readable text derived from `status` alone — not a failure\
            \ reason. A hard-failed verification still reads \"Verification completed\
            \ successfully\", so do not branch on this field or surface it to an end\
            \ user. Read `reason` for why a verification did not pass."
          example: Verification completed successfully
        reason:
          type: string
          description: "Why the verification came out the way it did, as a code from\
            \ a published, provider-agnostic set. Null on a clean success, and null\
            \ on verifications recorded before this field was introduced. `outcome`\
            \ tells you whether to proceed; this tells you which of several soft fails\
            \ you got, which is what a business rule usually needs. PROVIDER_ERROR\
            \ means the failure was on our side rather than the subject's — treat\
            \ it as \"could not verify\", not as a statement about the person. Values\
            \ are stable and safe to branch on; the free text a provider gave us is\
            \ deliberately not exposed."
          example: ID_MARKED_FOR_DELETION
          enum:
          - ID_NOT_FOUND
          - INVALID_ID
          - INVALID_NPR_ID
          - ID_MARKED_FOR_DELETION
          - DECEASED
          - ID_BLOCKED
          - SERVICE_UNAVAILABLE
          - PROVIDER_ERROR
          - NAME_MISMATCH
          - ID_NUMBER_MISMATCH
          - ACCOUNT_NOT_FOUND
          - ACCOUNT_CLOSED
          - ACCOUNT_TYPE_MISMATCH
          - ACCOUNT_TOO_NEW
          - ACCOUNT_DOES_NOT_ACCEPT_DEBITS
          - ACCOUNT_DOES_NOT_ACCEPT_CREDITS
          - BRANCH_DOES_NOT_EXIST
          - BANK_NOT_SUPPORTED
          - SANCTIONS_REVIEW_PENDING
        result:
          type: object
          description: "Provider result detail, present only for providers that return\
            \ one. Identity (DHA) and bank-account (QLink) verifications return null\
            \ here — the outcome is the whole answer. Sent as an explicit null rather\
            \ than omitted."
        errorDetails:
          type: array
          description: "Why the request itself could not be processed. Populated only\
            \ when `status` is FAILED; null otherwise. This describes a failure to\
            \ run the verification, not a verification that returned a negative answer."
          items:
            type: string
            description: "Why the request itself could not be processed. Populated\
              \ only when `status` is FAILED; null otherwise. This describes a failure\
              \ to run the verification, not a verification that returned a negative\
              \ answer."
      description: Verification status response
    BulkUploadUrlResponseDto:
      type: object
      properties:
        uploadId:
          type: string
          description: Upload ID to reference when submitting the batch
          example: 550e8400-e29b-41d4-a716-446655440000
        uploadUrl:
          type: string
          description: Presigned S3 PUT URL; upload the CSV here with Content-Type
            text/csv
        expiresInSeconds:
          type: integer
          description: Seconds until the presigned URL expires
          format: int64
          example: 900
      description: Presigned S3 URL for uploading a bulk verification CSV
    VerificationResponseDto:
      type: object
      properties:
        correlationId:
          type: string
          description: Correlation ID for tracking the verification request
          format: uuid
          example: 550e8400-e29b-41d4-a716-446655440000
        message:
          type: string
          description: Human-readable message about the request status
          example: Identity verification request accepted
        statusUrl:
          type: string
          description: URL to poll for verification status
          example: /v1/verifications/status/550e8400-e29b-41d4-a716-446655440000
      description: Verification request acceptance response
    AddressDto:
      type: object
      properties:
        addressType:
          type: string
          description: Type of address
          example: RESIDENTIAL
          enum:
          - RESIDENTIAL
          - POSTAL
          - BUSINESS
        line1:
          type: string
          description: Address line 1
          example: 123 Main Street
        line2:
          type: string
          description: Address line 2
          example: Apartment 4B
        city:
          type: string
          description: City
          example: Cape Town
        province:
          type: string
          description: Province/State
          example: Western Cape
        postalCode:
          type: string
          description: Postal code
          example: "8001"
        country:
          type: string
          description: Country (ISO 3166-1 alpha-2)
          example: ZA
      description: Address associated with a party
    PartyDto:
      type: object
      properties:
        partyType:
          type: string
          description: Type of party
          example: MAIN_LIFE
          enum:
          - MAIN_LIFE
          - BENEFICIARY
          - POLICYHOLDER
        firstName:
          type: string
          description: First name of the party
          example: John
        lastName:
          type: string
          description: Last name of the party
          example: Doe
        idNumber:
          type: string
          description: South African ID number (13 digits)
          example: "8001015009088"
        dateOfBirth:
          type: string
          description: Date of birth
          format: date
          example: 1980-01-01
        nationality:
          type: string
          description: Nationality (ISO 3166-1 alpha-2)
          example: ZA
        countryOfResidence:
          type: string
          description: Country of residence (ISO 3166-1 alpha-2)
          example: ZA
      description: Party to be screened for sanctions
    ProductDto:
      type: object
      properties:
        productCode:
          type: string
          description: Product code
          example: LIFE001
        productName:
          type: string
          description: Product name
          example: Life Cover Plus
        premiumAmount:
          type: number
          description: Premium amount
          example: 1500.0
        currency:
          type: string
          description: Currency (ISO 4217)
          example: ZAR
      description: Product context for the sanctions screening
    ScreenSanctionsRequestDto:
      required:
      - parties
      type: object
      properties:
        parties:
          type: array
          description: List of parties to screen
          items:
            $ref: '#/components/schemas/PartyDto'
        addresses:
          type: array
          description: Optional list of addresses associated with the parties
          items:
            $ref: '#/components/schemas/AddressDto'
        product:
          $ref: '#/components/schemas/ProductDto'
        requestReference:
          type: string
          description: Optional reference for tracking purposes
          example: REF-12345
        metadata:
          type: object
          additionalProperties:
            type: string
            description: Optional metadata as key-value pairs
          description: Optional metadata as key-value pairs
      description: Sanctions screening request
    VerifyBankAccountRequestDto:
      required:
      - accountNumber
      - accountType
      - bankName
      - branchCode
      - idNumber
      type: object
      properties:
        idNumber:
          type: string
          description: South African ID number (13 digits)
          example: "8001015009088"
        accountNumber:
          type: string
          description: Bank account number
          example: "1234567890"
        branchCode:
          type: string
          description: Bank branch code (6 digits)
          example: "250655"
        accountType:
          type: string
          description: Type of bank account
          example: CURRENT
          enum:
          - CURRENT
          - SAVINGS
          - TRANSMISSION
        bankName:
          type: string
          description: "Bank name, as required by the QLink verification"
          example: ABSA
        surname:
          type: string
          description: "Account holder surname (optional, improves the QLink match)"
          example: Doe
        requestReference:
          type: string
          description: Optional reference for tracking purposes
          example: REF-12345
        metadata:
          type: object
          additionalProperties:
            type: string
            description: Optional metadata as key-value pairs
          description: Optional metadata as key-value pairs
      description: Bank account verification request
    VerifyDeathDetailsRequestDto:
      required:
      - forename
      - idNumber
      - surname
      type: object
      properties:
        idNumber:
          type: string
          description: South African ID number (13 digits)
          example: "8001015009088"
        surname:
          type: string
          description: "Subject's surname, matched against the VOPD record"
          example: Doe
        forename:
          type: string
          description: Subject's first name
          example: John
        dateOfBirth:
          type: string
          description: Subject's date of birth (ISO-8601)
          format: date
          example: 1980-01-01
        requestReference:
          type: string
          description: Optional reference for tracking purposes
          example: REF-12345
        metadata:
          type: object
          additionalProperties:
            type: string
            description: Optional metadata echoed onto the verification outcome
          description: Optional metadata echoed onto the verification outcome
      description: "Death details verification request (VOPD Type 2: place/cause of\
        \ death)"
    VerifyDeathStatusRequestDto:
      required:
      - idNumber
      type: object
      properties:
        idNumber:
          type: string
          description: South African ID number (13 digits)
          example: "8001015009088"
        requestReference:
          type: string
          description: Optional reference for tracking purposes
          example: REF-12345
        metadata:
          type: object
          additionalProperties:
            type: string
            description: Optional metadata as key-value pairs
          description: Optional metadata as key-value pairs
      description: Death status verification request
    VerifyIdentityRequestDto:
      required:
      - idNumber
      type: object
      properties:
        idNumber:
          type: string
          description: South African ID number (13 digits)
          example: "8001015009088"
        requestReference:
          type: string
          description: Optional reference for tracking purposes
          example: REF-12345
        metadata:
          type: object
          additionalProperties:
            type: string
            description: Optional metadata as key-value pairs
          description: Optional metadata as key-value pairs
      description: Identity verification request
    VerifyPersonalDetailsRequestDto:
      required:
      - forename
      - idNumber
      - surname
      type: object
      properties:
        idNumber:
          type: string
          description: South African ID number (13 digits)
          example: "8001015009088"
        surname:
          type: string
          description: "Subject's surname, matched against the VOPD record"
          example: Doe
        forename:
          type: string
          description: Subject's first name
          example: John
        dateOfBirth:
          type: string
          description: Subject's date of birth (ISO-8601)
          format: date
          example: 1980-01-01
        requestReference:
          type: string
          description: Optional reference for tracking purposes
          example: REF-12345
        metadata:
          type: object
          additionalProperties:
            type: string
            description: Optional metadata echoed onto the verification outcome
          description: Optional metadata echoed onto the verification outcome
      description: Personal details verification request (VOPD Type 1)
  securitySchemes:
    Layer7OAuth2:
      type: oauth2
      description: |-
        OAuth2 client-credentials via the Sanlam Layer7 API Gateway. Request a client id/secret from the API Management team (apim@sanlam.co.za), exchange them at the token endpoint, and send the resulting token as `Authorization: Bearer <token>`.

        **The token endpoint is environment-specific:** `{gatewayUrl}/auth/oauth/v2/token`, where `{gatewayUrl}` is the gateway host issued to you at onboarding — `https://api-dev.sanlam.co.za` for development and `https://api-ppe.sanlam.co.za` for pre-production. OpenAPI allows only one `tokenUrl` per flow, so the development host is shown below as a concrete example. **Do not use it for other environments.** The production gateway host is not yet published; obtain it from API Management rather than inferring it from the pattern above.
      flows:
        clientCredentials:
          tokenUrl: https://api-dev.sanlam.co.za/auth/oauth/v2/token
