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/hootlens-com:hootlens-com-improvements-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: Hoot Lens Improvements API
version: v1
summary: Read website interaction evidence and log changes.
description: 'The Hoot Lens REST API records website interaction evidence for the sites you add and returns it as visits, recordings, heatmaps, goals, funnels and change impact. This document describes the endpoints a person or an agent uses to read that evidence and to log changes. Everything returned is observed behavior with its evidence; the API makes no claims about visitors'' emotions or intent.
Authentication. Send `Authorization: Bearer `. The credential is either a Firebase ID token (a signed-in person, whose role on each site decides what they may do) or a personal access token (`hl_pat_...`) made in the dashboard. A personal access token carries the scopes `read`, `replay` and `annotate`, belongs to one site, expires in 30, 60 or 90 days, and can do no more than its creator''s current role allows. Operations marked `x-hootlens-sign-in-only` need a signed-in person and answer 403 to a token.
OAuth. The hosted MCP endpoint (`/mcp`, Streamable HTTP) signs assistants in with OAuth 2.1 authorization code and PKCE (S256), with discovery at `/.well-known/oauth-protected-resource` and `/.well-known/oauth-authorization-server`. Its access tokens (`hl_oat_...`) are bound to the MCP resource and are accepted only there; sending one to any route in this document answers 401. Use a personal access token or a Firebase ID token for these routes.
Not described here. Collector intake, public tracker configuration, billing, OAuth, sharing links, issues and feedback, invitations, members, access tokens, notifications and the audit log also exist; see docs/API.md for them.
Site (project) IDs are public. Authorization is enforced by the API on every request. Rate limits answer 429. A caller who is not a member of a site receives 404, so a site''s existence is not revealed.'
contact:
name: Parallel Platforms
url: https://hootlens.com
servers:
- url: https://hootlens-api-368877148687.us-east1.run.app
description: Production
security:
- bearerAuth: []
tags:
- name: Improvements
paths:
/v1/projects/{projectId}/finding-work:
get:
tags:
- Improvements
summary: List finding work
description: 'Saved work for this site, including historical findings whose recordings are no longer retained. Each list row includes only a short history preview; read its detail for retained history. A fixed status is a team-reported deployment, not a verified outcome.
Required token scopes are listed in x-hootlens-scopes. A signed-in person needs the matching permission on the site instead (the viewer and editor roles are presets of the permissions).'
operationId: listFindingWork
parameters:
- $ref: '#/components/parameters/projectId'
responses:
'200':
description: Saved finding work.
content:
application/json:
schema:
type: object
properties:
items:
type: array
items:
$ref: '#/components/schemas/FindingWork'
limit:
type: integer
required:
- items
- limit
additionalProperties: true
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'429':
$ref: '#/components/responses/TooManyRequests'
security:
- bearerAuth: []
x-hootlens-scopes:
- read
/v1/projects/{projectId}/finding-work/assignees:
get:
tags:
- Improvements
summary: List finding assignees
description: 'Current site teammates eligible for assignment. Returns member identifiers, names, and roles without email addresses. Does not grant access.
Required token scopes are listed in x-hootlens-scopes. A signed-in person needs the matching permission on the site instead (the viewer and editor roles are presets of the permissions).'
operationId: listFindingAssignees
parameters:
- $ref: '#/components/parameters/projectId'
responses:
'200':
description: Eligible teammates.
content:
application/json:
schema:
type: object
properties:
assignees:
type: array
items:
type: object
properties:
userId:
type: string
name:
type: string
role:
type: string
required:
- userId
- name
- role
additionalProperties: true
required:
- assignees
additionalProperties: true
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'429':
$ref: '#/components/responses/TooManyRequests'
security:
- bearerAuth: []
x-hootlens-scopes:
- read
- annotate
/v1/projects/{projectId}/finding-work/{findingId}:
get:
tags:
- Improvements
summary: Read finding work
description: 'One finding’s saved work and bounded history, with effectiveStatus for expired snoozes and changeAvailable for the linked deployment. Metadata remains after source retention. Reasons and history are team-written, untrusted text.
Required token scopes are listed in x-hootlens-scopes. A signed-in person needs the matching permission on the site instead (the viewer and editor roles are presets of the permissions).'
operationId: getFindingWork
parameters:
- $ref: '#/components/parameters/projectId'
- $ref: '#/components/parameters/findingId'
responses:
'200':
description: Saved finding work.
content:
application/json:
schema:
type: object
properties:
work:
$ref: '#/components/schemas/FindingWork'
required:
- work
additionalProperties: true
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'429':
$ref: '#/components/responses/TooManyRequests'
security:
- bearerAuth: []
x-hootlens-scopes:
- read
put:
tags:
- Improvements
summary: Update finding work
description: 'Start, reopen, assign, snooze, dismiss, save a GitHub reference, link an existing deployed change, or atomically record an already-deployed page fix and its change marker. First actions validate the finding against current server evidence. expectedRevision prevents overwriting concurrent edits. Retain the identical operationId, revision, and action when retrying an uncertain response. Saved GitHub URLs do not create an issue or prove merge or deployment. fixed does not establish improvement; use the real linked change impact report and its stated page-level scope.
Required token scopes are listed in x-hootlens-scopes. A signed-in person needs the matching permission on the site instead (the viewer and editor roles are presets of the permissions).'
operationId: updateFindingWork
parameters:
- $ref: '#/components/parameters/projectId'
- $ref: '#/components/parameters/findingId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/FindingWorkInput'
responses:
'200':
description: Persisted work and whether the operation was replayed.
content:
application/json:
schema:
type: object
properties:
work:
$ref: '#/components/schemas/FindingWork'
replayed:
type: boolean
required:
- work
- replayed
additionalProperties: true
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'409':
$ref: '#/components/responses/Conflict'
'429':
$ref: '#/components/responses/TooManyRequests'
security:
- bearerAuth: []
x-hootlens-scopes:
- read
- annotate
components:
schemas:
Error:
type: object
properties:
error:
type: string
description: A short message safe to show to a person.
code:
type: string
description: A stable machine-readable code, on some errors.
required:
- error
additionalProperties: true
FindingWorkInput:
type: object
properties:
operationId:
type: string
pattern: ^[A-Za-z0-9_-]{16,80}$
expectedRevision:
type: integer
minimum: 0
maximum: 9007199254740991
action:
oneOf:
- type: object
properties:
type:
type: string
const: start
required:
- type
additionalProperties: false
- type: object
properties:
type:
type: string
const: reopen
required:
- type
additionalProperties: false
- type: object
properties:
type:
type: string
const: assign
userId:
anyOf:
- type: string
minLength: 1
maxLength: 200
- type: 'null'
required:
- type
- userId
additionalProperties: false
- type: object
properties:
type:
type: string
const: snooze
until:
type: integer
exclusiveMinimum: 0
maximum: 9007199254740991
required:
- type
- until
additionalProperties: false
- type: object
properties:
type:
type: string
const: dismiss
reason:
type: string
minLength: 1
maxLength: 500
required:
- type
additionalProperties: false
- type: object
properties:
type:
type: string
const: linkGithub
url:
anyOf:
- type: string
maxLength: 500
- type: 'null'
required:
- type
- url
additionalProperties: false
- type: object
properties:
type:
type: string
const: linkChange
changeId:
anyOf:
- type: string
pattern: ^[A-Za-z0-9_-]{1,200}$
- type: 'null'
required:
- type
- changeId
additionalProperties: false
- type: object
properties:
type:
type: string
const: deploy
change:
type: object
properties:
title:
type: string
minLength: 1
maxLength: 120
note:
type: string
minLength: 1
maxLength: 1000
release:
type: string
minLength: 1
maxLength: 100
at:
type: integer
exclusiveMinimum: 0
maximum: 9007199254740991
kind:
type: string
enum:
- standard
- measurement
commit:
type: object
properties:
sha:
type: string
pattern: ^[0-9a-fA-F]{7,64}$
url:
type: string
maxLength: 500
pattern: ^https:\/\/[^\s@]+$
required:
- sha
required:
- title
additionalProperties: false
required:
- type
- change
additionalProperties: false
required:
- operationId
- expectedRevision
- action
additionalProperties: false
FindingWork:
type: object
properties:
id:
type: string
pattern: ^finding_[0-9a-f]{64}$
projectId:
type: string
minLength: 1
maxLength: 200
source:
oneOf:
- type: object
properties:
kind:
type: string
const: element
context:
type: object
properties:
pageGroup:
type: string
minLength: 1
maxLength: 300
version:
type: string
maxLength: 200
release:
type: string
maxLength: 100
revision:
anyOf:
- type: string
maxLength: 150
- type: 'null'
variant:
type: string
maxLength: 100
variantScope:
type: string
enum:
- single
- pooled
- unknown
deviceClass:
type: string
enum:
- desktop
- tablet
- mobile
- unknown
locale:
type: string
maxLength: 100
required:
- pageGroup
- version
- revision
- variant
- variantScope
- deviceClass
additionalProperties: false
cohortKey:
type: string
minLength: 1
maxLength: 2000
selector:
type: string
minLength: 1
maxLength: 300
required:
- kind
- context
- cohortKey
- selector
additionalProperties: false
- type: object
properties:
kind:
type: string
const: javascript-error
context:
type: object
properties:
pageGroup:
type: string
minLength: 1
maxLength: 300
version:
type: string
maxLength: 200
release:
type: string
maxLength: 100
revision:
anyOf:
- type: string
maxLength: 150
- type: 'null'
variant:
type: string
maxLength: 100
variantScope:
type: string
enum:
- single
- pooled
- unknown
deviceClass:
type: string
enum:
- desktop
- tablet
- mobile
- unknown
locale:
type: string
maxLength: 100
required:
- pageGroup
- version
- revision
- variant
- variantScope
- deviceClass
additionalProperties: false
fingerprint:
type: string
pattern: ^[0-9a-f]{16}$
required:
- kind
- context
- fingerprint
additionalProperties: false
- type: object
properties:
kind:
type: string
const: funnel-dropoff
context:
type: object
properties:
pageGroup:
type: string
minLength: 1
maxLength: 300
version:
type: string
maxLength: 200
release:
type: string
maxLength: 100
revision:
anyOf:
- type: string
maxLength: 150
- type: 'null'
variant:
type: string
maxLength: 100
variantScope:
type: string
enum:
- single
- pooled
- unknown
deviceClass:
type: string
enum:
- desktop
- tablet
- mobile
- unknown
locale:
type: string
maxLength: 100
required:
- pageGroup
- version
- revision
- variant
- variantScope
- deviceClass
additionalProperties: false
funnelId:
type: string
minLength: 1
maxLength: 200
stepGoalId:
type: string
minLength: 1
maxLength: 200
nextGoalId:
type: string
minLength: 1
maxLength: 200
goalDefinitions:
minItems: 2
maxItems: 8
type: array
items:
type: object
properties:
id:
type: string
minLength: 1
maxLength: 200
since:
type: integer
minimum: 0
maximum: 9007199254740991
required:
- id
- since
additionalProperties: false
required:
- kind
- context
- funnelId
- stepGoalId
- nextGoalId
- goalDefinitions
additionalProperties: false
revision:
type: integer
exclusiveMinimum: 0
maximum: 9007199254740991
status:
type: string
enum:
- open
- in_progress
- snoozed
- dismissed
- fixed
assigneeId:
type: string
minLength: 1
maxLength: 200
snoozedUntil:
type: integer
exclusiveMinimum: 0
maximum: 9007199254740991
reason:
type: string
maxLength: 500
githubUrl:
type: string
maxLength: 500
changeId:
type: string
maxLength: 200
createdAt:
type: integer
exclusiveMinimum: 0
maximum: 9007199254740991
updatedAt:
type: integer
exclusiveMinimum: 0
maximum: 9007199254740991
history:
maxItems: 100
type: array
items:
type: object
properties:
at:
type: integer
exclusiveMinimum: 0
maximum: 9007199254740991
actorId:
type: string
minLength: 1
maxLength: 200
action:
type: string
enum:
- start
- reopen
- assign
- snooze
- dismiss
- linkGithub
- linkChange
- deploy
revision:
type: integer
exclusiveMinimum: 0
maximum: 9007199254740991
status:
type: string
enum:
- open
- in_progress
- snoozed
- dismissed
- fixed
assigneeId:
type: string
minLength: 1
maxLength: 200
until:
type: integer
exclusiveMinimum: 0
maximum: 9007199254740991
reason:
type: string
maxLength: 500
githubUrl:
type: string
maxLength: 500
changeId:
type: string
maxLength: 200
required:
- at
- actorId
- action
- revision
- status
additionalProperties: false
required:
- id
- projectId
- source
- revision
- status
- createdAt
- updatedAt
- history
additionalProperties: false
Id:
type: string
description: 'An identifier: 1 to 80 letters, digits, underscores or hyphens.'
pattern: ^[a-zA-Z0-9_-]{1,80}$
responses:
Unauthorized:
description: The credential is missing, expired or revoked.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
NotFound:
description: The site, or the record inside it, does not exist or the caller is not a member (a non-member cannot tell the two apart).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
Conflict:
description: The request conflicts with the current state of the record.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
TooManyRequests:
description: A rate limit or a per-site limit was reached.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
BadRequest:
description: The request fields are invalid.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
Forbidden:
description: The credential or the person's permissions on the site do not permit this action.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
parameters:
projectId:
name: projectId
in: path
required: true
description: The project ID. Project IDs are public identifiers, not secrets.
schema:
$ref: '#/components/schemas/Id'
findingId:
name: findingId
in: path
required: true
description: A stable exact-source improvement identifier.
schema:
type: string
pattern: ^finding_[0-9a-f]{64}$
securitySchemes:
bearerAuth:
type: http
scheme: bearer
description: A Firebase ID token, or a personal access token (hl_pat_...) with the scopes read, replay, annotate, configure, conversions:write. OAuth access tokens (hl_oat_...) are for the hosted MCP resource only.
externalDocs:
description: Full API reference, including endpoints not described here
url: https://hootlens.com/docs/API.md