AimRank Votes API
The Votes API from AimRank — 6 operation(s) for votes.
The Votes API from AimRank — 6 operation(s) for votes.
Every API here is available over the APIs.io API and to AI agents over MCP.
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
find_apisBrowse and filter every API in the catalog.get_api_artifactsOne API's artifacts, grouped by type.get_openapiThe primary OpenAPI for this API.find_similar_apisAPIs that look like this one.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.curl "https://apis.io/api/v1/apis/aimrank-io:aimrank-io-votes-api"
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: AimRank Votes API
description: Ranking-as-a-Service API — Turn binary comparisons into calibrated rankings with Glicko-2, Bradley-Terry, TrueSkill, and cross-domain transfer learning. Includes webhooks, API keys, RLHF exports, and embeddable widgets.
version: 4.12.0
tags:
- name: Votes
paths:
/api/v1/votes:
post:
tags:
- Votes
summary: Submit Vote
description: 'Submit a pairwise comparison vote.
Uses atomic transaction with row-level locking to ensure:
- All database changes succeed or fail together
- Concurrent votes on same entities don''t cause race conditions
Rate limited to prevent abuse (default: 100/minute).
Tier-cap enforcement (PLATFORM_AUDIT M17): authenticated users have a
monthly-vote limit per their subscription plan. Anonymous voters are
rate-limited at the IP layer (no per-user cap to enforce).
Raises:
HTTPException 403: Monthly vote limit reached for the user''s tier
HTTPException 404: Ranking or entity not found
HTTPException 400: Invalid winner_id
HTTPException 409: Conflict due to concurrent modification
HTTPException 500: Internal server error'
operationId: submit_vote_api_v1_votes_post
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/api__routes__votes__VoteCreate'
required: true
responses:
'201':
description: Successful Response
content:
application/json:
schema: {}
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/v1/votes/binary:
post:
tags:
- Votes
summary: Cast Binary Vote
description: 'Cast a binary label (True/False) on a single entity.
Mirrors POST /votes for the pairwise primitive. Used for tasks
where pairing items is artificial: moderation, fact-checking,
dataset cleanup, "is this safe?" / "is this on-brand?". The
ranking must have `vote_type=''binary''`.
Stored shape: outcome=''binary'', label=True/False, entity_a_id is
the labelled item, entity_b_id is NULL, winner_id is NULL.
Aggregation lives in GET /rankings/{id}/labels — wins/losses on
Entity stay zero for binary rankings; the canonical signal is the
label distribution per entity.'
operationId: cast_binary_vote_api_v1_votes_binary_post
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/BinaryVoteCreate'
required: true
responses:
'201':
description: Successful Response
content:
application/json:
schema: {}
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/v1/votes/bulk:
post:
tags:
- Votes
summary: Bulk Import Votes
description: 'Bulk-import votes for a ranking.
Designed for the AI-lab pilot use case: a buyer arrives with a
pre-collected dataset of 10K preference pairs (DPO format, Anthropic
HH format, OpenAssistant pairs) and needs to land them on AimRank
so the rating math + κ + competition report run against their data.
Hitting POST /votes one at a time at the 100/min rate limit takes
~100 minutes; this endpoint takes seconds.
Auth: API key OR JWT — caller must own the ranking. Anonymous
callers cannot bulk-import (fraud-control: a bulk endpoint without
auth is a brigading vector).
Limits: 1000 votes per call. Larger imports must chunk client-side.
No rate-limit decorator — the per-call cap IS the rate-limit.
Partial success is normal: invalid items are returned in `errors`
so the caller can re-submit just the failures.'
operationId: bulk_import_votes_api_v1_votes_bulk_post
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/BulkVoteRequest'
required: true
responses:
'201':
description: Successful Response
content:
application/json:
schema: {}
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
security:
- APIKeyHeader: []
/api/v1/votes/matchup/{ranking_id}:
get:
tags:
- Votes
summary: Get Matchup
description: 'Get a matchup for voting.
Strategies:
- adaptive: Auto-selects best strategy based on ranking maturity (RECOMMENDED)
- swiss: Swiss-system tournament pairing (fast convergence, rematch avoidance)
- random: Random pair selection
- balanced: Prefer evenly-matched pairs (better for accuracy)
- uncertainty: Prefer high-uncertainty entities (reduces RD faster)
- explore: AI-driven discovery - find novel matchups based on embeddings
- information_gain: Maximize expected information gain per vote (proper entropy formula)'
operationId: get_matchup_api_v1_votes_matchup__ranking_id__get
parameters:
- name: ranking_id
in: path
required: true
schema:
type: string
title: Ranking Id
- name: strategy
in: query
required: false
schema:
enum:
- adaptive
- swiss
- random
- balanced
- uncertainty
- explore
- information_gain
type: string
default: adaptive
title: Strategy
- name: pin
in: query
required: false
schema:
anyOf:
- type: string
- type: 'null'
description: Serve exactly this pair, as 'entity_a_id,entity_b_id'. Used by shared challenge links so the recipient answers the SAME question ('I picked A over B — do you agree?'). Falls back to the normal strategy when either entity is missing, inactive, or not in this ranking — a stale link should still yield a votable pair.
title: Pin
description: Serve exactly this pair, as 'entity_a_id,entity_b_id'. Used by shared challenge links so the recipient answers the SAME question ('I picked A over B — do you agree?'). Falls back to the normal strategy when either entity is missing, inactive, or not in this ranking — a stale link should still yield a votable pair.
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/MatchupResponse'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/v1/votes/stats:
get:
tags:
- Votes
summary: Get Vote Stats
description: Get voting statistics for current user.
operationId: get_vote_stats_api_v1_votes_stats_get
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/VoteStatsResponse'
/api/v1/votes/history/{ranking_id}:
get:
tags:
- Votes
summary: Get Vote History
description: Get recent votes for a ranking.
operationId: get_vote_history_api_v1_votes_history__ranking_id__get
parameters:
- name: ranking_id
in: path
required: true
schema:
type: string
title: Ranking Id
- name: limit
in: query
required: false
schema:
type: integer
maximum: 100
minimum: 1
default: 20
title: Limit
responses:
'200':
description: Successful Response
content:
application/json:
schema: {}
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
components:
schemas:
HTTPValidationError:
properties:
detail:
items:
$ref: '#/components/schemas/ValidationError'
type: array
title: Detail
type: object
title: HTTPValidationError
BulkVoteRequest:
properties:
ranking_id:
type: string
maxLength: 36
minLength: 36
title: Ranking Id
votes:
items:
$ref: '#/components/schemas/BulkVoteItem'
type: array
maxItems: 1000
minItems: 1
title: Votes
description: Up to 1000 votes per call
type: object
required:
- ranking_id
- votes
title: BulkVoteRequest
MatchupResponse:
properties:
entity_a:
additionalProperties: true
type: object
title: Entity A
entity_b:
additionalProperties: true
type: object
title: Entity B
match_quality:
type: number
title: Match Quality
media_type:
type: string
title: Media Type
default: text
user_streak:
anyOf:
- type: integer
- type: 'null'
title: User Streak
total_votes_on_matchup:
type: integer
title: Total Votes On Matchup
default: 0
type: object
required:
- entity_a
- entity_b
- match_quality
title: MatchupResponse
api__routes__votes__VoteCreate:
properties:
ranking_id:
type: string
maxLength: 36
minLength: 36
title: Ranking Id
description: UUID of the ranking
entity_a_id:
type: string
maxLength: 36
minLength: 36
title: Entity A Id
description: UUID of first entity
entity_b_id:
type: string
maxLength: 36
minLength: 36
title: Entity B Id
description: UUID of second entity
winner_id:
anyOf:
- type: string
maxLength: 36
minLength: 36
- type: 'null'
title: Winner Id
description: UUID of winner (null = draw/skip)
confidence:
anyOf:
- type: number
maximum: 1.0
minimum: 0.0
- type: 'null'
title: Confidence
description: User confidence 0-1
decision_time_ms:
anyOf:
- type: integer
maximum: 300000.0
minimum: 0.0
- type: 'null'
title: Decision Time Ms
description: Time to decide (max 5 min)
source:
anyOf:
- type: string
- type: 'null'
title: Source
description: 'Vote source: organic, recommendation, embed, api'
default: organic
invite_code:
anyOf:
- type: string
maxLength: 64
- type: 'null'
title: Invite Code
description: Invite code that grants access to a non-public ranking. Allows anonymous voting on private rankings when the code's access_type permits it.
idempotency_key:
anyOf:
- type: string
maxLength: 64
- type: 'null'
title: Idempotency Key
description: Client-supplied key that makes this vote safely retryable. A retried / double-clicked submission carrying the same key applies the rating delta exactly once — the replay returns the original vote result (200) instead of creating a second vote. Omit for the default fire-and-forget behaviour.
voter_segment:
anyOf:
- additionalProperties: true
type: object
- type: 'null'
title: Voter Segment
description: 'Voter demographics for segment slicing — free-shape JSON object, e.g. {age_group: ''25-34'', gender: ''female'', region: ''EU'', role: ''designer''}. Persisted on the vote so leaderboards can be filtered by audience segment (marketing-agency use case). Max 16 keys, value strings ≤ 64 chars.'
type: object
required:
- ranking_id
- entity_a_id
- entity_b_id
title: VoteCreate
description: Create a pairwise comparison vote.
BulkVoteItem:
properties:
entity_a_id:
type: string
maxLength: 36
minLength: 36
title: Entity A Id
entity_b_id:
type: string
maxLength: 36
minLength: 36
title: Entity B Id
winner_id:
anyOf:
- type: string
maxLength: 36
minLength: 36
- type: 'null'
title: Winner Id
confidence:
anyOf:
- type: number
maximum: 1.0
minimum: 0.0
- type: 'null'
title: Confidence
decision_time_ms:
anyOf:
- type: integer
maximum: 300000.0
minimum: 0.0
- type: 'null'
title: Decision Time Ms
voter_id:
anyOf:
- type: string
maxLength: 64
- type: 'null'
title: Voter Id
description: External annotator ID — preserved on the vote for κ analysis
voter_segment:
anyOf:
- additionalProperties: true
type: object
- type: 'null'
title: Voter Segment
type: object
required:
- entity_a_id
- entity_b_id
title: BulkVoteItem
description: 'A single vote in a bulk import payload. Same shape as VoteCreate
minus the ranking_id (carried at the batch level).'
VoteStatsResponse:
properties:
total_votes:
type: integer
title: Total Votes
accuracy:
type: number
title: Accuracy
streak:
type: integer
title: Streak
longest_streak:
type: integer
title: Longest Streak
rankings_voted:
type: integer
title: Rankings Voted
level:
type: integer
title: Level
total_points:
type: integer
title: Total Points
points_to_next_level:
type: integer
title: Points To Next Level
achievements_earned:
type: integer
title: Achievements Earned
achievements_total:
type: integer
title: Achievements Total
streak_at_risk:
type: boolean
title: Streak At Risk
type: object
required:
- total_votes
- accuracy
- streak
- longest_streak
- rankings_voted
- level
- total_points
- points_to_next_level
- achievements_earned
- achievements_total
- streak_at_risk
title: VoteStatsResponse
BinaryVoteCreate:
properties:
ranking_id:
type: string
maxLength: 36
minLength: 36
title: Ranking Id
entity_id:
type: string
maxLength: 36
minLength: 36
title: Entity Id
label:
type: boolean
title: Label
description: True if the entity passes the criterion, False otherwise
decision_time_ms:
anyOf:
- type: integer
maximum: 300000.0
minimum: 0.0
- type: 'null'
title: Decision Time Ms
voter_segment:
anyOf:
- additionalProperties: true
type: object
- type: 'null'
title: Voter Segment
type: object
required:
- ranking_id
- entity_id
- label
title: BinaryVoteCreate
description: Cast a binary label on a single entity in a vote_type='binary' ranking.
ValidationError:
properties:
loc:
items:
anyOf:
- type: string
- type: integer
type: array
title: Location
msg:
type: string
title: Message
type:
type: string
title: Error Type
input:
title: Input
ctx:
type: object
title: Context
type: object
required:
- loc
- msg
- type
title: ValidationError
securitySchemes:
APIKeyHeader:
type: apiKey
in: header
name: X-API-Key