openapi: 3.1.0
info:
  title: Scorika API
  version: "2024-01-20"
  description: |
    Risk Scoring & Fraud Detection API.
    
    Scorika provides real-time risk assessment from multiple signals including
    email, IP, domain, URL, company, and sanctions data.
  contact:
    email: support@scorika.io
    url: https://docs.scorika.io
  license:
    name: Proprietary
    url: https://scorika.io/terms

servers:
  - url: https://api.scorika.io/v1
    description: Production
  - url: https://scorika.p.rapidapi.com/v1
    description: RapidAPI
  - url: http://localhost:3000/v1
    description: Development

tags:
  - name: Scoring
    description: Risk scoring endpoints
  - name: Entities
    description: Entity resolution and normalization
  - name: Checks
    description: Individual signal checks
  - name: Cases
    description: Case management
  - name: Webhooks
    description: Webhook subscription management for real-time event notifications
  - name: Integrations
    description: Third-party integration configuration (Slack, Jira, Google Sheets)
  - name: Analytics
    description: Analytics and reporting endpoints

security:
  - ApiKeyAuth: []

paths:
  /score:
    post:
      operationId: createScore
      tags: [Scoring]
      summary: Create risk score
      description: |
        Main scoring endpoint that orchestrates all signal checks and returns
        a unified risk score with reason codes.
      x-codeSamples:
        - lang: curl
          source: |
            curl -X POST https://api.scorika.com/v1/score \
              -H "X-Api-Key: sk_live_your_api_key" \
              -H "Content-Type: application/json" \
              -d '{
                "email": "user@example.com",
                "ip": "1.2.3.4"
              }'
        - lang: python
          source: |
            import requests

            response = requests.post(
                "https://api.scorika.com/v1/score",
                headers={
                    "X-Api-Key": "sk_live_your_api_key",
                    "Content-Type": "application/json"
                },
                json={
                    "email": "user@example.com",
                    "ip": "1.2.3.4"
                }
            )

            data = response.json()
            print(f"Score: {data['data']['score']}")
            print(f"Decision: {data['data']['decision']}")
        - lang: node
          source: |
            const response = await fetch('https://api.scorika.com/v1/score', {
              method: 'POST',
              headers: {
                'X-Api-Key': 'sk_live_your_api_key',
                'Content-Type': 'application/json'
              },
              body: JSON.stringify({
                email: 'user@example.com',
                ip: '1.2.3.4'
              })
            });

            const data = await response.json();
            console.log(`Score: ${data.data.score}`);
            console.log(`Decision: ${data.data.decision}`);
        - lang: ruby
          source: |
            require 'net/http'
            require 'json'

            uri = URI('https://api.scorika.com/v1/score')
            http = Net::HTTP.new(uri.host, uri.port)
            http.use_ssl = true

            request = Net::HTTP::Post.new(uri.path)
            request['X-Api-Key'] = 'sk_live_your_api_key'
            request['Content-Type'] = 'application/json'
            request.body = { email: 'user@example.com', ip: '1.2.3.4' }.to_json

            response = http.request(request)
            data = JSON.parse(response.body)

            puts "Score: #{data['data']['score']}"
            puts "Decision: #{data['data']['decision']}"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ScoreRequest'
            examples:
              default:
                summary: Basic scoring request
                value:
                  email: "user@example.com"
                  ip: "1.2.3.4"
              email_only:
                summary: Email only
                value:
                  email: "user@example.com"
              ip_only:
                summary: IP only
                value:
                  ip: "1.2.3.4"
      responses:
        '200':
          description: Scoring successful
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ScoreResponse'
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/AuthenticationError'
        '429':
          $ref: '#/components/responses/RateLimitError'

  /score/batch:
    post:
      operationId: createBatchScore
      tags: [Scoring]
      summary: Batch risk scoring
      description: Score multiple entities in a single request (max 100)
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BatchScoreRequest'
      responses:
        '200':
          description: Batch scoring successful
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BatchScoreResponse'

  /check/email:
    post:
      operationId: checkEmail
      tags: [Checks]
      summary: Check email risk
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/EmailCheckRequest'
      responses:
        '200':
          description: Email check successful
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EmailCheckResponse'

  /check/ip:
    post:
      operationId: checkIp
      tags: [Checks]
      summary: Check IP risk
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/IpCheckRequest'
      responses:
        '200':
          description: IP check successful
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IpCheckResponse'

  /check/domain:
    post:
      operationId: checkDomain
      tags: [Checks]
      summary: Check domain risk
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DomainCheckRequest'
      responses:
        '200':
          description: Domain check successful
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DomainCheckResponse'

  /check/url:
    post:
      operationId: checkUrl
      tags: [Checks]
      summary: Check URL for threats
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UrlCheckRequest'
      responses:
        '200':
          description: URL check successful
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UrlCheckResponse'

  /cases:
    get:
      operationId: listCases
      tags: [Cases]
      summary: List cases
      parameters:
        - name: limit
          in: query
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 20
        - name: cursor
          in: query
          schema:
            type: string
        - name: decision
          in: query
          schema:
            type: string
            enum: [allow, review, block]
        - name: created_after
          in: query
          schema:
            type: string
            format: date-time
      responses:
        '200':
          description: Cases list
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CaseListResponse'

  /cases/{id}:
    get:
      operationId: getCase
      tags: [Cases]
      summary: Get case details
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            pattern: '^case_[a-zA-Z0-9]+$'
      responses:
        '200':
          description: Case details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CaseResponse'
        '404':
          $ref: '#/components/responses/NotFoundError'

  /cases/{id}/evidence:
    get:
      operationId: getCaseEvidence
      tags: [Cases]
      summary: Get case evidence pack
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Evidence pack
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EvidenceResponse'

  /cases/{id}/feedback:
    post:
      operationId: submitCaseFeedback
      tags: [Cases]
      summary: Submit feedback on a case decision
      description: |
        Report whether a scoring decision was correct, a false positive, or false negative.
        This feedback is used to improve scoring calibration over time.
        
        **Requires scope:** `cases:write`
      parameters:
        - name: id
          in: path
          required: true
          description: Case ID (UUID)
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CaseFeedbackRequest'
            examples:
              false_positive:
                summary: Report false positive
                value:
                  type: false_positive
                  actual_outcome: legitimate
                  notes: "Customer verified via phone call"
              false_negative:
                summary: Report false negative
                value:
                  type: false_negative
                  actual_outcome: fraud
                  notes: "Chargeback received"
              correct:
                summary: Confirm correct decision
                value:
                  type: correct
                  actual_outcome: fraud
      responses:
        '201':
          description: Feedback recorded successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CaseFeedbackResponse'
        '400':
          $ref: '#/components/responses/ValidationError'
        '403':
          description: Missing required scope
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Case not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '422':
          description: Feedback already submitted for this case
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  # ============================================================================
  # Entity Resolution
  # ============================================================================
  /resolve:
    post:
      operationId: resolveEntity
      tags: [Entities]
      summary: Resolve entity to canonical form
      description: |
        Resolve a single entity (email, IP, domain, URL, company, phone) to its 
        canonical form with optional enrichment and related entity lookup.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ResolveRequest'
      responses:
        '200':
          description: Entity resolved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ResolveResponse'
        '400':
          $ref: '#/components/responses/ValidationError'
        '422':
          description: Resolution failed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  # ============================================================================
  # Phone Check
  # ============================================================================
  /check/phone:
    post:
      operationId: checkPhone
      tags: [Checks]
      summary: Check phone number risk
      description: |
        Analyze a phone number for risk signals including VoIP detection,
        carrier lookup, country validation, and high-risk patterns.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PhoneCheckRequest'
      responses:
        '200':
          description: Phone check successful
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PhoneCheckResponse'
        '400':
          $ref: '#/components/responses/ValidationError'

  # ============================================================================
  # Company Check
  # ============================================================================
  /check/company:
    post:
      operationId: checkCompany
      tags: [Checks]
      summary: Check company registration and status
      description: |
        Verify company information against national registries (ARES for CZ, ORSR for SK).
        Returns company data, status, and risk signals.
        
        **IMPORTANT:** The `country` parameter is REQUIRED. Company identifiers (IČO) 
        have the same format across multiple countries (e.g., CZ and SK both use 8-digit 
        numbers), so country must be explicitly specified to select the correct registry.
      x-codeSamples:
        - lang: curl
          source: |
            curl -X POST https://api.scorika.com/v1/check/company \
              -H "X-Api-Key: sk_live_your_api_key" \
              -H "Content-Type: application/json" \
              -d '{
                "identifier": "27074358",
                "country": "CZ"
              }'
        - lang: python
          source: |
            import requests

            response = requests.post(
                "https://api.scorika.com/v1/check/company",
                headers={"X-Api-Key": "sk_live_your_api_key"},
                json={
                    "identifier": "27074358",
                    "country": "CZ"
                }
            )
            print(response.json())
        - lang: node
          source: |
            const res = await fetch('https://api.scorika.com/v1/check/company', {
              method: 'POST',
              headers: {
                'X-Api-Key': 'sk_live_your_api_key',
                'Content-Type': 'application/json'
              },
              body: JSON.stringify({
                identifier: '27074358',
                country: 'CZ'
              })
            });
            console.log(await res.json());
        - lang: ruby
          source: |
            require 'net/http'
            require 'json'

            uri = URI('https://api.scorika.com/v1/check/company')
            http = Net::HTTP.new(uri.host, uri.port)
            http.use_ssl = true

            request = Net::HTTP::Post.new(uri)
            request['X-Api-Key'] = 'sk_live_your_api_key'
            request['Content-Type'] = 'application/json'
            request.body = { identifier: '27074358', country: 'CZ' }.to_json

            response = http.request(request)
            puts JSON.parse(response.body)
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CompanyCheckRequest'
            examples:
              default:
                summary: Czech company by IČO
                value:
                  identifier: "27074358"
                  country: "CZ"
              by_name:
                summary: Company by name
                value:
                  name: "Example s.r.o."
                  country: "CZ"
      responses:
        '200':
          description: Company check successful
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CompanyCheckResponse'
              examples:
                found:
                  summary: Company found in registry
                  value:
                    data:
                      ico: "27074358"
                      country: "CZ"
                      found: true
                      score_delta: 0
                      reason_codes: []
                      enrichment:
                        company_name: "Seznam.cz, a.s."
                        legal_form: "Akciová společnost"
                        status: "active"
                        is_active: true
                        registered_at: "2000-01-15"
                        address:
                          street: "Radlická 3294/10"
                          city: "Praha"
                          postal_code: "150 00"
                          country: "CZ"
                        vat_id: "CZ27074358"
                        nace_codes: ["62010", "63110"]
                        source: "ares"
                    meta:
                      request_id: "req_company123"
                      api_version: "2024-01-20"
                      cached: false
                      cache_ttl: 86400
                      latency_ms: 250
                not_found:
                  summary: Company not found
                  value:
                    data:
                      ico: "99999999"
                      country: "CZ"
                      found: false
                      score_delta: 50
                      reason_codes:
                        - code: "COMPANY_NOT_FOUND"
                          severity: "critical"
                          score_impact: 50
                          description: "Company identifier not found in registry"
                      enrichment: null
                    meta:
                      request_id: "req_company456"
                      api_version: "2024-01-20"
                      cached: false
                      cache_ttl: 86400
                      latency_ms: 180
                inactive:
                  summary: Company inactive
                  value:
                    data:
                      ico: "12345678"
                      country: "CZ"
                      found: true
                      score_delta: 40
                      reason_codes:
                        - code: "COMPANY_INACTIVE"
                          severity: "high"
                          score_impact: 40
                          description: "Company is dissolved or inactive"
                      enrichment:
                        company_name: "Example Company, s.r.o."
                        legal_form: "Společnost s ručením omezeným"
                        status: "dissolved"
                        is_active: false
                        registered_at: "2010-05-20"
                        source: "ares"
                    meta:
                      request_id: "req_company789"
                      api_version: "2024-01-20"
                      cached: false
                      cache_ttl: 86400
                      latency_ms: 200
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/AuthenticationError'

  # ============================================================================
  # Insolvency Check
  # ============================================================================
  /check/insolvency:
    post:
      operationId: checkInsolvency
      tags: [Checks]
      summary: Check insolvency and bankruptcy status
      description: |
        Check entity (company or person) against insolvency registries across 12 EU countries.
        Returns active and historical insolvency proceedings, bankruptcy status, and risk signals.
        
        **IMPORTANT:** Either `identifier` (with `identifier_type`) or `name` is required.
        
        **Supported countries:**
        - CZ: ISIR (Czech Insolvency Registry)
        - SK: ÚSOV (Slovak Insolvency Registry)
        - DE: Bundesanzeiger (German Insolvency)
        - FR: BODACC (French Insolvency)
        - GB/UK: The Gazette (UK Insolvency)
        - PL: KRS Insolvency (Polish)
        - AT: Ediktsdatei (Austrian Insolvency)
        - IT: Fallimenti (Italian Insolvency)
        - ES: BOE (Spanish Insolvency)
        - NL: Faillissementsregister (Dutch Insolvency)
        - BE: Moniteur Belge (Belgian Insolvency)
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/InsolvencyCheckRequest'
      responses:
        '200':
          description: Insolvency check successful
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InsolvencyCheckResponse'
              examples:
                active_insolvency:
                  summary: Active insolvency proceedings
                  value:
                    data:
                      identifier: "12345678"
                      identifier_type: "ico"
                      found: true
                      score_delta: 80
                      reason_codes:
                        - code: "INSOLVENCY_ACTIVE"
                          severity: "critical"
                          score_impact: 80
                          description: "Active insolvency proceedings"
                      enrichment:
                        has_active_insolvency: true
                        has_bankruptcy: false
                        proceedings_count: 1
                        proceedings:
                          - case_number: "KSOS 22 INS 12345/2024"
                            debtor_name: "Test Company, s.r.o."
                            status: "active"
                            type: "insolvency"
                            filed_at: "2024-01-15"
                            court: "Krajský soud v Ostravě"
                        source: "isir"
                    meta:
                      request_id: "req_insolvency123"
                      api_version: "2024-01-20"
                      cached: false
                      cache_ttl: 86400
                      latency_ms: 320
                bankruptcy:
                  summary: Bankruptcy declared
                  value:
                    data:
                      identifier: "87654321"
                      identifier_type: "ico"
                      found: true
                      score_delta: 100
                      reason_codes:
                        - code: "BANKRUPTCY_DECLARED"
                          severity: "critical"
                          score_impact: 100
                          description: "Bankruptcy declared for this entity"
                      enrichment:
                        has_active_insolvency: true
                        has_bankruptcy: true
                        proceedings_count: 1
                        proceedings:
                          - case_number: "KSOS 22 INS 99999/2024"
                            debtor_name: "Bankrupt Company, a.s."
                            status: "active"
                            type: "bankruptcy"
                            filed_at: "2024-02-01"
                            court: "Krajský soud v Praze"
                        source: "isir"
                    meta:
                      request_id: "req_insolvency456"
                      api_version: "2024-01-20"
                      cached: false
                      cache_ttl: 86400
                      latency_ms: 310
                not_found:
                  summary: No insolvency records
                  value:
                    data:
                      identifier: "11111111"
                      identifier_type: "ico"
                      found: false
                      score_delta: 0
                      reason_codes: []
                      enrichment: null
                    meta:
                      request_id: "req_insolvency789"
                      api_version: "2024-01-20"
                      cached: false
                      cache_ttl: 86400
                      latency_ms: 280
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/AuthenticationError'

  # ============================================================================
  # UBO (Ultimate Beneficial Owner) Check
  # ============================================================================
  /check/ubo:
    post:
      operationId: checkUbo
      tags: [Checks]
      summary: Check Ultimate Beneficial Owner (UBO) registry
      description: |
        Verify Ultimate Beneficial Owner (UBO) information for companies in supported EU countries.
        Returns UBO declaration status, beneficial owners list, and risk signals (PEP, sanctions).
        
        **Supported Countries:** CZ, SK, NL, FR, DE
        
        **Enterprise Feature:** UBO checks require enterprise plan and provider activation.
        Contact support to enable UBO registries for your organization.
      x-codeSamples:
        - lang: curl
          source: |
            curl -X POST https://api.scorika.com/v1/check/ubo \
              -H "X-Api-Key: sk_live_your_api_key" \
              -H "Content-Type: application/json" \
              -d '{
                "company_identifier": "27074358",
                "country": "CZ",
                "identifier_type": "ico"
              }'
        - lang: python
          source: |
            import requests

            response = requests.post(
                "https://api.scorika.com/v1/check/ubo",
                headers={"X-Api-Key": "sk_live_your_api_key"},
                json={
                    "company_identifier": "27074358",
                    "country": "CZ",
                    "identifier_type": "ico"
                }
            )
            print(response.json())
        - lang: node
          source: |
            const res = await fetch('https://api.scorika.com/v1/check/ubo', {
              method: 'POST',
              headers: {
                'X-Api-Key': 'sk_live_your_api_key',
                'Content-Type': 'application/json'
              },
              body: JSON.stringify({
                company_identifier: '27074358',
                country: 'CZ',
                identifier_type: 'ico'
              })
            });
            console.log(await res.json());
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UboCheckRequest'
            examples:
              czech_company:
                summary: Czech company by IČO
                value:
                  company_identifier: "27074358"
                  country: "CZ"
                  identifier_type: "ico"
              dutch_company:
                summary: Dutch company by KvK number
                value:
                  company_identifier: "12345678"
                  country: "NL"
                  identifier_type: "kvk_number"
              french_company:
                summary: French company by SIREN
                value:
                  company_identifier: "123456789"
                  country: "FR"
                  identifier_type: "siren"
      responses:
        '200':
          description: UBO check successful
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UboCheckResponse'
              examples:
                ubo_declared:
                  summary: UBO declared with beneficial owners
                  value:
                    data:
                      company_identifier: "27074358"
                      country: "CZ"
                      ubo_declared: true
                      ubo_count: 2
                      beneficial_owners:
                        - name: "Jan Novák"
                          ownership_percentage: 45.5
                          is_pep: false
                          is_sanctioned: false
                        - name: "Marie Svobodová"
                          ownership_percentage: 30.0
                          is_pep: false
                          is_sanctioned: false
                      score_delta: 0
                      reason_codes: []
                    meta:
                      request_id: "req_ubo123"
                      api_version: "2024-01-20"
                      cached: false
                      cache_ttl: 86400
                      latency_ms: 450
                ubo_high_risk:
                  summary: UBO with high-risk owners (PEP/sanctioned)
                  value:
                    data:
                      company_identifier: "87654321"
                      country: "CZ"
                      ubo_declared: true
                      ubo_count: 1
                      beneficial_owners:
                        - name: "John Doe"
                          ownership_percentage: 60.0
                          is_pep: true
                          is_sanctioned: false
                      score_delta: 50
                      reason_codes:
                        - code: "UBO_HIGH_RISK"
                          severity: "high"
                          score_impact: 50
                          description: "High-risk beneficial owners detected (PEP or sanctioned individuals)"
                          details:
                            - name: "John Doe"
                              reason: "PEP"
                    meta:
                      request_id: "req_ubo456"
                      api_version: "2024-01-20"
                      cached: false
                      cache_ttl: 86400
                      latency_ms: 420
                ubo_not_declared:
                  summary: UBO not declared
                  value:
                    data:
                      company_identifier: "11111111"
                      country: "CZ"
                      ubo_declared: false
                      ubo_count: 0
                      beneficial_owners: []
                      score_delta: 30
                      reason_codes:
                        - code: "UBO_NOT_DECLARED"
                          severity: "medium"
                          score_impact: 30
                          description: "Ultimate Beneficial Owner information not declared in registry"
                    meta:
                      request_id: "req_ubo789"
                      api_version: "2024-01-20"
                      cached: false
                      cache_ttl: 86400
                      latency_ms: 380
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/AuthenticationError'

  # ============================================================================
  # PEP (Politically Exposed Persons) Screening
  # ============================================================================
  /check/pep:
    post:
      operationId: checkPep
      tags: [Checks]
      summary: Screen individual against PEP databases
      description: |
        Screen an individual against Politically Exposed Persons (PEP) databases.
        Uses OpenSanctions aggregated data covering 50+ countries.
        
        **PEP Types:**
        - Active: Currently holds public position
        - Historical: Previously held public position  
        - Family Member: Related to a PEP
        - Close Associate: Known associate of a PEP
        
        **Enterprise Feature:** PEP screening requires enterprise plan and provider activation.
        Contact support to enable OpenSanctions for your organization.
      x-codeSamples:
        - lang: curl
          source: |
            curl -X POST https://api.scorika.com/v1/check/pep \
              -H "X-Api-Key: sk_live_your_api_key" \
              -H "Content-Type: application/json" \
              -d '{
                "name": "John Doe",
                "country": "US",
                "birth_date": "1980-01-15"
              }'
        - lang: python
          source: |
            import requests

            response = requests.post(
                "https://api.scorika.com/v1/check/pep",
                headers={"X-Api-Key": "sk_live_your_api_key"},
                json={
                    "name": "John Doe",
                    "country": "US",
                    "birth_date": "1980-01-15"
                }
            )
            print(response.json())
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PepCheckRequest'
            examples:
              by_name:
                summary: Screen by full name
                value:
                  name: "John Doe"
                  country: "US"
                  birth_date: "1980-01-15"
              by_name_parts:
                summary: Screen by name parts (more precise)
                value:
                  first_name: "John"
                  last_name: "Doe"
                  country: "US"
      responses:
        '200':
          description: PEP screening successful
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PepCheckResponse'
              examples:
                pep_found:
                  summary: Active PEP found
                  value:
                    data:
                      name: "John Doe"
                      is_pep: true
                      pep_type: "active"
                      matches:
                        - matched_name: "John Doe"
                          country: "US"
                          position: "Senator"
                          start_date: "2020-01-01"
                          end_date: null
                          match_confidence: 0.95
                      score_delta: 40
                      reason_codes:
                        - code: "PEP_ACTIVE"
                          severity: "high"
                          score_impact: 40
                          description: "Individual is an active Politically Exposed Person"
                    meta:
                      request_id: "req_pep123"
                      api_version: "2024-01-20"
                      cached: false
                      cache_ttl: 604800
                      latency_ms: 350
                not_pep:
                  summary: Not a PEP
                  value:
                    data:
                      name: "Jane Smith"
                      is_pep: false
                      pep_type: null
                      matches: []
                      score_delta: 0
                      reason_codes: []
                    meta:
                      request_id: "req_pep456"
                      api_version: "2024-01-20"
                      cached: false
                      cache_ttl: 604800
                      latency_ms: 280
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/AuthenticationError'

  # ============================================================================
  # IBAN Check
  # ============================================================================
  /check/iban:
    post:
      operationId: checkIban
      tags: [Checks]
      summary: Validate IBAN format and checksum
      description: |
        Validate IBAN (International Bank Account Number) format, checksum (ISO 7064 Mod 97-10),
        and bank code mapping for CZ/SK. Returns bank information and risk signals.
        
        **No external API calls** - all validation is performed locally.
      x-codeSamples:
        - lang: curl
          source: |
            curl -X POST https://api.scorika.com/v1/check/iban \
              -H "X-Api-Key: sk_live_your_api_key" \
              -H "Content-Type: application/json" \
              -d '{
                "iban": "CZ6508000000192000145399"
              }'
        - lang: python
          source: |
            import requests

            response = requests.post(
                "https://api.scorika.com/v1/check/iban",
                headers={"X-Api-Key": "sk_live_your_api_key"},
                json={"iban": "CZ6508000000192000145399"}
            )
            print(response.json())
        - lang: node
          source: |
            const res = await fetch('https://api.scorika.com/v1/check/iban', {
              method: 'POST',
              headers: {
                'X-Api-Key': 'sk_live_your_api_key',
                'Content-Type': 'application/json'
              },
              body: JSON.stringify({ iban: 'CZ6508000000192000145399' })
            });
            console.log(await res.json());
        - lang: ruby
          source: |
            require 'net/http'
            require 'json'

            uri = URI('https://api.scorika.com/v1/check/iban')
            http = Net::HTTP.new(uri.host, uri.port)
            http.use_ssl = true

            request = Net::HTTP::Post.new(uri)
            request['X-Api-Key'] = 'sk_live_your_api_key'
            request['Content-Type'] = 'application/json'
            request.body = { iban: 'CZ6508000000192000145399' }.to_json

            response = http.request(request)
            puts JSON.parse(response.body)
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/IbanCheckRequest'
            examples:
              default:
                summary: Czech IBAN
                value:
                  iban: "CZ6508000000192000145399"
              with_country_check:
                summary: IBAN with country validation
                value:
                  iban: "CZ6508000000192000145399"
                  expected_country: "CZ"
      responses:
        '200':
          description: IBAN check successful
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IbanCheckResponse'
              examples:
                valid:
                  summary: Valid IBAN
                  value:
                    data:
                      iban: "CZ6508000000192000145399"
                      valid: true
                      country: "CZ"
                      bank_code: "0800"
                      bank_name: "Česká spořitelna, a.s."
                      bic: "GIBACZPX"
                      score_delta: 0
                      reason_codes: []
                    meta:
                      request_id: "req_iban123"
                      api_version: "2024-01-20"
                      cached: false
                      cache_ttl: 86400
                      latency_ms: 5
                invalid_format:
                  summary: Invalid IBAN format
                  value:
                    data:
                      iban: "INVALID"
                      valid: false
                      score_delta: 50
                      reason_codes:
                        - code: "IBAN_INVALID_FORMAT"
                          severity: "critical"
                          score_impact: 50
                          description: "IBAN format is invalid"
                    meta:
                      request_id: "req_iban456"
                      api_version: "2024-01-20"
                      cached: false
                      cache_ttl: 86400
                      latency_ms: 3
                invalid_checksum:
                  summary: Invalid IBAN checksum
                  value:
                    data:
                      iban: "CZ6608000000192000145399"
                      valid: false
                      score_delta: 50
                      reason_codes:
                        - code: "IBAN_INVALID_CHECKSUM"
                          severity: "critical"
                          score_impact: 50
                          description: "IBAN checksum is invalid"
                    meta:
                      request_id: "req_iban789"
                      api_version: "2024-01-20"
                      cached: false
                      cache_ttl: 86400
                      latency_ms: 4
                country_mismatch:
                  summary: Country mismatch
                  value:
                    data:
                      iban: "CZ6508000000192000145399"
                      valid: true
                      country: "CZ"
                      score_delta: 20
                      reason_codes:
                        - code: "IBAN_COUNTRY_MISMATCH"
                          severity: "medium"
                          score_impact: 20
                          description: "IBAN country (CZ) does not match expected country (SK)"
                    meta:
                      request_id: "req_iban012"
                      api_version: "2024-01-20"
                      cached: false
                      cache_ttl: 86400
                      latency_ms: 5
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/AuthenticationError'

  # ============================================================================
  # Sanctions Check
  # ============================================================================
  /check/sanctions:
    post:
      operationId: checkSanctions
      tags: [Checks]
      summary: Check entity against sanctions lists
      description: |
        Check entity (company or individual) against OFAC SDN list (US) and EU Consolidated Sanctions list.
        Returns matches with match scores, programs, and aliases.
        
        **IMPORTANT:** Either `name` or `identifier` is required.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SanctionsCheckRequest'
      responses:
        '200':
          description: Sanctions check successful
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SanctionsCheckResponse'
              examples:
                ofac_match:
                  summary: OFAC SDN match
                  value:
                    data:
                      name: "TEST SANCTIONED ENTITY"
                      found: true
                      match_count: 1
                      score_delta: 100
                      reason_codes:
                        - code: "SANCTIONS_OFAC_MATCH"
                          severity: "critical"
                          score_impact: 100
                          description: "Match found in OFAC SDN list"
                      enrichment:
                        ofac_matches:
                          - uid: "12345"
                            name: "TEST SANCTIONED ENTITY"
                            type: "entity"
                            programs: ["RUSSIA-EO14024"]
                            match_score: 0.95
                    meta:
                      request_id: "req_sanctions123"
                      api_version: "2024-01-20"
                      cached: false
                      cache_ttl: 604800
                      latency_ms: 150
                no_match:
                  summary: No sanctions match
                  value:
                    data:
                      name: "LEGITIMATE COMPANY"
                      found: false
                      match_count: 0
                      score_delta: 0
                      reason_codes: []
                      enrichment:
                        ofac_matches: []
                        eu_matches: []
                    meta:
                      request_id: "req_sanctions456"
                      api_version: "2024-01-20"
                      cached: false
                      cache_ttl: 604800
                      latency_ms: 120
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/AuthenticationError'

  # ============================================================================
  # Address Check
  # ============================================================================
  /check/address:
    post:
      operationId: checkAddress
      tags: [Checks]
      summary: Validate and normalize address
      description: |
        Validate address against national address registries across 8 EU countries.
        Returns normalized address, GPS coordinates, and validation status.
        
        **IMPORTANT:** The `country` parameter is REQUIRED.
        
        **Supported countries:**
        - CZ: RÚIAN (Czech Address Registry)
        - FR: BAN (French Address Registry)
        - DE: BKG (German Address Registry)
        - GB/UK: OS Places (UK Address Registry)
        - NL: BAG/PDOK (Dutch Address Registry)
        - DK: DAWA (Danish Address Registry)
        - BE: CRAB (Belgian Address Registry)
        - SE: Lantmäteriet (Swedish Address Registry)
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AddressCheckRequest'
      responses:
        '200':
          description: Address check successful
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AddressCheckResponse'
              examples:
                found:
                  summary: Address found and validated
                  value:
                    data:
                      address: "Václavské náměstí 1, Praha"
                      country: "CZ"
                      found: true
                      score_delta: 0
                      reason_codes: []
                      enrichment:
                        normalized_address: "Václavské náměstí 1, Praha, 110 00"
                        address_id: "12345678"
                        street: "Václavské náměstí"
                        city: "Praha"
                        postal_code: "110 00"
                        gps:
                          latitude: 50.0806
                          longitude: 14.4286
                          coordinate_system: "EPSG:5514"
                        address_type: "standard"
                        match_quality: 0.95
                        source: "ruian"
                    meta:
                      request_id: "req_address123"
                      api_version: "2024-01-20"
                      cached: false
                      cache_ttl: 86400
                      latency_ms: 180
                not_found:
                  summary: Address not found
                  value:
                    data:
                      address: "Nonexistent Street 999, Praha"
                      country: "CZ"
                      found: false
                      score_delta: 20
                      reason_codes:
                        - code: "ADDRESS_NOT_FOUND"
                          severity: "medium"
                          score_impact: 20
                          description: "Address not found in RÚIAN registry"
                      enrichment: null
                    meta:
                      request_id: "req_address456"
                      api_version: "2024-01-20"
                      cached: false
                      cache_ttl: 86400
                      latency_ms: 150
                partial_match:
                  summary: Partial address match
                  value:
                    data:
                      address: "Václavské náměstí, Praha"
                      country: "CZ"
                      found: true
                      score_delta: 10
                      reason_codes:
                        - code: "ADDRESS_PARTIAL_MATCH"
                          severity: "low"
                          score_impact: 10
                          description: "Address found but with partial match only"
                      enrichment:
                        normalized_address: "Václavské náměstí, Praha"
                        match_quality: 0.75
                        source: "ruian"
                    meta:
                      request_id: "req_address789"
                      api_version: "2024-01-20"
                      cached: false
                      cache_ttl: 86400
                      latency_ms: 170
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/AuthenticationError'

  # ============================================================================
  # VAT Check
  # ============================================================================
  /check/vat:
    post:
      operationId: checkVat
      tags: [Checks]
      summary: Validate VAT number (EU)
      description: |
        Validate VAT number via EU VIES (VAT Information Exchange System).
        Returns company name, address, and validation status.
        
        **IMPORTANT:** `vat_number` is required. Format: country code + number (e.g., "CZ12345678").
      x-codeSamples:
        - lang: curl
          source: |
            curl -X POST https://api.scorika.com/v1/check/vat \
              -H "X-Api-Key: sk_live_your_api_key" \
              -H "Content-Type: application/json" \
              -d '{
                "vat_number": "CZ12345678"
              }'
        - lang: python
          source: |
            import requests

            response = requests.post(
                "https://api.scorika.com/v1/check/vat",
                headers={"X-Api-Key": "sk_live_your_api_key"},
                json={"vat_number": "CZ12345678"}
            )
            print(response.json())
        - lang: node
          source: |
            const res = await fetch('https://api.scorika.com/v1/check/vat', {
              method: 'POST',
              headers: {
                'X-Api-Key': 'sk_live_your_api_key',
                'Content-Type': 'application/json'
              },
              body: JSON.stringify({ vat_number: 'CZ12345678' })
            });
            console.log(await res.json());
        - lang: ruby
          source: |
            require 'net/http'
            require 'json'

            uri = URI('https://api.scorika.com/v1/check/vat')
            http = Net::HTTP.new(uri.host, uri.port)
            http.use_ssl = true

            request = Net::HTTP::Post.new(uri)
            request['X-Api-Key'] = 'sk_live_your_api_key'
            request['Content-Type'] = 'application/json'
            request.body = { vat_number: 'CZ12345678' }.to_json

            response = http.request(request)
            puts JSON.parse(response.body)
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/VatCheckRequest'
            examples:
              default:
                summary: Czech VAT number
                value:
                  vat_number: "CZ12345678"
              with_name_verification:
                summary: VAT with name verification
                value:
                  vat_number: "CZ12345678"
                  expected_name: "Example s.r.o."
      responses:
        '200':
          description: VAT check successful
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VatCheckResponse'
              examples:
                valid:
                  summary: Valid VAT number
                  value:
                    data:
                      vat_number: "CZ12345678"
                      valid: true
                      country_code: "CZ"
                      company_name: "Example s.r.o."
                      address: "Example Street 123, Prague"
                      score_delta: 0
                      reason_codes: []
                      enrichment:
                        source: "vies"
                        validated_at: "2024-01-10T08:00:00Z"
                    meta:
                      request_id: "req_vat123"
                      api_version: "2024-01-20"
                      cached: false
                      cache_ttl: 86400
                      latency_ms: 300
                invalid:
                  summary: Invalid VAT number
                  value:
                    data:
                      vat_number: "CZ99999999"
                      valid: false
                      score_delta: 30
                      reason_codes:
                        - code: "VAT_INVALID"
                          severity: "medium"
                          score_impact: 30
                          description: "VAT number is invalid"
                    meta:
                      request_id: "req_vat456"
                      api_version: "2024-01-20"
                      cached: false
                      cache_ttl: 86400
                      latency_ms: 250
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/AuthenticationError'

  # ============================================================================
  # LEI Check
  # ============================================================================
  /check/lei:
    post:
      operationId: checkLei
      tags: [Checks]
      summary: Lookup Legal Entity Identifier (LEI)
      description: |
        Lookup Legal Entity Identifier (LEI) via GLEIF (Global Legal Entity Identifier Foundation).
        Returns legal entity information including name, jurisdiction, registration status, and HQ address.
        
        **IMPORTANT:** Either `lei` or `name` is required. If `name` is provided, performs search by company name.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/LeiCheckRequest'
      responses:
        '200':
          description: LEI lookup successful
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LeiCheckResponse'
              examples:
                found:
                  summary: LEI found
                  value:
                    data:
                      lei: "5493000J2M89Q7X1D75"
                      found: true
                      legal_name: "Example Corporation"
                      legal_form: "Corporation"
                      jurisdiction: "US"
                      registration_status: "ACTIVE"
                      hq_address:
                        street: "123 Main St"
                        city: "New York"
                        country: "US"
                      score_delta: 0
                      reason_codes: []
                      enrichment:
                        source: "gleif"
                        last_updated: "2024-01-10T08:00:00Z"
                    meta:
                      request_id: "req_lei123"
                      api_version: "2024-01-20"
                      cached: false
                      cache_ttl: 86400
                      latency_ms: 250
                not_found:
                  summary: LEI not found
                  value:
                    data:
                      lei: "INVALID12345678901234"
                      found: false
                      score_delta: 0
                      reason_codes: []
                    meta:
                      request_id: "req_lei456"
                      api_version: "2024-01-20"
                      cached: false
                      cache_ttl: 86400
                      latency_ms: 200
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/AuthenticationError'

  # ============================================================================
  # Webhooks
  # ============================================================================
  /webhooks:
    get:
      operationId: listWebhooks
      tags: [Webhooks]
      summary: List webhook subscriptions
      description: |
        List all webhook subscriptions for the current API key.
        Requires `webhooks:read` scope.
      responses:
        '200':
          description: List of webhooks
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhookListResponse'
        '401':
          $ref: '#/components/responses/AuthenticationError'
        '403':
          description: Missing required scope
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

    post:
      operationId: createWebhook
      tags: [Webhooks]
      summary: Create webhook subscription
      description: |
        Create a new webhook subscription to receive real-time event notifications.
        Requires `webhooks:write` scope.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WebhookCreateRequest'
      responses:
        '201':
          description: Webhook created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhookResponse'
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/AuthenticationError'

  /webhooks/{id}:
    get:
      operationId: getWebhook
      tags: [Webhooks]
      summary: Get webhook details
      description: Get details of a specific webhook subscription.
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
          description: Webhook subscription ID
      responses:
        '200':
          description: Webhook details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhookResponse'
        '404':
          $ref: '#/components/responses/NotFoundError'

    put:
      operationId: updateWebhook
      tags: [Webhooks]
      summary: Update webhook subscription
      description: |
        Update an existing webhook subscription.
        Requires `webhooks:write` scope.
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WebhookUpdateRequest'
      responses:
        '200':
          description: Webhook updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhookResponse'
        '400':
          $ref: '#/components/responses/ValidationError'
        '404':
          $ref: '#/components/responses/NotFoundError'

    delete:
      operationId: deleteWebhook
      tags: [Webhooks]
      summary: Delete webhook subscription
      description: |
        Delete a webhook subscription. This action cannot be undone.
        Requires `webhooks:write` scope.
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
      responses:
        '204':
          description: Webhook deleted
        '404':
          $ref: '#/components/responses/NotFoundError'

  /webhooks/{id}/test:
    post:
      operationId: testWebhook
      tags: [Webhooks]
      summary: Test webhook delivery
      description: |
        Send a test ping event to the webhook URL to verify connectivity.
        Requires `webhooks:write` scope.
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: Test webhook queued
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: Test webhook queued for delivery
        '404':
          $ref: '#/components/responses/NotFoundError'

  # ============================================================================
  # Integrations
  # ============================================================================
  /integrations:
    get:
      operationId: listIntegrations
      tags: [Integrations]
      summary: List configured integrations
      description: |
        List all third-party integrations configured for the current API key.
        Requires `integrations:read` scope.
      responses:
        '200':
          description: List of integrations
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IntegrationListResponse'
        '401':
          $ref: '#/components/responses/AuthenticationError'

    post:
      operationId: createIntegration
      tags: [Integrations]
      summary: Create integration
      description: |
        Configure a new third-party integration.
        Requires `integrations:write` scope.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/IntegrationCreateRequest'
      responses:
        '201':
          description: Integration created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IntegrationResponse'
        '400':
          $ref: '#/components/responses/ValidationError'

  /integrations/{provider}:
    put:
      operationId: updateIntegration
      tags: [Integrations]
      summary: Update integration
      description: Update an existing integration configuration.
      parameters:
        - name: provider
          in: path
          required: true
          schema:
            type: string
            enum: [slack, jira, google_sheets, webhook]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/IntegrationUpdateRequest'
      responses:
        '200':
          description: Integration updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IntegrationResponse'
        '404':
          $ref: '#/components/responses/NotFoundError'

    delete:
      operationId: deleteIntegration
      tags: [Integrations]
      summary: Delete integration
      description: Remove an integration configuration.
      parameters:
        - name: provider
          in: path
          required: true
          schema:
            type: string
            enum: [slack, jira, google_sheets, webhook]
      responses:
        '204':
          description: Integration deleted
        '404':
          $ref: '#/components/responses/NotFoundError'

  /integrations/{provider}/test:
    post:
      operationId: testIntegration
      tags: [Integrations]
      summary: Test integration
      description: |
        Test connectivity and configuration of an integration.
        Requires `integrations:write` scope.
      parameters:
        - name: provider
          in: path
          required: true
          schema:
            type: string
            enum: [slack, jira, google_sheets, webhook]
      responses:
        '200':
          description: Test successful
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
        '422':
          description: Test failed
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: false
                  message:
                    type: string

  # ============================================================================
  # Analytics
  # ============================================================================
  /analytics/summary:
    get:
      operationId: getAnalyticsSummary
      tags: [Analytics]
      summary: Get analytics summary
      description: |
        Get aggregated analytics and statistics for cases.
        Requires `cases:read` scope.
      parameters:
        - name: from
          in: query
          schema:
            type: string
            format: date-time
          description: Start date (default 7 days ago)
        - name: to
          in: query
          schema:
            type: string
            format: date-time
          description: End date (default now)
      responses:
        '200':
          description: Analytics summary
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AnalyticsSummaryResponse'
        '401':
          $ref: '#/components/responses/AuthenticationError'

  /analytics/score_distribution:
    get:
      operationId: getScoreDistribution
      tags: [Analytics]
      summary: Get score distribution
      description: |
        Get distribution of risk scores across all cases.
        Used for calibration monitoring and analysis.
        Requires `cases:read` scope.
      parameters:
        - name: from
          in: query
          schema:
            type: string
            format: date-time
          description: Start date (default 30 days ago)
        - name: to
          in: query
          schema:
            type: string
            format: date-time
          description: End date (default now)
        - name: bucket_size
          in: query
          schema:
            type: integer
            default: 10
          description: Score bucket size (default 10)
      responses:
        '200':
          description: Score distribution data
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ScoreDistributionResponse'
        '401':
          $ref: '#/components/responses/AuthenticationError'

  /analytics/signals:
    get:
      operationId: getSignalPerformance
      tags: [Analytics]
      summary: Get signal performance metrics
      description: |
        Get performance metrics for each signal type including
        average score impact, hit rate, and false positive rate.
        Requires `cases:read` scope.
      parameters:
        - name: from
          in: query
          schema:
            type: string
            format: date-time
          description: Start date (default 30 days ago)
        - name: to
          in: query
          schema:
            type: string
            format: date-time
          description: End date (default now)
      responses:
        '200':
          description: Signal performance metrics
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SignalPerformanceResponse'
        '401':
          $ref: '#/components/responses/AuthenticationError'

  /analytics/reason_codes:
    get:
      operationId: getReasonCodeFrequency
      tags: [Analytics]
      summary: Get reason code frequency
      description: |
        Get frequency and impact metrics for each reason code.
        Useful for understanding which signals fire most often.
        Requires `cases:read` scope.
      parameters:
        - name: from
          in: query
          schema:
            type: string
            format: date-time
          description: Start date (default 30 days ago)
        - name: to
          in: query
          schema:
            type: string
            format: date-time
          description: End date (default now)
        - name: limit
          in: query
          schema:
            type: integer
            default: 20
          description: Maximum number of reason codes to return
      responses:
        '200':
          description: Reason code frequency data
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ReasonCodeFrequencyResponse'
        '401':
          $ref: '#/components/responses/AuthenticationError'

components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-Api-Key
    RapidApiKey:
      type: apiKey
      in: header
      name: X-RapidAPI-Key

  schemas:
    # Common
    Meta:
      type: object
      required:
        - request_id
        - api_version
      properties:
        request_id:
          type: string
          example: req_abc123
        api_version:
          type: string
          example: "2024-01-20"
        cached:
          type: boolean
        cache_ttl:
          type: integer
        latency_ms:
          type: integer

    Pagination:
      type: object
      properties:
        cursor:
          type: string
        has_more:
          type: boolean
        limit:
          type: integer

    ReasonCode:
      type: object
      required:
        - code
        - severity
        - score_impact
      properties:
        code:
          type: string
          example: EMAIL_DISPOSABLE
        severity:
          type: string
          enum: [low, medium, high, critical]
        score_impact:
          type: integer
          minimum: 0
          maximum: 100
        signal:
          type: string
        description:
          type: string

    SignalResult:
      type: object
      properties:
        status:
          type: string
          enum: [success, error, timeout, skipped]
        score_delta:
          type: integer
        cached:
          type: boolean
        latency_ms:
          type: integer
        error_message:
          type: string

    Entity:
      type: object
      properties:
        id:
          type: string
          example: ent_abc123
        type:
          type: string
          enum: [email, ip, domain, url, company, person]
        canonical_value:
          type: string

    # Score
    ScoreRequest:
      type: object
      properties:
        email:
          type: string
          format: email
          maxLength: 254
          description: Email address (RFC 5321 limit)
        ip:
          type: string
          maxLength: 45
          description: IPv4 or IPv6 address
        domain:
          type: string
          maxLength: 253
          description: Domain name (DNS limit)
        url:
          type: string
          format: uri
          maxLength: 2048
          description: Full URL
        phone:
          type: string
          maxLength: 20
          description: Phone number (E.164 format)
        company:
          type: string
          maxLength: 200
          description: Company name
        context:
          type: object
          maxProperties: 50
          description: Additional context (max 50 keys)
          properties:
            event_type:
              type: string
            order_value:
              type: number
            currency:
              type: string
            user_id:
              type: string
            session_id:
              type: string
        signals:
          type: array
          maxItems: 20
          description: Specific signals to run (max 20)
          items:
            type: string
            enum: [email, ip, domain, url, phone, velocity, cross_field, order_context, sanctions]
        options:
          type: object
          properties:
            skip_cache:
              type: boolean
              default: false
            include_evidence:
              type: boolean
              default: false

    SuggestedAction:
      type: object
      description: Recommended action based on the risk assessment
      required:
        - code
        - message
        - urgency
      properties:
        code:
          type: string
          description: Machine-readable action code for automation
          enum:
            - PROCEED
            - REQUEST_EMAIL_VERIFICATION
            - REQUEST_PHONE_VERIFICATION
            - REQUEST_ID_VERIFICATION
            - MANUAL_REVIEW
            - DELAY_FULFILLMENT
            - LIMIT_TRANSACTION
            - BLOCK_AND_NOTIFY
            - ESCALATE_TO_FRAUD_TEAM
          example: REQUEST_PHONE_VERIFICATION
        message:
          type: string
          description: Human-readable action description
          example: Request phone verification before proceeding
        urgency:
          type: string
          description: How quickly action should be taken
          enum: [low, medium, high, critical]
          example: medium
        automation_hint:
          type: string
          description: Hint for automation systems
          example: trigger_sms_otp

    RiskFactors:
      type: object
      description: Risk factors grouped by severity for UI display
      properties:
        critical:
          type: array
          items:
            type: string
          description: Critical risk factors requiring immediate attention
          example: ["SANCTIONS_MATCH", "KNOWN_FRAUD_RING"]
        high:
          type: array
          items:
            type: string
          description: High severity risk factors
          example: ["IP_TOR_EXIT", "EMAIL_DISPOSABLE"]
        medium:
          type: array
          items:
            type: string
          description: Medium severity risk factors
          example: ["IP_DATACENTER_ASN", "DOMAIN_AGE_LT_7D"]
        low:
          type: array
          items:
            type: string
          description: Low severity indicators
          example: ["EMAIL_FREE_PROVIDER", "IP_VPN_LIKELY"]

    ScoreData:
      type: object
      required:
        - case_id
        - score
        - decision
        - suggested_action
        - risk_factors
      properties:
        case_id:
          type: string
          format: uuid
          example: case_xyz789
          description: |
            Unique identifier for this scoring case. Save this ID to:
            - Retrieve case details later: GET /v1/cases/{case_id}
            - Download evidence pack: GET /v1/cases/{case_id}/evidence
            - Submit feedback on decision: POST /v1/cases/{case_id}/feedback
        score:
          type: integer
          minimum: 0
          maximum: 100
          description: Risk score from 0 (safe) to 100 (high risk)
        decision:
          type: string
          enum: [allow, review, block]
          description: Recommended decision based on score thresholds
        suggested_action:
          $ref: '#/components/schemas/SuggestedAction'
        risk_factors:
          $ref: '#/components/schemas/RiskFactors'
        confidence:
          type: number
          minimum: 0
          maximum: 1
          description: Confidence level based on signal availability and quality
        score_breakdown:
          type: object
          additionalProperties:
            type: integer
          description: Score contribution from each signal
          example:
            baseline: 0
            email: 5
            ip: 25
            domain: 20
            velocity: 17
        reason_codes:
          type: array
          items:
            $ref: '#/components/schemas/ReasonCode'
        signals:
          type: object
          additionalProperties:
            $ref: '#/components/schemas/SignalResult'
        entity:
          $ref: '#/components/schemas/Entity'
        policy_version:
          type: string

    ScoreResponse:
      type: object
      required:
        - data
        - meta
      properties:
        data:
          $ref: '#/components/schemas/ScoreData'
        meta:
          $ref: '#/components/schemas/Meta'
        links:
          type: object
          properties:
            self:
              type: string
            evidence:
              type: string

    # Batch
    BatchScoreRequest:
      type: object
      required:
        - requests
      properties:
        requests:
          type: array
          maxItems: 100
          items:
            type: object
            required:
              - id
            properties:
              id:
                type: string
              email:
                type: string
              ip:
                type: string
        options:
          type: object
          properties:
            signals:
              type: array
              items:
                type: string
            fail_fast:
              type: boolean

    BatchScoreResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            responses:
              type: array
              items:
                type: object
                properties:
                  id:
                    type: string
                  case_id:
                    type: string
                  score:
                    type: integer
                  decision:
                    type: string
                  status:
                    type: string
            summary:
              type: object
              properties:
                total:
                  type: integer
                succeeded:
                  type: integer
                failed:
                  type: integer
        meta:
          $ref: '#/components/schemas/Meta'

    # Email Check
    EmailCheckRequest:
      type: object
      required:
        - email
      properties:
        email:
          type: string
          format: email
        options:
          type: object
          properties:
            check_deliverability:
              type: boolean
            check_breach:
              type: boolean

    EmailCheckResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            email:
              type: string
            normalized:
              type: string
            valid:
              type: boolean
            score_delta:
              type: integer
            reason_codes:
              type: array
              items:
                $ref: '#/components/schemas/ReasonCode'
            details:
              type: object
              properties:
                domain:
                  type: string
                provider_type:
                  type: string
                has_mx:
                  type: boolean
                is_role_account:
                  type: boolean
                is_free_provider:
                  type: boolean
        meta:
          $ref: '#/components/schemas/Meta'

    # IP Check
    IpCheckRequest:
      type: object
      required:
        - ip
      properties:
        ip:
          type: string
        options:
          type: object
          properties:
            expected_country:
              type: string

    IpCheckResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            ip:
              type: string
            score_delta:
              type: integer
            reason_codes:
              type: array
              items:
                $ref: '#/components/schemas/ReasonCode'
            details:
              type: object
              properties:
                asn:
                  type: integer
                asn_name:
                  type: string
                country:
                  type: string
                is_datacenter:
                  type: boolean
                is_vpn:
                  type: boolean
                is_tor:
                  type: boolean
        meta:
          $ref: '#/components/schemas/Meta'

    # Domain Check
    DomainCheckRequest:
      type: object
      required:
        - domain
      properties:
        domain:
          type: string

    DomainCheckResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            domain:
              type: string
            normalized:
              type: string
            score_delta:
              type: integer
            reason_codes:
              type: array
              items:
                $ref: '#/components/schemas/ReasonCode'
            details:
              type: object
              properties:
                age_days:
                  type: integer
                registrar:
                  type: string
                registered_at:
                  type: string
                  format: date-time
        meta:
          $ref: '#/components/schemas/Meta'

    # URL Check
    UrlCheckRequest:
      type: object
      required:
        - url
      properties:
        url:
          type: string
          format: uri

    UrlCheckResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            url:
              type: string
            score_delta:
              type: integer
            reason_codes:
              type: array
              items:
                $ref: '#/components/schemas/ReasonCode'
            details:
              type: object
              properties:
                threat_type:
                  type: string
                threat_source:
                  type: string
        meta:
          $ref: '#/components/schemas/Meta'

    # Company Check
    CompanyCheckRequest:
      type: object
      required:
        - ico
        - country
      properties:
        ico:
          type: string
          description: Company identification number (IČO)
          example: "27074358"
        identifier:
          type: string
          description: Alternative field name for IČO (use if ico is not provided)
          example: "27074358"
        country:
          type: string
          description: |
            Country code (ISO 3166-1 alpha-2). **REQUIRED** - Company identifiers have 
            the same format across multiple countries (e.g., CZ and SK both use 8-digit 
            numbers), so country must be explicitly specified.
          example: "CZ"
          enum: [CZ, SK, DE, GB, UK]

    CompanyCheckResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            ico:
              type: string
            country:
              type: string
            found:
              type: boolean
            score_delta:
              type: integer
            reason_codes:
              type: array
              items:
                $ref: '#/components/schemas/ReasonCode'
            enrichment:
              type: object
              nullable: true
              properties:
                company_name:
                  type: string
                legal_form:
                  type: string
                status:
                  type: string
                  enum: [active, dissolved, in_liquidation, in_bankruptcy]
                is_active:
                  type: boolean
                registered_at:
                  type: string
                  format: date
                address:
                  type: object
                  properties:
                    street:
                      type: string
                    city:
                      type: string
                    postal_code:
                      type: string
                    country:
                      type: string
                vat_id:
                  type: string
                nace_codes:
                  type: array
                  items:
                    type: string
                source:
                  type: string
                  enum: [ares, orsr]
        meta:
          $ref: '#/components/schemas/Meta'

    # Insolvency Check
    InsolvencyCheckRequest:
      type: object
      oneOf:
        - required: [identifier, identifier_type]
          properties:
            identifier:
              type: string
              description: Company identification number (IČO) or other identifier
              example: "12345678"
            identifier_type:
              type: string
              description: Type of identifier. Currently only 'ico' is supported.
              example: "ico"
              enum: [ico]
        - required: [name]
          properties:
            name:
              type: string
              description: Person full name
              example: "Jan Novák"
            birth_date:
              type: string
              format: date
              description: Optional birth date for more precise matching
              example: "1980-01-15"

    InsolvencyCheckResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            identifier:
              type: string
              nullable: true
              description: Company IČO or person RC (rodné číslo)
            identifier_type:
              type: string
              nullable: true
              enum: [ico, rc]
              description: Type of identifier (ico for company, rc for person)
            name:
              type: string
              nullable: true
              description: Person name (when checking by name instead of identifier)
            found:
              type: boolean
              description: Whether any insolvency records were found
            score_delta:
              type: integer
              description: Risk score impact (0-100+)
            reason_codes:
              type: array
              items:
                $ref: '#/components/schemas/ReasonCode'
            enrichment:
              type: object
              nullable: true
              description: Registry data (only present when found=true)
              properties:
                has_active_insolvency:
                  type: boolean
                  description: Whether there are active insolvency proceedings
                has_bankruptcy:
                  type: boolean
                  description: Whether bankruptcy has been declared
                proceedings_count:
                  type: integer
                  description: Total number of proceedings (active and historical)
                proceedings:
                  type: array
                  description: List of all insolvency proceedings
                  items:
                    type: object
                    properties:
                      case_number:
                        type: string
                        description: Court case number
                      debtor_name:
                        type: string
                        nullable: true
                        description: Name of debtor
                      status:
                        type: string
                        enum: [active, closed, unknown]
                        description: Status of proceeding
                      type:
                        type: string
                        enum: [bankruptcy, debt_relief, reorganization, insolvency, unknown]
                        description: Type of proceeding
                      filed_at:
                        type: string
                        format: date
                        nullable: true
                        description: Date when proceeding was filed
                      court:
                        type: string
                        nullable: true
                        description: Court handling the proceeding
                source:
                  type: string
                  enum: [isir]
                  description: Source registry
        meta:
          $ref: '#/components/schemas/Meta'

    # UBO Check
    UboCheckRequest:
      type: object
      required: [company_identifier, country]
      properties:
        company_identifier:
          type: string
          description: Company identification number (IČO for CZ/SK, KvK for NL, SIREN/SIRET for FR, HRB for DE)
          example: "27074358"
        country:
          type: string
          description: Country code (ISO 3166-1 alpha-2)
          enum: [CZ, SK, NL, FR, DE]
          example: "CZ"
        identifier_type:
          type: string
          description: Type of identifier (optional, auto-detected if not provided)
          enum: [ico, kvk_number, siren, siret, hrb]
          example: "ico"

    UboCheckResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            company_identifier:
              type: string
              description: Company identification number used for lookup
            country:
              type: string
              description: Country code
            ubo_declared:
              type: boolean
              description: Whether UBO information is declared in registry
            ubo_count:
              type: integer
              description: Number of beneficial owners found
            beneficial_owners:
              type: array
              description: List of beneficial owners
              items:
                type: object
                properties:
                  name:
                    type: string
                    description: Full name of beneficial owner
                  ownership_percentage:
                    type: number
                    format: float
                    description: Ownership percentage (0-100)
                  is_pep:
                    type: boolean
                    description: Whether owner is a Politically Exposed Person
                  is_sanctioned:
                    type: boolean
                    description: Whether owner is on sanctions list
                  date_of_birth:
                    type: string
                    format: date
                    nullable: true
                    description: Date of birth (if available)
                  nationality:
                    type: string
                    nullable: true
                    description: Nationality (if available)
            score_delta:
              type: integer
              description: Risk score impact (0-100+)
            reason_codes:
              type: array
              items:
                $ref: '#/components/schemas/ReasonCode'
        meta:
          $ref: '#/components/schemas/Meta'

    # PEP Check
    PepCheckRequest:
      type: object
      properties:
        name:
          type: string
          description: Full name of the individual to screen
          example: "John Doe"
        first_name:
          type: string
          description: First name (more precise than full name)
          example: "John"
        last_name:
          type: string
          description: Last name (more precise than full name)
          example: "Doe"
        birth_date:
          type: string
          format: date
          description: Date of birth (optional, improves match accuracy)
          example: "1980-01-15"
        country:
          type: string
          description: Country/nationality (ISO 3166-1 alpha-2)
          example: "US"

    PepCheckResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            name:
              type: string
              description: Name that was screened
            is_pep:
              type: boolean
              description: Whether the individual is a PEP
            pep_type:
              type: string
              nullable: true
              enum: [active, historical, family_member, close_associate]
              description: Type of PEP status
            matches:
              type: array
              description: List of matching PEP records
              items:
                type: object
                properties:
                  matched_name:
                    type: string
                    description: Name from PEP database
                  country:
                    type: string
                    nullable: true
                    description: Country of the matched PEP
                  position:
                    type: string
                    nullable: true
                    description: Political position held
                  start_date:
                    type: string
                    format: date
                    nullable: true
                    description: Start date of position
                  end_date:
                    type: string
                    format: date
                    nullable: true
                    description: End date of position (null if current)
                  match_confidence:
                    type: number
                    format: float
                    description: Match confidence score (0-1)
            score_delta:
              type: integer
              description: Risk score impact (0-100+)
            reason_codes:
              type: array
              items:
                $ref: '#/components/schemas/ReasonCode'
        meta:
          $ref: '#/components/schemas/Meta'

    # IBAN Check
    IbanCheckRequest:
      type: object
      required:
        - iban
      properties:
        iban:
          type: string
          description: IBAN (International Bank Account Number) to validate
          example: "CZ6508000000192000145399"
        expected_country:
          type: string
          description: Expected country code (ISO 3166-1 alpha-2). If provided, checks if IBAN country matches.
          example: "CZ"
          enum: [CZ, SK, DE, GB, UK, FR, IT, ES, NL, BE, AT, PL, SE, NO, DK, FI]

    IbanCheckResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            iban:
              type: string
              description: Normalized IBAN (uppercase, no spaces)
            valid:
              type: boolean
              description: Whether IBAN format and checksum are valid
            country:
              type: string
              nullable: true
              description: Country code from IBAN (first 2 characters)
            bank_code:
              type: string
              nullable: true
              description: Bank code (for CZ/SK IBANs)
            bank_name:
              type: string
              nullable: true
              description: Bank name (for CZ/SK IBANs with known bank code)
            bic:
              type: string
              nullable: true
              description: BIC/SWIFT code (for CZ/SK IBANs with known bank code)
            score_delta:
              type: integer
              description: Risk score impact (0-100+)
            reason_codes:
              type: array
              items:
                $ref: '#/components/schemas/ReasonCode'
        meta:
          $ref: '#/components/schemas/Meta'

    # Address Check
    AddressCheckRequest:
      type: object
      oneOf:
        - required: [address, country]
          properties:
            address:
              type: string
              description: Full address string
              example: "Václavské náměstí 1, Praha"
            country:
              type: string
              description: |
                Country code (ISO 3166-1 alpha-2). **REQUIRED** - Currently only CZ (RÚIAN) 
                is supported.
              example: "CZ"
              enum: [CZ]
        - required: [street, city, country]
          properties:
            street:
              type: string
            house_number:
              type: string
            city:
              type: string
            postal_code:
              type: string
            district:
              type: string
            country:
              type: string
              description: |
                Country code (ISO 3166-1 alpha-2). **REQUIRED** - Currently only CZ (RÚIAN) 
                is supported.
              example: "CZ"
              enum: [CZ]

    AddressCheckResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            address:
              type: string
            country:
              type: string
            found:
              type: boolean
            score_delta:
              type: integer
            reason_codes:
              type: array
              items:
                $ref: '#/components/schemas/ReasonCode'
            enrichment:
              type: object
              nullable: true
              properties:
                normalized_address:
                  type: string
                address_id:
                  type: string
                street:
                  type: string
                city:
                  type: string
                postal_code:
                  type: string
                gps:
                  type: object
                  properties:
                    latitude:
                      type: number
                    longitude:
                      type: number
                    coordinate_system:
                      type: string
                address_type:
                  type: string
                  enum: [standard, po_box]
                match_quality:
                  type: number
                  format: float
                  minimum: 0
                  maximum: 1
                source:
                  type: string
                  enum: [ruian, ban, bkg, os_places, bag, dawa, crab, lantmateriet, cz, fr, de, gb, nl, dk, be, se]
        meta:
          $ref: '#/components/schemas/Meta'

    # LEI Check
    LeiCheckRequest:
      type: object
      properties:
        lei:
          type: string
          description: |
            Legal Entity Identifier (LEI) - 20-character alphanumeric code.
            Format: 4 characters (LOU) + 14 characters (entity) + 2 characters (checksum)
          example: "5493000J2M89Q7X1D75"
          pattern: "^[A-Z0-9]{20}$"
        name:
          type: string
          description: |
            Company name for search. If provided, performs search by name instead of direct LEI lookup.
            Either `lei` or `name` is required.
          example: "Example Corporation"
        country:
          type: string
          description: Optional country code (ISO 3166-1 alpha-2) to filter search results
          example: "US"

    LeiCheckResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            lei:
              type: string
              nullable: true
              description: LEI code (if found or provided)
            found:
              type: boolean
              description: Whether LEI or company was found
            legal_name:
              type: string
              nullable: true
              description: Legal entity name
            legal_form:
              type: string
              nullable: true
              description: Legal form (e.g., "Corporation", "LLC")
            jurisdiction:
              type: string
              nullable: true
              description: Jurisdiction (country code)
            registration_status:
              type: string
              nullable: true
              description: Registration status (e.g., "ACTIVE", "INACTIVE")
              enum: [ACTIVE, INACTIVE, NULLIFIED, DUPLICATE]
            hq_address:
              type: object
              nullable: true
              description: Headquarters address
              properties:
                street:
                  type: string
                city:
                  type: string
                country:
                  type: string
            score_delta:
              type: integer
              description: Risk score impact (0-100+)
            reason_codes:
              type: array
              items:
                $ref: '#/components/schemas/ReasonCode'
            enrichment:
              type: object
              nullable: true
              properties:
                source:
                  type: string
                  enum: [gleif]
                last_updated:
                  type: string
                  format: date-time
        meta:
          $ref: '#/components/schemas/Meta'

    # VAT Check
    VatCheckRequest:
      type: object
      required:
        - vat_number
      properties:
        vat_number:
          type: string
          description: |
            VAT number (country code + number). Examples: "CZ12345678", "DE123456789", "GB123456789".
            Must start with 2-letter country code (ISO 3166-1 alpha-2).
          example: "CZ12345678"
          pattern: "^[A-Z]{2}[A-Z0-9]{2,12}$"
        expected_name:
          type: string
          description: Optional company name to verify against VAT registry
          example: "Example s.r.o."

    VatCheckResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            vat_number:
              type: string
              description: Normalized VAT number
            valid:
              type: boolean
              description: Whether VAT number is valid
            country_code:
              type: string
              nullable: true
              description: Country code from VAT number
            company_name:
              type: string
              nullable: true
              description: Company name from VAT registry
            address:
              type: string
              nullable: true
              description: Company address from VAT registry
            score_delta:
              type: integer
              description: Risk score impact (0-100+)
            reason_codes:
              type: array
              items:
                $ref: '#/components/schemas/ReasonCode'
            enrichment:
              type: object
              nullable: true
              properties:
                source:
                  type: string
                  enum: [vies]
                validated_at:
                  type: string
                  format: date-time
        meta:
          $ref: '#/components/schemas/Meta'

    # Cases
    CaseListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
              score:
                type: integer
              decision:
                type: string
              created_at:
                type: string
                format: date-time
        meta:
          $ref: '#/components/schemas/Meta'
        pagination:
          $ref: '#/components/schemas/Pagination'
        links:
          type: object

    CaseResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/ScoreData'
        meta:
          $ref: '#/components/schemas/Meta'
        links:
          type: object

    EvidenceResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            case_id:
              type: string
            collected_at:
              type: string
              format: date-time
            evidence:
              type: array
              items:
                type: object
                properties:
                  source:
                    type: string
                  kind:
                    type: string
                  data:
                    type: object
        meta:
          $ref: '#/components/schemas/Meta'

    # ============================================================================
    # Case Feedback
    # ============================================================================
    CaseFeedbackRequest:
      type: object
      required:
        - type
      properties:
        type:
          type: string
          enum: [false_positive, false_negative, correct]
          description: |
            Type of feedback:
            - `false_positive`: Decision was too strict (blocked/reviewed legitimate transaction)
            - `false_negative`: Decision was too lenient (allowed fraudulent transaction)
            - `correct`: Decision was correct
        actual_outcome:
          type: string
          enum: [fraud, legitimate, unknown]
          description: The actual outcome of the transaction (if known)
        notes:
          type: string
          maxLength: 1000
          description: Additional notes or context about the feedback
      example:
        type: false_positive
        actual_outcome: legitimate
        notes: "Customer verified via phone call"

    CaseFeedbackResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            id:
              type: integer
              description: Feedback record ID
            case_id:
              type: string
              format: uuid
              description: Associated case ID
            feedback_type:
              type: string
              enum: [false_positive, false_negative, correct]
            actual_outcome:
              type: string
              enum: [fraud, legitimate, unknown]
              nullable: true
            submitted_at:
              type: string
              format: date-time
        meta:
          $ref: '#/components/schemas/Meta'

    # ============================================================================
    # Resolve
    # ============================================================================
    ResolveRequest:
      type: object
      required:
        - type
        - value
      properties:
        type:
          type: string
          enum: [email, ip, domain, url, company, phone]
          description: Entity type to resolve
        value:
          type: string
          description: Entity value to resolve
        options:
          type: object
          properties:
            redact_pii:
              type: boolean
              default: false
              description: Redact personally identifiable information in response
            include_related:
              type: boolean
              default: false
              description: Include related entities in response
            metadata:
              type: object
              description: Additional metadata to associate with the entity

    ResolveResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            id:
              type: string
              example: ent_abc123
            type:
              type: string
              enum: [email, ip, domain, url, company, phone]
            canonical_value:
              type: string
              description: Normalized canonical form
            original_value:
              type: string
            normalized_value:
              type: string
            fingerprints:
              type: object
              additionalProperties: true
            first_seen_at:
              type: string
              format: date-time
            last_seen_at:
              type: string
              format: date-time
            related_entities:
              type: array
              items:
                $ref: '#/components/schemas/Entity'
        meta:
          $ref: '#/components/schemas/Meta'

    # ============================================================================
    # Phone Check
    # ============================================================================
    PhoneCheckRequest:
      type: object
      required:
        - phone
      properties:
        phone:
          type: string
          description: Phone number in any format
          example: "+1-555-123-4567"
        country:
          type: string
          description: Default country code (ISO 3166-1 alpha-2) for parsing
          example: US
          default: US
        ip:
          type: string
          description: Optional IP address for country mismatch detection

    PhoneCheckResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            phone:
              type: string
            normalized:
              type: string
              description: E.164 formatted phone number
              example: "+15551234567"
            valid:
              type: boolean
            score_delta:
              type: integer
            reason_codes:
              type: array
              items:
                $ref: '#/components/schemas/ReasonCode'
            details:
              type: object
              properties:
                country:
                  type: string
                  example: United States
                country_code:
                  type: string
                  example: US
                national_format:
                  type: string
                  example: "(555) 123-4567"
                type:
                  type: string
                  enum: [mobile, fixed_line, voip, toll_free, premium_rate, unknown]
                carrier:
                  type: string
                geo_name:
                  type: string
                is_voip:
                  type: boolean
                is_virtual:
                  type: boolean
                is_landline:
                  type: boolean
                high_risk_country:
                  type: boolean
                country_mismatch:
                  type: boolean
        meta:
          $ref: '#/components/schemas/Meta'

    # ============================================================================
    # Webhooks
    # ============================================================================
    WebhookEvent:
      type: string
      enum:
        - case.created
        - case.decision_changed
        - entity.risk_changed
        - monitoring.alert
      description: |
        Webhook event types:
        - `case.created` - New case scored
        - `case.decision_changed` - Decision changed via monitoring
        - `entity.risk_changed` - Entity risk level changed
        - `monitoring.alert` - Monitoring subscription triggered

    Webhook:
      type: object
      properties:
        id:
          type: integer
          example: 123
        url:
          type: string
          format: uri
          example: https://your-app.com/webhooks/scorika
        events:
          type: array
          items:
            $ref: '#/components/schemas/WebhookEvent'
        active:
          type: boolean
          default: true
        consecutive_failures:
          type: integer
          description: Number of consecutive delivery failures
        last_delivered_at:
          type: string
          format: date-time
          nullable: true
        deactivated_reason:
          type: string
          nullable: true
          description: Reason if webhook was auto-deactivated
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        secret:
          type: string
          description: HMAC signing secret (only returned on create with generate_secret)

    WebhookListResponse:
      type: object
      properties:
        webhooks:
          type: array
          items:
            $ref: '#/components/schemas/Webhook'

    WebhookResponse:
      type: object
      properties:
        webhook:
          $ref: '#/components/schemas/Webhook'

    WebhookCreateRequest:
      type: object
      required:
        - url
        - events
      properties:
        url:
          type: string
          format: uri
          description: HTTPS URL to receive webhook events
          example: https://your-app.com/webhooks/scorika
        events:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/WebhookEvent'
          description: Events to subscribe to
        active:
          type: boolean
          default: true
        generate_secret:
          type: boolean
          default: false
          description: Generate HMAC signing secret

    WebhookUpdateRequest:
      type: object
      properties:
        url:
          type: string
          format: uri
        events:
          type: array
          items:
            $ref: '#/components/schemas/WebhookEvent'
        active:
          type: boolean

    # ============================================================================
    # Integrations
    # ============================================================================
    IntegrationProvider:
      type: string
      enum: [slack, jira, google_sheets, webhook]
      description: |
        Supported integration providers:
        - `slack` - Slack notifications via incoming webhook
        - `jira` - Jira ticket creation
        - `google_sheets` - Google Sheets export
        - `webhook` - Custom webhook integration

    Integration:
      type: object
      properties:
        provider:
          $ref: '#/components/schemas/IntegrationProvider'
        active:
          type: boolean
        settings:
          type: object
          additionalProperties: true
          description: Provider-specific settings
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time

    IntegrationListResponse:
      type: object
      properties:
        integrations:
          type: array
          items:
            $ref: '#/components/schemas/Integration'

    IntegrationResponse:
      type: object
      properties:
        integration:
          $ref: '#/components/schemas/Integration'

    IntegrationCreateRequest:
      type: object
      required:
        - provider
        - credentials
      properties:
        provider:
          $ref: '#/components/schemas/IntegrationProvider'
        credentials:
          type: string
          description: |
            JSON-encoded credentials. Required fields vary by provider:
            - `slack`: `{"webhook_url": "https://hooks.slack.com/..."}`
            - `jira`: `{"base_url": "...", "email": "...", "api_token": "...", "project_key": "..."}`
            - `google_sheets`: `{"service_account": {...}}`
        active:
          type: boolean
          default: true
        settings:
          type: object
          additionalProperties: true

    IntegrationUpdateRequest:
      type: object
      properties:
        credentials:
          type: string
        active:
          type: boolean
        settings:
          type: object
          additionalProperties: true

    # ============================================================================
    # Analytics
    # ============================================================================
    AnalyticsSummaryResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            total_cases:
              type: integer
              description: Total cases in period
            decisions:
              type: object
              properties:
                allow:
                  type: integer
                review:
                  type: integer
                block:
                  type: integer
            average_score:
              type: number
              format: float
            top_reason_codes:
              type: array
              items:
                type: object
                properties:
                  code:
                    type: string
                  count:
                    type: integer
            daily_volume:
              type: array
              items:
                type: object
                properties:
                  date:
                    type: string
                    format: date
                  count:
                    type: integer
        meta:
          type: object
          properties:
            request_id:
              type: string

    ScoreDistributionResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            buckets:
              type: array
              description: Score distribution buckets
              items:
                type: object
                properties:
                  range:
                    type: string
                    example: "0-9"
                  count:
                    type: integer
                  percentage:
                    type: number
                    format: float
            total_cases:
              type: integer
            period:
              type: object
              properties:
                from:
                  type: string
                  format: date-time
                to:
                  type: string
                  format: date-time
        meta:
          $ref: '#/components/schemas/Meta'

    SignalPerformanceResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            signals:
              type: array
              description: Performance metrics for each signal type
              items:
                type: object
                properties:
                  signal_type:
                    type: string
                    enum: [email, ip, domain, url, phone, velocity, cross_field, order_context]
                  total_checks:
                    type: integer
                  avg_score_impact:
                    type: number
                    format: float
                  hit_rate:
                    type: number
                    format: float
                    description: Percentage of checks that returned non-zero score
                  false_positive_rate:
                    type: number
                    format: float
                    description: Based on feedback data (if available)
        meta:
          $ref: '#/components/schemas/Meta'

    ReasonCodeFrequencyResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            reason_codes:
              type: array
              description: Reason codes sorted by frequency
              items:
                type: object
                properties:
                  code:
                    type: string
                    example: "EMAIL_DISPOSABLE"
                  count:
                    type: integer
                  percentage:
                    type: number
                    format: float
                  avg_score_impact:
                    type: number
                    format: float
                  signal_type:
                    type: string
            total_cases:
              type: integer
        meta:
          $ref: '#/components/schemas/Meta'

    # ============================================================================
    # Errors
    # ============================================================================
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
            message:
              type: string
            details:
              type: array
              items:
                type: object
                properties:
                  field:
                    type: string
                  code:
                    type: string
                  message:
                    type: string
            request_id:
              type: string
            documentation_url:
              type: string

  responses:
    ValidationError:
      description: Validation error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: VALIDATION_ERROR
              message: Invalid request parameters
              details:
                - field: email
                  code: INVALID_FORMAT
                  message: Email must be a valid email address

    AuthenticationError:
      description: Authentication error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: AUTHENTICATION_ERROR
              message: Invalid or missing API key

    NotFoundError:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: NOT_FOUND
              message: Case not found

    RateLimitError:
      description: Rate limit exceeded
      headers:
        X-RateLimit-Limit:
          schema:
            type: integer
        X-RateLimit-Remaining:
          schema:
            type: integer
        X-RateLimit-Reset:
          schema:
            type: integer
        Retry-After:
          schema:
            type: integer
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: RATE_LIMITED
              message: Rate limit exceeded, retry after 60 seconds
