Developer API

Ranking API for Agents

Score and rank ad creatives programmatically. Send image URLs or data:image payloads, include copy context when you have live ad text, and get back ranked results with copy lift, refinement outcomes, rationales, and confidence levels.

Overview

The Ranking API evaluates ad creatives using Kettio's SSR (Semantic Similarity Rating) pipeline — the same scoring engine behind the Kettio dashboard. Each asset is scored 1–5 against a target audience persona, with a written rationale explaining the score.

Batch ranking

Up to 20 assets per request

Full ad package

Image plus optional copy context

Evaluation billing

Only successful score evaluations are charged

┌───────────────────────┐
│  Agent / CLI / Script │
└──────────┬────────────┘
           │  POST /api/v1/rank
           │  { assets[], audience, goal, platform }
           ▼
┌───────────────────────┐
│    Kettio API         │
│  Auth + Rate Limit    │
│  Credit Check         │
└──────────┬────────────┘
           │  Parallel evaluation (4 concurrent)
           ▼
┌───────────────────────┐
│   SSR Pipeline        │
│  Gemini → Rationale   │
│  Embed → Score (1-5)  │
└──────────┬────────────┘
           │  Sorted results
           ▼
┌───────────────────────┐
│   JSON Response       │
│  ranked[], errors[],  │
│  copy lift + credits  │
└───────────────────────┘

API Key

Generate an API key below. Keys start with agk_live_ and are sent via the Authorization header.

Quickstart

Rank three ad creatives with a single curl command:

curl -X POST https://kettio.com/api/v1/rank \
  -H "Authorization: Bearer agk_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "assets": [
      {
        "url": "https://example.com/ad-a.png",
        "id": "ad-a",
        "copy_context": {
          "pageName": "Pawbox",
          "adBody": "First box free for new subscribers.",
          "adHeadline": "Healthy treats your dog will actually want"
        }
      },
      { "url": "https://example.com/ad-b.png", "id": "ad-b" },
      { "url": "https://example.com/ad-c.png", "id": "ad-c" }
    ],
    "audience": {
      "name": "Budget-conscious parents",
      "description": "Parents aged 30-44 who compare prices",
      "demographics": { "ageRange": "35-44", "priceSensitivity": "high" }
    },
    "goal": "purchase-intent",
    "platform": "meta",
    "refine_close_pairs": true
  }'

For Computer-Use Agents

The API returns structured JSON — no browser interaction needed. Agents can parse the ranked[] array directly, read rationale strings for reasoning, and use score values to make decisions.

API Reference

Endpoint

POST/api/v1/rank

Score and rank up to 20 image assets against a target audience persona. Assets with copy context are evaluated as full ad packages and also receive image-only ablations for copy lift.

Requires API key60 scoring evals/minCopy context uses up to 2 evals120s max timeout

Request Body

assets{ url, id?, asset_type?, copy_context? }[]required
Array of 1–20 objects. url is required and must be an https:// URL or data:image/ URI. id is optional for correlation.
audienceobject
Inline audience: name (required), description, demographics. Mutually exclusive with audience_id.
audience_idstring
ID of a saved audience from your Kettio account. Mutually exclusive with audience.
goalstringDefault: purchase-intent
Evaluation goal. See Goals table.
asset_typestringDefault: Social Media Post
Asset type for context framing. See Asset Types table.
platformstring
Optional delivery context such as meta, instagram, facebook, tiktok, linkedin, or google.
campaign_typestring
Optional campaign or placement alias used when platform is omitted.
refine_close_pairsbooleanDefault: true
Runs pairwise refinement for near-tied successful assets. Set to false for raw SSR-only ordering.

Copy Context

Add copy_context when you know the live ad copy. Kettio scores that asset as a full ad package, then runs a separate image-only ablation so the response can report image_only_score and copy_lift.

{
  "url": "https://cdn.example.com/ad-a.png",
  "id": "ad-a",
  "copy_context": {
    "pageName": "Pawbox",
    "adBody": "First box free for new subscribers. Fresh treats picked for picky dogs.",
    "adHeadline": "Healthy treats your dog will actually want",
    "adCaption": "Cancel anytime",
    "adDescription": "Subscription dog treats delivered monthly"
  }
}
Accepted AliasNormalized Field
businessName, displayNamepageName
primaryText, body, copyadBody
headlineadHeadline
captionadCaption
descriptionadDescription

Response

{
  "request_id": "a1b2c3d4-...",
  "ranked": [
    {
      "rank": 1,
      "asset_url": "https://example.com/ad-a.png",
      "asset_id": "ad-a",
      "score": 4.23,
      "score_before_refine": 4.23,
      "score_layer": "full-ad-package",
      "asset_type": "Social Media Post",
      "copy_context_included": true,
      "image_only_score": 3.81,
      "copy_lift": 0.42,
      "rationale": "This ad immediately communicates value...",
      "product_read": "A promotional banner showing a family...",
      "panel_outcome": null,
      "confidence": "high",
      "confidence_details": {
        "entropy": 0.42,
        "top_margin": 0.31,
        "sample_std_dev": 0.08
      },
      "details": {
        "probabilities": [0.02, 0.06, 0.18, 0.46, 0.28],
        "similarities": [0.12, 0.21, 0.35, 0.47, 0.41]
      }
    },
    {
      "rank": 2,
      "asset_url": "https://example.com/ad-b.png",
      "asset_id": "ad-b",
      "score": 3.15,
      "score_before_refine": 3.15,
      "score_layer": "image-only",
      "asset_type": "Social Media Post",
      "copy_context_included": false,
      "image_only_score": 3.15,
      "copy_lift": 0,
      "rationale": "The creative lacks a clear value proposition...",
      "confidence": "medium",
      "panel_outcome": null
    }
  ],
  "errors": [],
  "summary": {
    "goal": "purchase-intent",
    "asset_type": "Social Media Post",
    "audience": "Budget-conscious parents",
    "assets_ranked": 2,
    "assets_failed": 0,
    "scoring_evaluations": 3,
    "close_pair_refinement": {
      "enabled": true,
      "pairs_evaluated": 0,
      "results": []
    },
    "credits_used": 3,
    "credits_remaining": 48
  }
}
ranked[]array
Sorted by final score descending. Each entry has rank, score, score_before_refine, score_layer, copy lift fields, rationale, confidence, and the original URL/ID.
errors[]array
Assets that failed evaluation. Credits are not charged for failed scoring evaluations.
summaryobject
Totals: assets_ranked, assets_failed, scoring_evaluations, close_pair_refinement, credits_used, credits_remaining.

Batch Uploads & Refinement

Send up to 20 assets in one request. Kettio evaluates assets concurrently and returns one sorted list. When refine_close_pairs is enabled, near-tied successful assets can get a pairwise panel check. If the panel disagrees with the initial SSR order, the final score is nudged and the affected assets include panel_outcome.

score_before_refinenumber
The raw SSR score before close-pair adjustment.
panel_outcomeobject | null
Pairwise winner/loser, whether the result flipped the original order, votes, and consistency.
summary.close_pair_refinementobject
Whether refinement was enabled, how many pairs were evaluated, and the raw pair results.

Billing & Limits

Rate limits and credits are counted by successful scoring evaluations, not just uploaded asset count. Image-only assets usually use 1 evaluation. Assets with copy context can use 2 evaluations because Kettio also runs an image-only ablation.

LimitValue
Maximum assets20 per request
ConcurrencyUp to 4 assets evaluated at a time inside the request
Rate limit60 scoring evaluations per minute per API key
Image-only billing1 successful scoring evaluation
Copy-context billingUp to 2 successful scoring evaluations
Refinement billingReported separately; current credit/rate accounting is based on scoring evaluations

Error Codes

StatusMeaning
401Missing or invalid API key
402Insufficient credits for this batch
404audience_id not found or not owned by you
422Validation error (bad request body)
429Rate limited — check Retry-After header

Reference

Configuration

Evaluation Goals

The goal parameter determines what dimension your assets are scored on. purchase-intent is the default and highest accuracy.

GoalBest For
purchase-intentdefaultProduct ads, DTC creatives
click-through-rateAds optimized for clicks
conversion-potentialLanding pages, lead gen
trustworthinessAny ad — perceived trust
scroll-stoppingFeed-based social ads
engagementSocial content, community
brand-recognitionBrand awareness
emotional-resonanceStorytelling creative
open-rateEmail headers
logo-professionalismLogo evaluation
logo-versatilityLogo evaluation
product-page-conversionProduct detail pages
landing-page-conversionLanding pages

Asset Types

The asset_type sets the context framing — it changes the system prompt so the simulated persona evaluates the asset in the right mental context.

Asset TypeContext
Social Media PostdefaultFeed-based content
AdvertisementPaid ads
Product PhotoProduct imagery
Email HeaderEmail marketing
Landing Page HeroHero sections
LogoBrand marks
Website BannerDisplay ads
IllustrationCustom art

Demographics Fields

Optional fields on audience.demographics. These shape the simulated persona's attitude and behavior. All fields are optional — sensible defaults are applied automatically.

FieldAccepted Values
ageRange18-24, 25-34, 35-44, 45-54, 55-64, 65+
incomeLevelunder-25k, 25k-50k, 50k-75k, 75k-100k, 100k-150k, 150k+
adSkepticismvery-low, low, moderate, high, very-high
trustBaselinevery-low, low, moderate, high, very-high
priceSensitivityvery-low, low, moderate, high, very-high
categoryFamiliaritynone, casual, knowledgeable, expert
shoppingIntentbrowsing, researching, comparing, ready-to-buy
urgencynone, low, moderate, high, urgent
brandFamiliarityunaware, heard-of, familiar, loyal
platformFatiguelow, medium, high, very-high