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/adcrunch-dev:adcrunch-dev-targeting-options-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:
contact:
email: tech@adcrunch.dev
description: 'Every AdCrunch API, in one document. Each API also publishes its own, at `/openapi/.json`.
One origin serves the four, and the first segment of a path names the API. `/observe` reads the campaigns, the ads and the Insights of the ad accounts your organization connects. `/mutations` changes what runs on them. `/context` holds the Skills, Brands, Personas, Documents and Campaign Plans an organization writes down for its agents. `/assets` holds your images and videos, and places them in the library of an ad account.
One credential works on the four — see the security scheme.
The guide explains what these operations share: authentication, the failure shape, and the conventions for ids, money, time and pagination. It also describes three flows that span several operations: a change, an upload, and an edit that does not overwrite.
Start at https://docs.adcrunch.dev/api/introduction.'
license:
name: Proprietary
url: https://adcrunch.dev
title: AdCrunch Targeting options API
version: 1.0.0
servers:
- description: production stage
url: https://api.adcrunch.dev
security:
- bearerAuth: []
tags:
- description: 'The Meta interests and job titles that an ad set can target. An option is configuration of Meta, not an entity: it has no Insight, and AdCrunch stores none. Search them by name, and send their ids when you create an ad set.'
name: Targeting options
paths:
/observe/{advertiserId}/targeting-options:
get:
security:
- bearerAuth: []
description: '**Available on:** 
Live read. Asks Meta now for the interests or the job titles whose name matches `q`, as this ad account can target them. Send the `id` of each option that you choose in `interests` or `workPositions` when you create an ad set.
Keep the `id`, not the name: Meta can rename an option. `audienceSizeLowerBound` and `audienceSizeUpperBound` give the size of the audience that Meta estimates for the option alone. `path` gives the category of an interest. A field that Meta does not give is null. Meta gives at most 45 options on one page.
An advertiser that your organization does not own answers `404`, with `error` of `not_found`. An advertiser that does not exist, and one that is not a Meta ad account, answer the same.
AdCrunch stores nothing from this read. Each request counts against the rate limits of Meta.
`limit` and `cursor` page the answer. Send `nextCursor` back as `cursor` to get the next page. A page can hold no row and still carry `nextCursor`.'
x-adcrunch-providers:
- meta
operationId: searchTargetingOptions
responses:
'200':
content:
application/json:
example:
data:
- audienceSizeLowerBound: 412000000
audienceSizeUpperBound: 484500000
id: '6003139266461'
name: Yoga
path:
- Interests
- Fitness and wellness
- Yoga
type: interest
- audienceSizeLowerBound: 18400000
audienceSizeUpperBound: 21700000
id: '6003256093937'
name: Hot yoga
path:
- Interests
- Additional interests
- Hot yoga
type: interest
schema:
type: object
properties:
data:
type: array
items:
type: object
properties:
audienceSizeLowerBound:
description: The lower bound of the audience size that Meta estimates for this option alone. Null when Meta gives none.
type:
- integer
- 'null'
minimum: -9007199254740991
maximum: 9007199254740991
audienceSizeUpperBound:
description: The upper bound of the audience size that Meta estimates for this option alone. Null when Meta gives none.
type:
- integer
- 'null'
minimum: -9007199254740991
maximum: 9007199254740991
id:
type: string
description: 'The Meta id of the option. Send it in `interests` or `workPositions` to create an ad set. Keep the id: Meta can rename an option.'
name:
type: string
description: The name of the option in Meta.
path:
description: The category of the option and its parent categories, from the top. Null when Meta gives none.
type:
- array
- 'null'
items:
type: string
type:
type: string
enum:
- interest
- work_position
description: 'The type of the option: `interest` or `work_position`.'
required:
- audienceSizeLowerBound
- audienceSizeUpperBound
- id
- name
- path
- type
additionalProperties: false
description: 'The interests or the job titles whose name matches `q`, in the order of Meta. An empty array can carry `nextCursor`: then more rows can exist.'
nextCursor:
description: Send this value as `cursor` to get the next page. It is absent on the last page.
type: string
required:
- data
additionalProperties: false
example:
data:
- audienceSizeLowerBound: 412000000
audienceSizeUpperBound: 484500000
id: '6003139266461'
name: Yoga
path:
- Interests
- Fitness and wellness
- Yoga
type: interest
- audienceSizeLowerBound: 18400000
audienceSizeUpperBound: 21700000
id: '6003256093937'
name: Hot yoga
path:
- Interests
- Additional interests
- Hot yoga
type: interest
description: The options that match the search.
'400':
content:
application/json:
schema:
anyOf:
- type: object
properties:
issues:
type: array
items:
type: object
properties:
in:
type: string
enum:
- body
- cookie
- headers
- params
- query
description: The part of the request that holds the field.
message:
type: string
description: A sentence to show a person. Written to say what to do next. Reworded whenever it can be said better, so never branch on it.
path:
type: string
description: A JSON Pointer into that part of the request, such as `/filename`. An empty string is the whole part.
required:
- in
- message
- path
additionalProperties: false
description: One entry for each field that does not match.
error:
type: string
enum:
- invalid_request
description: A stable code for the failure. This is the field to branch on. It does not change for a given failure.
message:
type: string
description: A sentence to show a person. Written to say what to do next. Reworded whenever it can be said better, so never branch on it.
required:
- issues
- error
- message
additionalProperties: false
- type: object
properties:
error:
type: string
enum:
- invalid_cursor
description: A stable code for the failure. This is the field to branch on. It does not change for a given failure.
message:
type: string
description: A sentence to show a person. Written to say what to do next. Reworded whenever it can be said better, so never branch on it.
required:
- error
- message
additionalProperties: false
description: 'The request does not match the schema of this operation: a field is missing or has the wrong type, or the body is not valid JSON. `error` is `invalid_request`, and `issues` names each field. Nothing was changed. Or AdCrunch cannot use the `cursor`: it cannot read it, or the cursor belongs to a different query. Then `error` is `invalid_cursor`. Send the `nextCursor` of the previous page with no change, or omit `cursor` to get the first page.'
'401':
content:
application/json:
schema:
type: object
properties:
error:
type: string
enum:
- unauthorized
description: A stable code for the failure. This is the field to branch on. It does not change for a given failure.
message:
type: string
description: A sentence to show a person. Written to say what to do next. Reworded whenever it can be said better, so never branch on it.
required:
- error
- message
additionalProperties: false
description: No API key, or one that does not resolve. See the security scheme. `error` is `unauthorized`.
'402':
content:
application/json:
schema:
type: object
properties:
paywallUrl:
type: string
format: uri
description: The page where an owner of the organization subscribes. Show it to the person.
error:
type: string
enum:
- organization_unentitled
description: A stable code for the failure. This is the field to branch on. It does not change for a given failure.
message:
type: string
description: A sentence to show a person. Written to say what to do next. Reworded whenever it can be said better, so never branch on it.
required:
- paywallUrl
- error
- message
additionalProperties: false
description: The organization has no active subscription. An owner subscribes at `paywallUrl`. `error` is `organization_unentitled`.
'403':
content:
application/json:
schema:
type: object
properties:
error:
type: string
enum:
- forbidden
description: A stable code for the failure. This is the field to branch on. It does not change for a given failure.
message:
type: string
description: A sentence to show a person. Written to say what to do next. Reworded whenever it can be said better, so never branch on it.
required:
- error
- message
additionalProperties: false
description: The caller does not hold `observe:read`. `error` is `forbidden`.
'404':
content:
application/json:
schema:
type: object
properties:
error:
type: string
enum:
- not_found
description: A stable code for the failure. This is the field to branch on. It does not change for a given failure.
message:
type: string
description: A sentence to show a person. Written to say what to do next. Reworded whenever it can be said better, so never branch on it.
required:
- error
- message
additionalProperties: false
description: Your organization does not own the advertiser in the path, it does not exist, or it is not a Meta ad account. The answer does not tell them apart. `error` is `not_found`. AdCrunch asks Meta nothing.
'409':
content:
application/json:
schema:
type: object
properties:
provider:
type: string
description: 'The ad platform this failure came from: `meta`.'
error:
type: string
enum:
- provider_not_connected
description: A stable code for the failure. This is the field to branch on. It does not change for a given failure.
message:
type: string
description: A sentence to show a person. Written to say what to do next. Reworded whenever it can be said better, so never branch on it.
required:
- provider
- error
- message
additionalProperties: false
description: This advertiser has no usable connection to Meta. A person must reconnect it.
'502':
content:
application/json:
schema:
type: object
properties:
platformError:
description: The provider’s own error object, unchanged. For Meta it carries `code`, `error_subcode`, `type`, `error_user_title` and `error_user_msg` — branch on the subcode for anything AdCrunch does not model. It never holds the request AdCrunch sent.
provider:
type: string
description: 'The ad platform this failure came from: `meta`.'
error:
type: string
enum:
- provider_error
description: A stable code for the failure. This is the field to branch on. It does not change for a given failure.
message:
type: string
description: A sentence to show a person. Written to say what to do next. Reworded whenever it can be said better, so never branch on it.
required:
- platformError
- provider
- error
- message
additionalProperties: false
description: The provider refused the request, or could not answer it. This failure is often transient. Send the request again.
summary: Search the Meta interests and job titles
tags:
- Targeting options
parameters:
- name: advertiserId
in: path
required: true
schema:
type: string
pattern: ^(acc_)[\s\S]{0,}$
description: The ad account to read, prefixed `acc_`. It must belong to your organization. One that does not answers `404`, with `error` of `not_found`.
- name: q
in: query
required: true
schema:
type: string
minLength: 1
description: The words to search for in the names of the options, for example `yoga`.
- name: type
in: query
required: true
schema:
type: string
enum:
- interest
- work_position
description: 'The type of option to search: `interest` or `work_position` (a job title).'
- name: cursor
in: query
required: false
schema:
description: 'The `nextCursor` of the previous page. Omit it to get the first page. Send it with no change, and with the same filters as the request that answered it: a cursor from a different query gets a 400 `invalid_cursor`. Do not build or change a cursor.'
type: string
minLength: 1
- name: limit
in: query
required: false
schema:
default: 100
description: The greatest number of rows on the page, from 1 to 500. The default is 100. A greater value gets a 400, with `error` of `invalid_request`.
type: integer
minimum: 1
maximum: 500
components:
securitySchemes:
bearerAuth:
description: 'Send `Authorization: Bearer <credential>`.
Use an **API key** (`acr_…`), from the AdCrunch console under Settings → API keys.
The credential names the organization, and no operation takes an organization parameter.
See https://docs.adcrunch.dev/api/authentication.'
scheme: bearer
type: http
x-adcrunch-commit: 7a89aff7eb17461cc80089b9374e622947e37b2b
x-tagGroups:
- name: Observe API
tags:
- Insights
- Campaigns
- Ad groups
- Ads
- Creatives
- Custom audiences
- Asset groups
- Pages
- Pixels
- Custom conversions
- Targeting options
- Stored reads
- name: Mutations API
tags:
- Mutations
- name: Context API
tags:
- Skills
- Brands
- Personas
- Documents
- Campaign Plans
- Line Items
- name: Assets API
tags:
- Assets