Every API here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for apis
7 MCP tools reach this
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.
All 92 tools →
Call it yourself
curl for this page
This API
curl "https://apis.io/api/v1/apis/hookdetector-com:hookdetector-com-polls-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"
Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.
Get an API key
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: Hook Detector Polls API
description: 'Find short-form hooks that already work.
Sign up with a beta access code (ask at https://hookdetector.com/access): one POST to
`/v1/accounts` with `access_code` gives an API key and free credits. The same operations are available as MCP tools at `/mcp`.
Full guide, always current, at `/llms.txt`.'
contact:
name: Hook Detector
url: https://hookdetector.com/
email: contact@hookdetector.com
version: 3.0.0
tags:
- name: polls
paths:
/v1/polls:
post:
tags:
- polls
summary: Put 2 to 4 packages to a vote before publishing
description: 'Put 2 to 4 packages (a title and a thumbnail each) to Hook Detector''s users, who pick the one
they would click, blind, each seeing the options in an order of their own. The poll closes at
votes_wanted (10 to 200, default 30) or after 7 days. Results: each option''s votes, share and
95% interval, a leader only once the votes separate, the slot each vote sat in, and the
voters'' reasons. What these voters chose, never a click-through rate. 2 credits, given back
when a picture cannot be stored. MCP: create_poll.'
operationId: create_poll_v1_polls_post
parameters:
- name: Idempotency-Key
in: header
required: false
schema:
anyOf:
- type: string
- type: 'null'
description: 1 to 255 visible ASCII characters; the same key and request within 24 hours answer the saved poll and charge nothing
title: Idempotency-Key
description: 1 to 255 visible ASCII characters; the same key and request within 24 hours answer the saved poll and charge nothing
- name: authorization
in: header
required: false
schema:
anyOf:
- type: string
- type: 'null'
description: Bearer hd_... from POST /v1/accounts or POST /v1/keys
title: Authorization
description: Bearer hd_... from POST /v1/accounts or POST /v1/keys
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PollIn'
responses:
'201':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/PollOut'
'401':
description: missing, invalid, revoked or expired API key (code key_expired)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
'402':
description: not enough credits
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
'403':
description: the key lacks the scope this call needs (insufficient_scope), or its credit_limit is spent (key_credit_limit_reached)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
'413':
description: request body over the size cap
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
'422':
description: invalid input
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
'429':
description: rate limited; see Retry-After
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
'500':
description: our fault; names the request id
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
'200':
description: the Idempotency-Key replayed the saved poll
content:
application/json:
schema:
$ref: '#/components/schemas/PollOut'
'503':
description: 'storage_unavailable: a picture could not be stored; the credits were given back'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
get:
tags:
- polls
summary: Your package votes
description: 'Your polls, newest first, each with its results so far. Free. MCP: list_polls.'
operationId: list_polls_v1_polls_get
parameters:
- name: authorization
in: header
required: false
schema:
anyOf:
- type: string
- type: 'null'
description: Bearer hd_... from POST /v1/accounts or POST /v1/keys
title: Authorization
description: Bearer hd_... from POST /v1/accounts or POST /v1/keys
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/PollListOut'
'401':
description: missing, invalid, revoked or expired API key (code key_expired)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
'403':
description: the key lacks the scope this call needs (insufficient_scope), or its credit_limit is spent (key_credit_limit_reached)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
'413':
description: request body over the size cap
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
'422':
description: invalid input
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
'500':
description: our fault; names the request id
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
/v1/polls/next:
get:
tags:
- polls
summary: A poll waiting for your vote
description: 'An open poll of another Hook Detector user that you have not voted on and did not pass in
`skip`, its options in an order of your own and no counts; null when none is waiting. Free.
MCP: next_poll.'
operationId: next_poll_v1_polls_next_get
parameters:
- name: skip
in: query
required: false
schema:
anyOf:
- type: string
- type: 'null'
description: poll ids to pass over in this ask, comma separated (Skip)
title: Skip
description: poll ids to pass over in this ask, comma separated (Skip)
- name: authorization
in: header
required: false
schema:
anyOf:
- type: string
- type: 'null'
description: Bearer hd_... from POST /v1/accounts or POST /v1/keys
title: Authorization
description: Bearer hd_... from POST /v1/accounts or POST /v1/keys
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/NextPollOut'
'401':
description: missing, invalid, revoked or expired API key (code key_expired)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
'403':
description: the key lacks the scope this call needs (insufficient_scope), or its credit_limit is spent (key_credit_limit_reached)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
'413':
description: request body over the size cap
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
'422':
description: invalid input
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
'500':
description: our fault; names the request id
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
/v1/polls/{poll_id}:
get:
tags:
- polls
summary: One poll and its results
description: 'Your poll with everything (votes, shares, intervals, leader, slots, reasons), or a poll you
voted on with its shares. Any other is 404. Free. MCP: get_poll.'
operationId: get_poll_v1_polls__poll_id__get
parameters:
- name: poll_id
in: path
required: true
schema:
type: string
format: uuid
title: Poll Id
- name: authorization
in: header
required: false
schema:
anyOf:
- type: string
- type: 'null'
description: Bearer hd_... from POST /v1/accounts or POST /v1/keys
title: Authorization
description: Bearer hd_... from POST /v1/accounts or POST /v1/keys
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/PollOut'
'401':
description: missing, invalid, revoked or expired API key (code key_expired)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
'403':
description: the key lacks the scope this call needs (insufficient_scope), or its credit_limit is spent (key_credit_limit_reached)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
'404':
description: not found on this account
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
'413':
description: request body over the size cap
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
'422':
description: invalid input
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
'500':
description: our fault; names the request id
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
delete:
tags:
- polls
summary: Delete a poll
description: 'Delete your poll, its votes and its pictures. Free. MCP: delete_poll.'
operationId: delete_poll_v1_polls__poll_id__delete
parameters:
- name: poll_id
in: path
required: true
schema:
type: string
format: uuid
title: Poll Id
- name: authorization
in: header
required: false
schema:
anyOf:
- type: string
- type: 'null'
description: Bearer hd_... from POST /v1/accounts or POST /v1/keys
title: Authorization
description: Bearer hd_... from POST /v1/accounts or POST /v1/keys
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/PollDeletedOut'
'401':
description: missing, invalid, revoked or expired API key (code key_expired)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
'403':
description: the key lacks the scope this call needs (insufficient_scope), or its credit_limit is spent (key_credit_limit_reached)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
'404':
description: not found on this account
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
'413':
description: request body over the size cap
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
'422':
description: invalid input
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
'500':
description: our fault; names the request id
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
/v1/polls/{poll_id}/vote:
post:
tags:
- polls
summary: Vote on a poll
description: 'Vote with the slot you picked in next_poll''s answer, and an optional reason. One vote an
account; never on your own or your team''s poll (403 own_poll); a closed poll is 409
poll_closed. Answers the poll''s shares so far. Free. MCP: vote_poll.'
operationId: vote_poll_v1_polls__poll_id__vote_post
parameters:
- name: poll_id
in: path
required: true
schema:
type: string
format: uuid
title: Poll Id
- name: authorization
in: header
required: false
schema:
anyOf:
- type: string
- type: 'null'
description: Bearer hd_... from POST /v1/accounts or POST /v1/keys
title: Authorization
description: Bearer hd_... from POST /v1/accounts or POST /v1/keys
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/VoteIn'
responses:
'201':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/PollOut'
'401':
description: missing, invalid, revoked or expired API key (code key_expired)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
'403':
description: the key lacks the scope this call needs (insufficient_scope), or its credit_limit is spent (key_credit_limit_reached)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
'404':
description: not found on this account
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
'413':
description: request body over the size cap
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
'422':
description: invalid input
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
'500':
description: our fault; names the request id
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
'409':
description: conflict with the account's state
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
'429':
description: rate limited; see Retry-After
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
/v1/polls/{poll_id}/close:
post:
tags:
- polls
summary: Close your poll now
description: 'End your poll now: no more votes, the votes so far kept with its results. Closing a
closed poll answers it as it is. Free. MCP: close_poll.'
operationId: close_poll_v1_polls__poll_id__close_post
parameters:
- name: poll_id
in: path
required: true
schema:
type: string
format: uuid
title: Poll Id
- name: authorization
in: header
required: false
schema:
anyOf:
- type: string
- type: 'null'
description: Bearer hd_... from POST /v1/accounts or POST /v1/keys
title: Authorization
description: Bearer hd_... from POST /v1/accounts or POST /v1/keys
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/PollOut'
'401':
description: missing, invalid, revoked or expired API key (code key_expired)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
'403':
description: the key lacks the scope this call needs (insufficient_scope), or its credit_limit is spent (key_credit_limit_reached)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
'404':
description: not found on this account
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
'413':
description: request body over the size cap
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
'422':
description: invalid input
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
'500':
description: our fault; names the request id
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorOut'
components:
schemas:
NextPollOut:
properties:
poll:
anyOf:
- additionalProperties: true
type: object
- type: 'null'
title: Poll
description: a poll waiting for your vote, its options in your own order, no counts; null when none is waiting
basis:
type: string
title: Basis
additionalProperties: true
type: object
required:
- poll
- basis
title: NextPollOut
examples:
- basis: Pick the one you would click.
poll:
closes_at: '2026-11-03T12:00:00+00:00'
options:
- slot: 0
thumbnail_url: https://...signed...
title: '30 Days of Home Workouts: What Changed'
- slot: 1
thumbnail_url: https://...signed...
title: I Tried Every Home Workout For 30 Days
poll_id: 0b9d3c1e-5a2f-4e7b-9c8d-1f2e3a4b5c6d
question: Which would you click?
subject: home workouts
ErrorOut:
properties:
detail:
type: string
title: Detail
description: one sentence a person can read
code:
type: string
title: Code
description: stable machine code; see the Errors section of /llms.txt
errors:
anyOf:
- items:
additionalProperties: true
type: object
type: array
- type: 'null'
title: Errors
description: 'on a 422 only: the field level list'
additionalProperties: true
type: object
required:
- detail
- code
title: ErrorOut
examples:
- code: run_not_found
detail: no such run for this account
PollListOut:
properties:
polls:
items:
additionalProperties: true
type: object
type: array
title: Polls
count:
type: integer
title: Count
additionalProperties: true
type: object
required:
- polls
- count
title: PollListOut
VoteIn:
properties:
slot:
title: Slot
description: the slot you picked in next_poll's answer (0 is the first shown)
reason:
anyOf:
- type: string
- type: 'null'
title: Reason
description: 'optional: why, at most 140 characters'
type: object
title: VoteIn
PollIn:
properties:
options:
items: {}
type: array
title: Options
description: 2 to 4 packages, each {title, thumbnail}
question:
anyOf:
- type: string
- type: 'null'
title: Question
description: default "Which would you click?", at most 120 characters
subject:
anyOf:
- type: string
- type: 'null'
title: Subject
description: what the video is about, shown to voters
votes_wanted:
title: Votes Wanted
description: '10 to 200 (default 30): the poll closes when it has them, or after 7 days'
type: object
required:
- options
title: PollIn
PollOut:
properties:
poll_id:
type: string
title: Poll Id
status:
type: string
title: Status
description: open or closed (votes_wanted reached, or 7 days passed)
votes:
type: integer
title: Votes
options:
items:
additionalProperties: true
type: object
type: array
title: Options
description: each option's votes, share and 95% interval (Wilson)
leader:
anyOf:
- type: integer
- type: 'null'
title: Leader
description: the option whose interval is clear of every other's; null until the votes separate them
basis:
type: string
title: Basis
additionalProperties: true
type: object
required:
- poll_id
- status
- votes
- options
- leader
- basis
title: PollOut
examples:
- basis: 'Counted from the Hook Detector users who voted: each saw the options in an order of their own and picked the one they would click. It says what these voters chose, not a click-through rate or a prediction of your audience. The votes do not separate the options yet: no option''s 95% interval is clear of the others''.'
closes_at: '2026-11-03T12:00:00+00:00'
created_at: '2026-10-27T12:00:00+00:00'
mine: true
options:
- interval:
- 0.468
- 0.911
option: 0
share: 0.75
thumbnail_url: https://...signed...
title: I Tried Every Home Workout For 30 Days
votes: 9
- interval:
- 0.089
- 0.532
option: 1
share: 0.25
thumbnail_url: https://...signed...
title: '30 Days of Home Workouts: What Changed'
votes: 3
poll_id: 0b9d3c1e-5a2f-4e7b-9c8d-1f2e3a4b5c6d
question: Which would you click?
reasons:
- option: 0
reason: the face reads at a glance
slots:
- share: 0.583
slot: 0
votes: 7
- share: 0.417
slot: 1
votes: 5
status: open
subject: home workouts
votes: 12
votes_wanted: 30
PollDeletedOut:
properties:
poll_id:
type: string
title: Poll Id
deleted:
type: boolean
title: Deleted
additionalProperties: true
type: object
required:
- poll_id
- deleted
title: PollDeletedOut