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

# Validate Policies (Batch)

> Runs data consistency checks against multiple policies in a single
request and returns paginated results. This is a read-only
diagnostic endpoint — no data is modified.

Three modes control which policies are validated (mutually
exclusive):

1. **Explicit pairs** (`policyVersions`) — validate specific
   policy/version combinations. Pagination parameters are ignored.
2. **Time travel** (`timeTravelBackToDate`) — validate the latest
   version of each policy as of a historical point in time.
   Paginated via `limit`/`offset`.
3. **Default** (neither parameter) — validate the latest version of
   all policies in the company. Paginated via `limit`/`offset`.

The same eight checks from the single-policy validation endpoint
are available. Use the `checks` parameter to select a subset.

### Available checks

| Check | Scope | What it validates |
|-------|-------|-------------------|
| `contiguity` | version | Segments form a contiguous date range with no gaps or overlaps |
| `fullTermInvariance` | version | Billing and policy metadata fields are constant across all segments in a version |
| `hashCorrectness` | version | Stored segment hash matches the computed hash of the segment data |
| `noDuplicateSegments` | version | No adjacent segments have identical hashes |
| `transactionSegmentExistence` | version | At least one segment exists for the version |
| `versionSequentiality` | policy | Versions are sequential starting from 1 with no gaps |
| `cancelEarnedPremium` | policy | Cancel transaction premium matches earned premium through the cancellation date |
| `cancelReinstatePremium` | policy | Reinstate transaction premium matches the pre-cancel version premium |

**Required permission:** `company.policy:read`




## OpenAPI

````yaml /openapi/generated-external-api.yaml get /api/v1/external/companies/{companyId}/policies/validate
openapi: 3.0.3
info:
  title: AI Insurance External API
  description: External API for AI Insurance platform
  version: 1.0.0
  contact:
    email: support@aiinsurance.io
servers:
  - url: https://app.aiinsurance.io
    description: Production
security:
  - ApiKeyAuth: []
paths:
  /api/v1/external/companies/{companyId}/policies/validate:
    get:
      tags:
        - Field Model Policy Validation
      summary: Validate Policies (Batch)
      description: >
        Runs data consistency checks against multiple policies in a single

        request and returns paginated results. This is a read-only

        diagnostic endpoint — no data is modified.


        Three modes control which policies are validated (mutually

        exclusive):


        1. **Explicit pairs** (`policyVersions`) — validate specific
           policy/version combinations. Pagination parameters are ignored.
        2. **Time travel** (`timeTravelBackToDate`) — validate the latest
           version of each policy as of a historical point in time.
           Paginated via `limit`/`offset`.
        3. **Default** (neither parameter) — validate the latest version of
           all policies in the company. Paginated via `limit`/`offset`.

        The same eight checks from the single-policy validation endpoint

        are available. Use the `checks` parameter to select a subset.


        ### Available checks


        | Check | Scope | What it validates |

        |-------|-------|-------------------|

        | `contiguity` | version | Segments form a contiguous date range with no
        gaps or overlaps |

        | `fullTermInvariance` | version | Billing and policy metadata fields
        are constant across all segments in a version |

        | `hashCorrectness` | version | Stored segment hash matches the computed
        hash of the segment data |

        | `noDuplicateSegments` | version | No adjacent segments have identical
        hashes |

        | `transactionSegmentExistence` | version | At least one segment exists
        for the version |

        | `versionSequentiality` | policy | Versions are sequential starting
        from 1 with no gaps |

        | `cancelEarnedPremium` | policy | Cancel transaction premium matches
        earned premium through the cancellation date |

        | `cancelReinstatePremium` | policy | Reinstate transaction premium
        matches the pre-cancel version premium |


        **Required permission:** `company.policy:read`
      operationId: validatePolicies
      parameters:
        - $ref: '#/components/parameters/companyId'
        - name: policyVersions
          in: query
          schema:
            type: string
          description: |
            Comma-separated list of `policyId:version` pairs to validate.
            Example: `pol-abc:1,pol-def:2,pol-abc:3`.

            Each pair must have a non-empty policy ID and a positive integer
            version. Multiple versions of the same policy are allowed.

            When provided, `limit` and `offset` are ignored — all requested
            pairs are returned.

            Mutually exclusive with `timeTravelBackToDate`.
        - name: timeTravelBackToDate
          in: query
          schema:
            type: string
            format: date-time
          description: |
            ISO 8601 timestamp. Validates the latest version of each policy
            that has at least one transaction created on or before this
            date. Policies with no transactions by this date are excluded.

            Mutually exclusive with `policyVersions`.
        - name: checks
          in: query
          schema:
            type: string
          description: |
            Comma-separated list of check names to run (e.g.,
            `contiguity,hashCorrectness`). If omitted, all checks run.
            Unrecognized check names are silently ignored. If all provided
            names are unrecognized, all checks run (same as omitting the
            parameter). Check names are case-sensitive.
        - name: limit
          in: query
          required: true
          schema:
            type: integer
            minimum: 1
          description: |
            Maximum number of policies to return per page. Required for all
            requests, though it is ignored when `policyVersions` is
            provided.
        - name: offset
          in: query
          schema:
            type: integer
            minimum: 0
            default: 0
          description: |
            Number of policies to skip before returning results. Defaults
            to 0. Ignored when `policyVersions` is provided.
      responses:
        '200':
          description: Paginated validation results
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PolicyValidationListResponse'
              examples:
                defaultMode:
                  summary: Default mode — latest versions, paginated
                  value:
                    items:
                      - policyId: 550e8400-e29b-41d4-a716-446655440001
                        validatedAt: '2026-04-14T18:30:00.000Z'
                        summary:
                          totalChecks: 8
                          passed: 8
                          failed: 0
                          skipped: 0
                        results:
                          - check: contiguity
                            status: pass
                            scope: version:1
                          - check: versionSequentiality
                            status: pass
                            scope: policy
                      - policyId: 550e8400-e29b-41d4-a716-446655440002
                        validatedAt: '2026-04-14T18:30:00.000Z'
                        summary:
                          totalChecks: 13
                          passed: 12
                          failed: 1
                          skipped: 0
                        results:
                          - check: hashCorrectness
                            status: fail
                            scope: version:2
                            message: >-
                              Segment 0 hash mismatch: stored a1b2c3d4e5f6,
                              computed f6e5d4c3b2a1
                          - check: versionSequentiality
                            status: pass
                            scope: policy
                    totalCount: 47
                explicitPairs:
                  summary: Explicit policyVersions mode
                  value:
                    items:
                      - policyId: 550e8400-e29b-41d4-a716-446655440001
                        validatedAt: '2026-04-14T18:30:00.000Z'
                        summary:
                          totalChecks: 8
                          passed: 8
                          failed: 0
                          skipped: 0
                        results:
                          - check: contiguity
                            status: pass
                            scope: version:1
                          - check: versionSequentiality
                            status: pass
                            scope: policy
                    totalCount: 1
        '400':
          description: Invalid request parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                mutuallyExclusive:
                  summary: Both targeting modes provided
                  value:
                    error:
                      code: VALIDATION_ERROR
                      message: >-
                        policyVersions and timeTravelBackToDate are mutually
                        exclusive. Provide one or neither.
                invalidPair:
                  summary: Malformed policyVersions pair
                  value:
                    error:
                      code: VALIDATION_ERROR
                      message: >-
                        Invalid policyVersions format: "policy123". Expected
                        "policyId:version".
                missingLimit:
                  summary: Missing required limit parameter
                  value:
                    error:
                      code: VALIDATION_ERROR
                      message: 'limit: must be an integer'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
components:
  parameters:
    companyId:
      name: companyId
      in: path
      required: true
      schema:
        type: string
        format: uuid
      description: Company identifier
  schemas:
    PolicyValidationListResponse:
      type: object
      description: |
        Paginated list of validation results for multiple policies.
      required:
        - items
        - totalCount
      properties:
        items:
          type: array
          description: Validation results for each policy in this page
          items:
            $ref: '#/components/schemas/PolicyValidationResponse'
        totalCount:
          type: integer
          description: >
            Total number of policies matching the query (before pagination). Use
            with `limit` and `offset` to page through results.
          example: 47
    ErrorResponse:
      type: object
      description: Standard error response for all external API endpoints
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              description: Machine-readable error code
              example: VALIDATION_ERROR
            message:
              type: string
              description: Human-readable error message
              example: 'submissionId: Required field is missing'
            details:
              type: array
              description: Additional details for validation errors (field-level errors)
              items:
                type: object
                properties:
                  field:
                    type: string
                    description: The field that caused the error
                    example: submissionId
                  message:
                    type: string
                    description: Description of the field error
                    example: Required field is missing
    PolicyValidationResponse:
      type: object
      description: >
        Validation results for a single policy, including a summary of
        pass/fail/skip counts and the individual check results.
      required:
        - policyId
        - validatedAt
        - summary
        - results
      properties:
        policyId:
          type: string
          format: uuid
          description: The policy that was validated
        validatedAt:
          type: string
          format: date-time
          description: ISO 8601 timestamp of when the validation was performed
        summary:
          $ref: '#/components/schemas/PolicyValidationSummary'
        results:
          type: array
          description: >
            Individual check results. Contains one entry per check per scope
            (version-scoped checks produce one result per version).
          items:
            $ref: '#/components/schemas/PolicyValidationCheckResult'
    PolicyValidationSummary:
      type: object
      description: >
        Aggregate counts of check results for a single policy. A policy with
        multiple versions will have more results than the number of check types,
        because version-scoped checks run once per version.
      required:
        - totalChecks
        - passed
        - failed
        - skipped
      properties:
        totalChecks:
          type: integer
          description: >
            Total number of check results (passed + failed + skipped). This can
            exceed 8 (the number of check types) because version-scoped checks
            run once per version.
          example: 18
        passed:
          type: integer
          description: Number of checks that passed
          example: 17
        failed:
          type: integer
          description: Number of checks that failed
          example: 1
        skipped:
          type: integer
          description: >
            Number of checks that were skipped because the `checks` query
            parameter excluded them
          example: 0
    PolicyValidationCheckResult:
      type: object
      description: >
        Result of a single validation check against a policy or policy version.
        Each check evaluates a specific data consistency invariant.
      required:
        - check
        - status
        - scope
      properties:
        check:
          type: string
          description: >
            Name of the validation check. See the `checks` query parameter for
            the full list of available check names.
          enum:
            - cancelEarnedPremium
            - cancelReinstatePremium
            - contiguity
            - fullTermInvariance
            - hashCorrectness
            - noDuplicateSegments
            - transactionSegmentExistence
            - versionSequentiality
          example: contiguity
        status:
          type: string
          description: >
            Outcome of the check: `pass` if the invariant holds, `fail` if a
            violation was detected, or `skipped` if the check was excluded by
            the `checks` filter.
          enum:
            - pass
            - fail
            - skipped
          example: pass
        scope:
          type: string
          description: >
            Context in which the check ran. Version-scoped checks use the format
            `version:N` (e.g., `version:1`). Policy-scoped checks use `policy`.
          example: version:1
        message:
          type: string
          description: |
            Explanation of the failure. Only present when `status` is `fail`.
          example: >-
            Segments for version 2 are not contiguous: gap between 2025-06-01
            and 2025-07-01
  responses:
    Unauthorized:
      description: Unauthorized - Invalid or missing API key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            missingApiKey:
              summary: Missing API key
              value:
                error:
                  code: UNAUTHORIZED
                  message: Authorization header is required
            bearerTokenNotAllowed:
              summary: Bearer token used instead of API key
              value:
                error:
                  code: UNAUTHORIZED
                  message: External API endpoints require API key authentication
    Forbidden:
      description: Forbidden - Insufficient permissions
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            insufficientPermissions:
              summary: Insufficient permissions
              value:
                error:
                  code: FORBIDDEN
                  message: Insufficient permissions to perform this action
    InternalServerError:
      description: Internal Server Error - Unexpected error occurred
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            internalError:
              summary: Unexpected server error
              value:
                error:
                  code: INTERNAL_ERROR
                  message: An unexpected error occurred. Please try again later.
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: Authorization
      description: >-
        API key authentication. Include your API key in the Authorization
        header.

````