> ## 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.

# Pairwise API

> Run a five-voter blinded panel on explicit head-to-head matchups.

`POST /api/v1/pairwise` compares creatives directly instead of scoring them independently. Use
it when you already know which matchups need a decision.

Every pair gets exactly five blinded Claude Haiku votes, with presentation order balanced 3/2 to
control for position bias. The response returns every vote and every raw response, so the result
is auditable rather than a black-box verdict.

<Note>
  This is **not** the same mechanism as `refine_close_pairs` on the Rank API. Refinement is
  automatic and fires only on near-ties that Kettio detects. The Pairwise API runs a full panel on
  exactly the pairs you name, whatever their scores.
</Note>

## Request

```bash theme={null}
curl -X POST https://kettio.com/api/v1/pairwise \
  -H "Authorization: Bearer agk_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "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"
  }'
```

Send 1 to 10 pairs per request. The endpoint uses the same inline-or-saved audience contract as
`/api/v1/rank`, so an `audience_id` works here too.

Full schemas are in the [Pairwise API reference](/api-reference/pairwise).

## Outcomes and billing

| Result                     | Billed                            |
| -------------------------- | --------------------------------- |
| Completed five-voter panel | 1 `pairwise_evaluation`, 1 credit |
| `partial`                  | Not billed                        |
| `error`                    | Not billed                        |

Pairwise usage is reported separately from Rank API usage. The Rank API's rate limit and credit
accounting are based on scoring evaluations; `pairwise_evaluations` are counted on their own.

## Use it as a controlled cascade

The reason to keep the two endpoints separate is that it lets you run a clean experiment. The
pattern:

<Steps>
  <Step title="Rank with refinement off">
    Call `/api/v1/rank` with `refine_close_pairs: false` so the SSR scores stay frozen.
  </Step>

  <Step title="Pick the comparisons before you look at outcomes">
    Choose which pairs to send to `/api/v1/pairwise` — and choose your consensus threshold — up
    front, not after seeing results.
  </Step>

  <Step title="Override only on consensus">
    Replace the SSR winner only when the panel clears the threshold you preregistered.
  </Step>
</Steps>

<Warning>
  Picking the pairs or the threshold *after* reading outcomes turns this into a post-hoc fit. If
  you intend to report the result as evidence, fix both before the first outcome lands.
</Warning>

## Choosing between the two

<CardGroup cols={2}>
  <Card title="Use Rank" icon="list-ol">
    You have a batch and need an ordering. You do not know in advance which comparisons matter.
  </Card>

  <Card title="Use Pairwise" icon="code-compare">
    You have two specific creatives and need to know which one wins, with the votes on record.
  </Card>
</CardGroup>
