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/ironfang:ironfang-analytics-heatmaps-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
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: Ironfang Analytics Heatmaps API
version: 0.1.0
summary: Sites, origins, public keys and capture settings for session replay and web analytics.
description: 'Ironfang Analytics follows each visit to your website as a session:
the pages a visitor saw, in every tab, with how long they stayed, the
errors and failed requests they met, the events your pages tracked, and
the recordings that let you replay it, live or afterwards.'
contact:
name: Ironfang
email: hello@ironfang.uk
url: https://ironfang.com/contact
termsOfService: https://ironfang.com/legal/terms
license:
name: Proprietary - use governed by the Ironfang terms of service
url: https://ironfang.com/legal/terms
servers:
- url: https://api.ironfang.com/analytics
security:
- apiKey: []
- bearerAuth: []
tags:
- name: Heatmaps
description: Totals of where visitors click, how far they scroll, how long each part of a page is on screen and where the pointer goes, across the recorded visits to one page. Computed from recordings, so they keep what recordings keep and need analytics.sessions.read. Every figure is per page visit; horizontal positions count from the centre of the viewport.
paths:
/v1/sites/{siteId}/pages:
parameters:
- $ref: '#/components/parameters/SiteId'
get:
tags:
- Heatmaps
operationId: listHeatmapPages
summary: List pages with visits
description: The site's pages that recorded visits showed in a period, most visited first, by device. A recording is indexed shortly after it ends. Needs analytics.sessions.read.
parameters:
- $ref: '#/components/parameters/HeatmapFrom'
- $ref: '#/components/parameters/HeatmapTo'
- name: limit
in: query
required: false
schema:
type: integer
minimum: 1
maximum: 500
default: 100
responses:
'200':
description: Pages
content:
application/json:
schema:
type: object
required:
- from
- to
- pages
properties:
from:
type: string
format: date-time
to:
type: string
format: date-time
pages:
type: array
items:
$ref: '#/components/schemas/HeatmapPage'
'400':
$ref: '#/components/responses/InvalidQuery'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
/v1/sites/{siteId}/pages/changes:
parameters:
- $ref: '#/components/parameters/SiteId'
get:
tags:
- Heatmaps
operationId: listLayoutChanges
summary: List the days a page's layout changed
description: 'Each day whose most common layout differs from the previous day the page was visited: when the page changed, for comparing the week before with the week after. Days are in tz, or the site''s time zone. Needs analytics.sessions.read.'
parameters:
- $ref: '#/components/parameters/HeatmapPath'
- name: bucket
in: query
required: false
description: One device; every device when left out.
schema:
$ref: '#/components/schemas/HeatmapBucket'
- $ref: '#/components/parameters/HeatmapFrom'
- $ref: '#/components/parameters/HeatmapTo'
- name: tz
in: query
required: false
description: An IANA time zone for the days.
schema:
type: string
example: Europe/London
responses:
'200':
description: Layout changes
content:
application/json:
schema:
type: object
required:
- path
- timezone
- changes
properties:
path:
type: string
timezone:
type: string
changes:
type: array
items:
type: object
required:
- day
- from
- to
properties:
day:
type: string
format: date
from:
type:
- string
- 'null'
to:
type:
- string
- 'null'
'400':
$ref: '#/components/responses/InvalidQuery'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
/v1/sites/{siteId}/heatmaps:
parameters:
- $ref: '#/components/parameters/SiteId'
get:
tags:
- Heatmaps
operationId: getHeatmap
summary: Get a page's heatmap
description: Attention, scroll reach, clicks and movement for one page and device over a period, from at most 20,000 of its visits (a deterministic sample when there are more), with the visit to draw it over. Fewer than 30 visits is flagged small_sample. Needs analytics.sessions.read.
parameters:
- $ref: '#/components/parameters/HeatmapPath'
- $ref: '#/components/parameters/HeatmapBucketParam'
- $ref: '#/components/parameters/HeatmapFrom'
- $ref: '#/components/parameters/HeatmapTo'
responses:
'200':
description: Heatmap
content:
application/json:
schema:
$ref: '#/components/schemas/Heatmap'
'400':
$ref: '#/components/responses/InvalidQuery'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
/v1/sites/{siteId}/heatmaps/compare:
parameters:
- $ref: '#/components/parameters/SiteId'
get:
tags:
- Heatmaps
operationId: compareHeatmaps
summary: Compare two periods
description: One page and device over two periods, with the targets clicked in both and how their rate changed. overlay_valid says both periods have the same most common layout, so a difference overlay on one page means something; across a redesign, show them side by side. Needs analytics.sessions.read.
parameters:
- $ref: '#/components/parameters/HeatmapPath'
- $ref: '#/components/parameters/HeatmapBucketParam'
- name: a_from
in: query
required: true
schema:
type: string
format: date-time
- name: a_to
in: query
required: true
schema:
type: string
format: date-time
- name: b_from
in: query
required: true
schema:
type: string
format: date-time
- name: b_to
in: query
required: true
schema:
type: string
format: date-time
responses:
'200':
description: Comparison
content:
application/json:
schema:
type: object
required:
- a
- b
- overlay_valid
- elements
properties:
a:
$ref: '#/components/schemas/Heatmap'
b:
$ref: '#/components/schemas/Heatmap'
overlay_valid:
type: boolean
elements:
type: array
items:
type: object
required:
- selector
- a
- b
- change
properties:
selector:
type: string
a:
type: number
description: Clicks per visit in the first period.
b:
type: number
description: Clicks per visit in the second period.
change:
type: number
'400':
$ref: '#/components/responses/InvalidQuery'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
components:
parameters:
HeatmapPath:
name: path
in: query
required: true
description: The page's path, without a query string or fragment.
schema:
type: string
example: /pricing
HeatmapFrom:
name: from
in: query
required: false
description: The period's start; with to, at most 93 days. Both left out is the seven days to now.
schema:
type: string
format: date-time
HeatmapBucketParam:
name: bucket
in: query
required: true
schema:
$ref: '#/components/schemas/HeatmapBucket'
SiteId:
name: siteId
in: path
required: true
schema:
type: string
format: uuid
HeatmapTo:
name: to
in: query
required: false
description: The period's end, not included.
schema:
type: string
format: date-time
responses:
NotFound:
description: No such object in this organisation (`not_found`).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
Forbidden:
description: The credential lacks the permission or scope, names another organisation, or belongs to a partner integration that is not active (`forbidden`, `insufficient_scope`, `integration_inactive`).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
InvalidQuery:
description: An unknown, repeated or malformed query parameter (`invalid_query`).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
Unauthorized:
description: No credential, an invalid one, an expired partner integration key, or a delegated token where none is accepted (`unauthorized`, `invalid_api_key`, `api_key_expired`, `delegated_not_allowed`).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
schemas:
HeatmapBackground:
type: object
required:
- recording_id
- epoch_index
- started_at
- offset_ms
- duration_ms
- layout_hash
- viewport_width
- viewport_height
properties:
recording_id:
type: string
format: uuid
epoch_index:
type: integer
started_at:
type: string
format: date-time
offset_ms:
type: integer
description: Where the visit starts in its recording, in milliseconds from the recording's first event, as the replay player counts them.
duration_ms:
type: integer
description: How long the visit lasted.
layout_hash:
type:
- string
- 'null'
viewport_width:
type: integer
viewport_height:
type: integer
Heatmap:
type: object
required:
- path
- bucket
- from
- to
- visits
- sampled
- small_sample
- visibility_known
- seconds_on_screen
- layouts
- background
- backgrounds
- bands
- clicks
- moves
properties:
path:
type: string
bucket:
$ref: '#/components/schemas/HeatmapBucket'
from:
type: string
format: date-time
to:
type: string
format: date-time
visits:
type: integer
description: Page visits in the period.
sampled:
type: integer
description: The visits the totals come from, at most 20000.
small_sample:
type: boolean
description: Fewer than 30 visits.
visibility_known:
type: number
description: The share of visits whose time excludes a hidden tab (SDK 0.5.0).
seconds_on_screen:
type: object
required:
- mean
- median
properties:
mean:
type: number
median:
type: number
layouts:
type: array
description: The layouts seen, most common first.
items:
type: object
required:
- hash
- visits
properties:
hash:
type:
- string
- 'null'
visits:
type: integer
background:
description: The visit whose page at load the heatmap is drawn over; play it through the playback routes.
anyOf:
- $ref: '#/components/schemas/HeatmapBackground'
- type: 'null'
backgrounds:
type: array
description: 'The visits the heatmap can be drawn over, background first: of the most common layout, at a width near the period''s median, and of those the ones that scrolled furthest. At most 5.'
items:
$ref: '#/components/schemas/HeatmapBackground'
bands:
type: object
required:
- px
- attention_share
- ms_per_visit
- reach
properties:
px:
type: integer
description: The height of a band.
attention_share:
type: array
items:
type: number
description: Per band from the top, the share of a visit's time it was on screen.
ms_per_visit:
type: array
items:
type: number
reach:
type: array
items:
type: number
description: Per band, the share of visits that scrolled to its bottom.
clicks:
type: object
required:
- per_visit
- fixed_per_visit
- cell_px
- cells
- fixed_cells
- elements
properties:
per_visit:
type: number
fixed_per_visit:
type: number
description: Clicks on fixed or sticky elements, which belong to the screen rather than a place on the page.
cell_px:
type: integer
cells:
type: array
items:
$ref: '#/components/schemas/HeatmapCell'
fixed_cells:
type: array
items:
$ref: '#/components/schemas/HeatmapCell'
elements:
type: array
description: The targets most clicked, named without text.
items:
type: object
required:
- selector
- clicks
- per_visit
- fixed
- located
- offsets
- cells
properties:
selector:
type: string
clicks:
type: integer
per_visit:
type: number
fixed:
type: boolean
description: Whether most of its clicks landed on it while fixed or sticky. located, offsets and cells cover those clicks only.
located:
type: integer
description: How many of its clicks carry where within the target they landed (SDK 0.5.0).
offsets:
type: array
description: A sample of the located clicks, where within the target each landed, 0 to 10000 across and down.
items:
type: array
items:
type: integer
minItems: 2
maxItems: 2
cells:
type: array
description: The located clicks in the page grid (the fixed grid when fixed), per visit. Drawing them inside the target's box instead, take these out of cells or fixed_cells so they are not counted twice.
items:
$ref: '#/components/schemas/HeatmapCell'
moves:
type: object
required:
- cell_px
- cells
properties:
cell_px:
type: integer
cells:
type: array
items:
$ref: '#/components/schemas/HeatmapCell'
description: Milliseconds per visit the pointer rested in each cell.
HeatmapBucket:
type: string
enum:
- mobile
- tablet
- desktop
description: By viewport width when the visit began, under 768, under 1280, and wider.
Error:
type: object
required:
- error
properties:
error:
type: object
required:
- code
- message
- docs
properties:
code:
type: string
description: Stable machine-readable code.
message:
type: string
description: Human-readable explanation; do not parse.
docs:
type: string
format: uri
request_id:
type: string
HeatmapPage:
type: object
required:
- path
- visits
- mobile
- tablet
- desktop
properties:
path:
type: string
visits:
type: integer
mobile:
type: integer
tablet:
type: integer
desktop:
type: integer
HeatmapCell:
type: array
description: '[x, y, value]: x cells from the centre of the viewport (negative to the left), y cells from the top of the page (of the viewport for fixed clicks), and the value per visit.'
items:
type: number
minItems: 3
maxItems: 3
securitySchemes:
apiKey:
type: http
scheme: bearer
bearerFormat: if_live_ platform API key
description: 'A platform API key minted in the portal. Its scopes are its
permissions - `analytics:sites:read`, `analytics:sites:write` and the
other `analytics:` scopes, or `analytics:*` - and it acts only in the
organisation it was minted for. Keys without the scope a route needs
are refused with 403.
'
bearerAuth:
type: http
scheme: bearer
bearerFormat: Warden JWT
description: 'A Warden user token. Each route also requires a tenant permission in
the acting tenant (`X-Ironfang-Tenant`), resolved live from Warden,
which each operation names: sites need `analytics.sites.read` to read
and `analytics.sites.write` to change; sessions, recordings and
heatmaps need `analytics.sessions.read`, and deleting a session or a
recording `analytics.sessions.delete`. A missing permission is 403; a
permission lookup failure is 503.
'
externalDocs:
description: Ironfang Analytics documentation
url: https://ironfang.com/analytics/docs