openapi: 3.1.0
info:
  title: Vantrace Evaluate API
  version: 1.0.0
  description: >-
    Synchronous AML transaction evaluation. Sign the exact raw JSON request-body
    bytes with HMAC-SHA256 and use should_block as the only settlement gate.
  license:
    name: Proprietary
    url: https://docs.vantrace.io/resources/versioning/
servers:
  - url: '{baseUrl}'
    description: Authorized Vantrace environment
    variables:
      baseUrl:
        default: https://api.example.com
        description: Replace with the private base URL supplied for your environment.
tags:
  - name: Evaluation
    description: Synchronous transaction evaluation before settlement.
paths:
  /v1/engine/evaluate:
    post:
      tags: [Evaluation]
      operationId: evaluateTransaction
      summary: Evaluate a transaction before settlement
      description: >-
        Returns a synchronous core decision. When should_block is true, do not
        settle. Alerts, Mule analysis, and case processing are asynchronous and
        are not settlement gates.
      security:
        - ApiKey: []
      parameters:
        - $ref: '#/components/parameters/SignatureVersion'
        - $ref: '#/components/parameters/Timestamp'
        - $ref: '#/components/parameters/RequestId'
        - $ref: '#/components/parameters/Signature'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/EvaluateRequest'
            examples:
              minimalOutbound:
                summary: Minimal outbound transfer
                value:
                  transaction:
                    reference_id: BANK-TXN-0001
                    amount: 25000
                    currency: NGN
                    trx_type: transfer
                    channel: mobile_app
                    txn_direction: outbound
                    is_cash: false
                    source_account_id: 41001
                    evaluated_account_id: 41001
                    beneficiary_account_id: 91001
                  customer:
                    customer_id: CUST-1001
                    entity_type: individual
                    kyc_tier: 2
                    is_pep: false
                    sanctions_flag: false
                    adverse_media_flag: false
                    is_shell_company: false
                    has_complete_cdd: true
                  context:
                    current_balance: 480000
      responses:
        '200':
          description: Complete or explicit incomplete evaluation.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EvaluateResponse'
              examples:
                allow:
                  value:
                    evaluation_status: complete
                    rule_evaluations: []
                    trx_id: 120045
                    should_block: false
                    final_action: none
                    highest_severity: low
                    triggered_rules: []
                    triggered_count: 0
                    alert_ids: []
                    mule_risk_summary: null
                    mule_risk: null
                    behavioural_data_status: sufficient
                    behavioural_sufficiency:
                      status: sufficient
                      reasons: []
                incomplete:
                  value:
                    evaluation_status: incomplete
                    rule_evaluations:
                      - rule_id: B5
                        rule_name: Velocity spike
                        evaluation_status: failed
                        triggered: null
                        action: null
                        error_code: RULE_EVALUATION_ERROR
                    trx_id: 120046
                    should_block: true
                    final_action: block
                    highest_severity: low
                    triggered_rules: []
                    triggered_count: 0
                    alert_ids: []
                    mule_risk_summary: null
                    mule_risk: null
                    behavioural_data_status: null
                    behavioural_sufficiency: null
        '400':
          description: Malformed timestamp, request ID, or request body.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MessageError'
        '401':
          description: Missing or invalid API key, signature, or timestamp window.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MessageError'
        '422':
          description: Request-body schema validation failed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidationError'
        '500':
          description: Unexpected evaluation or database failure; treat the outcome as unknown.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MessageError'
        '503':
          description: Required service or security configuration unavailable; treat the outcome as unknown.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MessageError'
components:
  securitySchemes:
    ApiKey:
      type: apiKey
      in: header
      name: X-API-Key
      description: Environment-specific tenant API key supplied by Vantrace.
  parameters:
    SignatureVersion:
      name: X-Signature-Version
      in: header
      required: true
      description: Signature contract version. Must be v2.
      schema:
        type: string
        const: v2
    Signature:
      name: X-Signature
      in: header
      required: true
      description: Hex-encoded HMAC-SHA256 of the exact raw request-body bytes using the tenant HMAC secret.
      schema:
        type: string
        pattern: '^[A-Fa-f0-9]{64}$'
    Timestamp:
      name: X-Timestamp
      in: header
      required: true
      description: Current ISO 8601 request time. It must be within five minutes of server time.
      schema:
        type: string
        format: date-time
    RequestId:
      name: X-Request-ID
      in: header
      required: true
      description: Fresh caller-generated UUID for this request attempt.
      schema:
        type: string
        format: uuid
  schemas:
    EvaluateRequest:
      type: object
      additionalProperties: true
      required: [transaction, customer]
      properties:
        transaction:
          $ref: '#/components/schemas/Transaction'
        customer:
          $ref: '#/components/schemas/Customer'
        account_snapshot:
          $ref: '#/components/schemas/AccountSnapshot'
        context:
          $ref: '#/components/schemas/Context'
    Transaction:
      type: object
      additionalProperties: true
      required:
        - amount
        - trx_type
        - channel
        - txn_direction
        - source_account_id
      properties:
        reference_id:
          type: string
          description: Stable client transaction reference; not a server-side idempotency key.
        amount:
          type: number
          exclusiveMinimum: 0
          description: Amount in major currency units.
        currency:
          type: string
          minLength: 3
          maxLength: 3
          default: NGN
        trx_type:
          type: string
          examples: [transfer, deposit, withdrawal]
        channel:
          type: string
          examples: [mobile_app, USSD, POS, ATM, teller, online]
        txn_direction:
          type: string
          enum: [inbound, outbound]
        is_cash:
          type: boolean
          default: false
        is_cross_border:
          type: boolean
          default: false
        source_account_id:
          type: integer
        evaluated_account_id:
          type: integer
        beneficiary_account_id:
          type: integer
        counterparty_name:
          type: string
        counterparty_bank_code:
          type: string
        narration:
          type: string
        geo_lat:
          type: number
        geo_long:
          type: number
        status:
          type: string
          default: completed
        transaction_timestamp:
          type: string
          format: date-time
    Customer:
      type: object
      additionalProperties: true
      required: [customer_id, entity_type, kyc_tier]
      properties:
        customer_id:
          oneOf:
            - type: string
            - type: integer
          description: Numeric inputs are normalized to strings.
        entity_type:
          type: string
          enum: [individual, corporate]
        kyc_tier:
          type: integer
          minimum: 1
          maximum: 3
        is_pep:
          type: [boolean, 'null']
          description: CBS-supplied PEP status. Vantrace resolves it only when the CBS value is empty.
        sanctions_flag:
          type: [boolean, 'null']
          description: CBS-supplied sanctions status. Vantrace resolves it only when the CBS value is empty.
        adverse_media_flag:
          type: [boolean, 'null']
          description: CBS-supplied adverse-media status. Vantrace resolves it only when the CBS value is empty.
        is_shell_company:
          type: [boolean, 'null']
          description: Non-null CBS values, including false, are used and saved. Omitted or null values fall back to the stored database value without replacing it; null means neither source has a value.
        has_complete_cdd:
          type: [boolean, 'null']
          description: Non-null CBS values, including false, are used and saved. Omitted or null values fall back to the stored database value without replacing it; null means neither source has a value.
        kyc_last_reviewed_at:
          type: string
          format: date-time
    Context:
      type: object
      description: CBS-supplied real-time context. Additional fields depend on the integration contract and enabled rules.
      additionalProperties: true
      properties:
        current_balance:
          type: number
          description: Current CBS balance for the evaluated account at request time. Vantrace does not derive or replace it.
    AccountSnapshot:
      type: object
      additionalProperties: false
      required: [account_id, account_type]
      properties:
        account_id:
          type: integer
        open_ts:
          type: string
          format: date-time
        last_activity_ts:
          type: string
          format: date-time
        balance:
          type: number
        account_type:
          type: string
          examples: [savings, current, loan]
        currency:
          type: string
          minLength: 3
          maxLength: 3
          default: NGN
    EvaluateResponse:
      type: object
      additionalProperties: true
      required:
        - evaluation_status
        - rule_evaluations
        - trx_id
        - should_block
        - final_action
        - highest_severity
        - triggered_rules
        - triggered_count
        - alert_ids
      properties:
        evaluation_status:
          type: string
          enum: [complete, incomplete]
        rule_evaluations:
          type: array
          items:
            $ref: '#/components/schemas/RuleEvaluation'
        trx_id:
          type: integer
        should_block:
          type: boolean
          description: Authoritative synchronous settlement gate.
        final_action:
          type: string
          enum: [none, flag, alert, block]
        highest_severity:
          type: string
          enum: [low, medium, high, critical]
          description: Low is the baseline when no rule triggers.
        triggered_rules:
          type: array
          items:
            $ref: '#/components/schemas/TriggeredRule'
        triggered_count:
          type: integer
          minimum: 0
        alert_ids:
          type: array
          description: Normally empty in the immediate response because alert creation is asynchronous.
          items:
            type: integer
        mule_risk_summary:
          oneOf:
            - $ref: '#/components/schemas/MuleRiskSummary'
            - type: 'null'
        mule_risk:
          type: [object, 'null']
          additionalProperties: true
        behavioural_data_status:
          type: [string, 'null']
        behavioural_sufficiency:
          oneOf:
            - $ref: '#/components/schemas/BehaviouralSufficiency'
            - type: 'null'
    RuleEvaluation:
      type: object
      additionalProperties: true
      required: [rule_id, rule_name, evaluation_status, triggered, action, error_code]
      properties:
        rule_id:
          type: string
        rule_name:
          type: string
        evaluation_status:
          type: string
          enum: [completed, failed]
        triggered:
          type: [boolean, 'null']
        action:
          type: [string, 'null']
          enum: [none, flag, alert, block, null]
        error_code:
          type: [string, 'null']
    TriggeredRule:
      type: object
      additionalProperties: true
      required: [rule_id, rule_name, severity, action, report_type, details]
      properties:
        rule_id:
          type: string
        rule_name:
          type: string
        severity:
          type: string
          enum: [low, medium, high, critical]
        action:
          type: string
          enum: [flag, alert, block]
        report_type:
          type: [string, 'null']
        details:
          type: object
          additionalProperties: true
    MuleRiskSummary:
      type: object
      additionalProperties: true
      properties:
        enabled:
          type: boolean
        status:
          type: string
          enum: [queued, evaluated, partially_evaluated, not_evaluated, disabled, failed]
        risk_score:
          type: [number, 'null']
        risk_level:
          type: [string, 'null']
        reason:
          type: [string, 'null']
    BehaviouralSufficiency:
      type: object
      additionalProperties: true
      properties:
        status:
          type: string
        reasons:
          type: array
          items:
            type: string
    MessageError:
      type: object
      additionalProperties: true
      properties:
        detail:
          type: string
    ValidationError:
      type: object
      additionalProperties: true
      properties:
        detail:
          type: array
          items:
            type: object
            additionalProperties: true
            properties:
              type:
                type: string
              loc:
                type: array
                items: {}
              msg:
                type: string
