Peekaboo
Integrations and API

Integrations and API

REST API

Pull your AI Peekaboo data programmatically using an API key, with read or read+write scopes, filtering, and bulk writes.

7 minute read · Last reviewed: August 14, 2026

You want to pull your AI Peekaboo data programmatically, whether that's for a custom dashboard, an automation, or feeding another tool.

Base URL and authentication

The API base URL is:

https://www.aipeekaboo.com/api/v1

Authenticate every request with an X-API-Key header (a lowercase x-api-key or an Authorization: Bearer header work too). Your key looks like:

pk_{projectId}_{secret}

Generate a key from Settings → Integrations. You can revoke a key at any time from the same page.

Read vs. read+write scopes

When you generate a key, you choose its scope:

  • Read keys can pull data: brands, visibility, competitors, sources, prompts, categories, and recommended prompts.
  • Read+write keys can also create, update, and delete brands, prompts, competitors, and categories.

The read endpoints you'll use most

These GET endpoints cover the same core data you see in the dashboard. Any valid key can call them.

EndpointMethodWhat it returns
/brandsGETEvery brand in your project, with basic detail
/brands/:brandIdGETOne brand's metadata: name, URL, industry, prompt and competitor counts, analysis frequency
/brands/:brandId/snapshotGETVisibility score, top prompts, top sources, competitor rankings, and traffic in one pre-computed call
/brands/:brandId/visibilityGETVisibility score, trend, and market share for a 7d, 30d, or 90d window
/brands/:brandId/competitorsGETCompetitor scores on the same formula as your brand, plus traffic and rank
/brands/:brandId/sourcesGETDomains cited by AI models, with model attribution and mention counts
/brands/:brandId/promptsGETYour tracked prompts with score, trend, best and worst score, and search intent
/brands/:brandId/prompts/:promptIdGETOne prompt's per-run history, including cited article URLs and every entity mentioned
/brands/:brandId/categoriesGETYour prompt categories with aggregate performance per category
/brands/:brandId/recommendationsGETGap-driven prompt suggestions tied to real measured gaps, not generic ideas

A worked example: the snapshot call

One authenticated GET gives you the whole picture for a brand:

curl -H "X-API-Key: $API_KEY" \
  https://www.aipeekaboo.com/api/v1/brands/$BRAND_ID/snapshot

The response wraps everything in the standard envelope, with the payload under data:

{
  "success": true,
  "data": {
    "brand": { "id": "a1b2c3d4-...", "name": "Acme Corp" },
    "snapshotDate": "2026-02-24T02:00:00.000Z",
    "visibility": {
      "score": 42,
      "rank": 3,
      "maxScore": 100,
      "totalCitations": 87,
      "totalChatsAnalyzed": 40
    },
    "prompts": [
      {
        "promptText": "Best project management tools for teams",
        "category": "Discovery",
        "mentions": 8,
        "averageScore": 78,
        "aiModels": ["gpt-4o-mini", "gemini-2.5-flash", "sonar"]
      }
    ],
    "sources": [
      { "domain": "forbes.com", "mentions": 12, "aiModels": ["gpt-4o-mini"] }
    ],
    "competitors": [
      {
        "id": "c1d2e3f4-...",
        "name": "Competitor A",
        "url": "https://competitor-a.com",
        "score": 58,
        "change": "+12%",
        "monthlyVisits": 4500000,
        "globalRank": 12000,
        "rank": 1
      }
    ],
    "aiSuggestions": ["Focus on discovery prompts where competitors outrank you"],
    "traffic": {
      "monthlyVisits": 250000,
      "globalRank": 45000,
      "countryRank": 8500,
      "bounceRate": 0.42,
      "pagesPerVisit": 3.2,
      "avgTimeOnSite": 185
    }
  },
  "metadata": {
    "requestId": "550e8400-e29b-41d4-a716-446655440000",
    "timestamp": "2026-02-25T14:30:00.000Z",
    "queryTimeMs": 10
  }
}

Every response uses that same envelope: success, then data, then metadata carrying a requestId worth quoting in any support ticket. Paginated endpoints add a pagination object with offset, limit, total, and hasMore. If analysis hasn't run for the brand yet, snapshot comes back null rather than erroring.

Query parameters for filtering and paging

ParameterDefaultAccepted valuesWorks on
time_range7d7d, 30d, 90d/visibility, /prompts, /prompts/:promptId, /categories
offset00 or greater/prompts
limit501 to 200/prompts
categorynoneAny of your category names/prompts
search_intentnoneINFORMATIONAL, COMMERCIAL, TRANSACTIONAL, NAVIGATIONAL, LOCAL, INVESTIGATIONAL, SENTIMENT, BRANDED/prompts, /categories

Ninety days is the longest window the API will serve, and no all-time option exists, so anything longer has to be pulled on a schedule and stored on your side.

curl -H "X-API-Key: $API_KEY" \
  "https://www.aipeekaboo.com/api/v1/brands/$BRAND_ID/prompts?time_range=30d&search_intent=COMMERCIAL&limit=200&offset=0"

The write endpoints

A read+write key unlocks create, update, and delete across brands, prompts, competitors, and categories. The bulk routes are the reason to bother: the dashboard adds items one at a time, and these load a whole account in one call.

EndpointMethodWhat it does
/brandsPOSTCreate a brand (name required, plus optional url, industry, productDescription)
/brands/:brandIdPUTUpdate a brand's name, URL, industry, or description
/brands/:brandIdDELETESoft-delete a brand
/brands/:brandId/promptsPOSTAdd one prompt
/brands/:brandId/prompts/bulkPOSTAdd up to 100 prompts in one request
/brands/:brandId/prompts/:promptIdPUTEdit a prompt's text or category
/brands/:brandId/prompts/:promptIdDELETESoft-delete one prompt
/brands/:brandId/prompts/bulk-deletePOSTSoft-delete up to 100 prompts by ID
/brands/:brandId/competitorsPOSTAdd one competitor
/brands/:brandId/competitors/bulkPOSTAdd up to 50 competitors in one request
/brands/:brandId/competitors/:competitorIdPUT / DELETEUpdate or remove a competitor
/brands/:brandId/categoriesPOSTCreate a prompt category
/brands/:brandId/categories/:categoryIdPUT / DELETEUpdate or remove a category

Field length limits are enforced server side: brand and competitor names up to 200 characters, URLs up to 500, prompt text up to 1,000, category names up to 100, and product descriptions up to 2,000. Anything longer comes back as INVALID_PARAMS rather than being silently truncated.

Error codes and what they mean

Errors come back with success: false and an error object holding a code, a human-readable message, and sometimes details.

CodeHTTPWhat went wrong
UNAUTHORIZED401No X-API-Key header, or the key is invalid or revoked
FORBIDDEN403A read-only key hit a write endpoint, or writes are temporarily disabled
SUBSCRIPTION_INACTIVE403No active subscription on the project, or it has lapsed
LIMIT_EXCEEDED403You hit a plan limit, typically max prompts, competitors, or brands
INVALID_PARAMS400Bad UUID, out-of-range pagination, or a body that failed validation
NOT_FOUND404The brand or prompt doesn't exist, or isn't in your project
CONFLICT409The change collides with existing state, such as a duplicate prompt or competitor name
RATE_LIMITED429Per-minute or daily limit reached
INTERNAL_ERROR500Something broke on our side. Send us the requestId from metadata

A brand that belongs to another project returns NOT_FOUND rather than FORBIDDEN, so a 404 on an ID you believe is valid usually means the key belongs to a different project.

Rate limits by plan

Limits are counted per API key, on a per-minute window plus a daily budget that resets at midnight UTC.

PlanPer minutePer day
Starter and Peek plans550
Grow plans201,000
Custom and Enterprise plans402,000

Every response, not just a 429, carries the full set of counters:

HeaderMeaning
X-RateLimit-LimitYour per-minute ceiling
X-RateLimit-RemainingRequests left in the current minute
X-RateLimit-ResetUnix epoch in seconds when the minute window resets
X-RateLimit-Daily-LimitYour daily ceiling
X-RateLimit-Daily-RemainingRequests left today

Read X-RateLimit-Remaining before firing the next call and sleep until X-RateLimit-Reset when it reaches zero, rather than retrying into a wall of 429s. Starter and Peek keys hit the ceiling almost immediately, so production automations belong on Grow or higher.

Gotchas worth knowing before you build

  • Prompt history uses `aiModel`, not `model`. In each /prompts/:id history entry, the model name lives in the aiModel field. Reading model returns nothing and collapses every row to "unknown".
  • Prompt history caps at 100 entries. That endpoint returns the 100 most recent runs with no pagination. Since each run produces one entry per model, a daily brand only reaches back about 20 days. To keep more history, pull on a schedule and store it yourself.
  • Only `7d`, `30d`, and `90d` windows work. Any other time_range value silently falls back to 7 days rather than erroring, so a typo quietly returns the wrong window.
  • `/recommendations` is slow, so cache it. It runs a fresh model call per suggestion and can take 8 to 15 seconds. Store the result on your side instead of calling it on every page load.

Who can use it

The REST API requires an active paid subscription on any tier. It isn't available on free, no-subscription workspaces.