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

# Compare pairs

> Run five-voter Haiku pairwise comparisons on explicit matchups.



## OpenAPI

````yaml openapi/rank-api.json POST /api/v1/pairwise
openapi: 3.1.0
info:
  title: Kettio Rank API
  version: 1.1.0
  description: >-
    Score and rank batches of ad creative assets with Kettio's SSR pipeline,
    then validate selected matchups with a five-voter Haiku Bradley-Terry panel.
servers:
  - url: https://kettio.com
    description: Production
security:
  - bearerAuth: []
paths:
  /api/v1/pairwise:
    post:
      summary: Run five-voter Haiku pairwise comparisons
      description: >-
        Evaluates 1 to 10 explicit creative pairs with five blinded,
        presentation-balanced Claude Haiku votes per pair. Every vote and model
        response is returned for auditability.
      operationId: compareCreativePairs
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PairwiseRequest'
            example:
              pairs:
                - pair_id: creative-a-vs-b
                  a:
                    id: creative-a
                    image_url: https://cdn.example.com/ad-a.png
                  b:
                    id: creative-b
                    image_url: https://cdn.example.com/ad-b.png
              audience:
                name: GLP-1 shoppers
                description: >-
                  Women considering GLP-1 support who need credible purchase
                  proof
              goal: purchase-intent
              platform: facebook
      responses:
        '200':
          description: Completed pairwise panels and individual votes.
          headers:
            X-Request-Id:
              schema:
                type: string
                format: uuid
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PairwiseResponse'
        '400':
          $ref: '#/components/responses/Error'
        '401':
          $ref: '#/components/responses/Error'
        '402':
          $ref: '#/components/responses/Error'
        '404':
          $ref: '#/components/responses/Error'
        '422':
          $ref: '#/components/responses/Error'
        '429':
          $ref: '#/components/responses/RateLimitError'
        '500':
          $ref: '#/components/responses/Error'
        '503':
          $ref: '#/components/responses/Error'
      security:
        - bearerAuth: []
components:
  schemas:
    PairwiseRequest:
      type: object
      additionalProperties: false
      required:
        - pairs
      properties:
        pairs:
          type: array
          minItems: 1
          maxItems: 10
          items:
            $ref: '#/components/schemas/PairwisePair'
        audience:
          $ref: '#/components/schemas/InlineAudience'
        audience_id:
          type: string
        goal:
          type: string
          default: purchase-intent
        platform:
          type: string
        campaign_type:
          type: string
    PairwiseResponse:
      type: object
      required:
        - request_id
        - pairs
        - summary
      properties:
        request_id:
          type: string
          format: uuid
        pairs:
          type: array
          items:
            $ref: '#/components/schemas/PairwiseResult'
        summary:
          $ref: '#/components/schemas/PairwiseSummary'
    PairwisePair:
      type: object
      additionalProperties: false
      required:
        - pair_id
        - a
        - b
      properties:
        pair_id:
          type: string
        a:
          $ref: '#/components/schemas/PairwiseAsset'
        b:
          $ref: '#/components/schemas/PairwiseAsset'
    InlineAudience:
      type: object
      additionalProperties: false
      required:
        - name
      properties:
        name:
          type: string
        description:
          type: string
        demographics:
          type: object
          additionalProperties: true
          properties:
            ageRange:
              type: string
            incomeLevel:
              type: string
            adSkepticism:
              type: string
            trustBaseline:
              type: string
            priceSensitivity:
              type: string
            categoryFamiliarity:
              type: string
            shoppingIntent:
              type: string
            urgency:
              type: string
            brandFamiliarity:
              type: string
            platformFatigue:
              type: string
    PairwiseResult:
      type: object
      required:
        - pairId
        - aId
        - bId
        - status
        - votes
      properties:
        pairId:
          type: string
        aId:
          type: string
        bId:
          type: string
        status:
          type: string
          enum:
            - done
            - partial
            - error
        winnerId:
          type: string
        votesFor:
          type: integer
        votesTotal:
          type: integer
        winRate:
          type: number
        consistency:
          type: number
        votes:
          type: array
          items:
            $ref: '#/components/schemas/PairwiseVote'
        error:
          type: string
    PairwiseSummary:
      type: object
      properties:
        goal:
          type: string
        platform:
          type:
            - string
            - 'null'
        audience:
          type: string
        model:
          type: string
        panel_size:
          type: integer
          const: 5
        pairs_requested:
          type: integer
        pairs_completed:
          type: integer
        pairs_failed:
          type: integer
        valid_votes:
          type: integer
        pairwise_evaluations:
          type: integer
        credits_used:
          type: integer
        credits_remaining:
          type:
            - integer
            - 'null'
    ErrorResponse:
      type: object
      required:
        - error
      properties:
        error:
          type: string
        field:
          type: string
    PairwiseAsset:
      type: object
      additionalProperties: false
      required:
        - id
        - image_url
      properties:
        id:
          type: string
        image_url:
          type: string
    PairwiseVote:
      type: object
      required:
        - voterId
        - order
        - winnerId
        - loserId
        - response
      properties:
        voterId:
          type: string
        order:
          type: string
          enum:
            - ab
            - ba
        winnerId:
          type: string
        loserId:
          type: string
        response:
          type: string
  responses:
    Error:
      description: Error response.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    RateLimitError:
      description: Rate limit response.
      headers:
        Retry-After:
          schema:
            type: string
      content:
        application/json:
          schema:
            allOf:
              - $ref: '#/components/schemas/ErrorResponse'
              - type: object
                properties:
                  retryAfter:
                    type: integer
                  resetAt:
                    type: integer
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: 'Kettio API key, for example Authorization: Bearer agk_live_xxx.'

````