ReadershipReport
The owner's readership dashboard data. `file`, `tier` and `summary` are always present; the other sections follow the OWNER's plan (`tier`): Basic adds `effectivePages`, `viewsOverTime`, `funnel`, `referrers`, `browsers`, `sources`, `viewerModes`, `peakTimes`, `devices` and `countries`; Pro adds per-viewer `sessions` (with `variants` when the file has link variants) and, when configured, `hotspotTaps` and `ctaTaps`. Sections above the plan are omitted, not empty.
Properties
| Name | Type | Description |
|---|---|---|
| file | object | |
| tier | string | The owner's plan, which decides which sections are present. |
| summary | object | |
| variants | array | Pro only, when the file has link variants: per-variant readership. |
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://artifacts.apis.io/everypage-co/json-schema/everypage-co-readership-report-schema.json",
"title": "ReadershipReport",
"description": "The owner's readership dashboard data. `file`, `tier` and `summary` are always present; the other sections follow the OWNER's plan (`tier`): Basic adds `effectivePages`, `viewsOverTime`, `funnel`, `referrers`, `browsers`, `sources`, `viewerModes`, `peakTimes`, `devices` and `countries`; Pro adds per-viewer `sessions` (with `variants` when the file has link variants) and, when configured, `hotspotTaps` and `ctaTaps`. Sections above the plan are omitted, not empty.",
"x-generated": "2026-11-07",
"x-method": "derived",
"x-generator": "derive-json-schema.py",
"x-source": "openapi/everypage-openapi.json#/components/schemas/ReadershipReport",
"type": "object",
"required": [
"file",
"tier",
"summary"
],
"properties": {
"file": {
"$ref": "#/$defs/File"
},
"tier": {
"type": "string",
"enum": [
"free",
"basic",
"pro"
],
"description": "The owner's plan, which decides which sections are present."
},
"summary": {
"type": "object",
"properties": {
"totalViews": {
"type": "integer"
},
"totalSessions": {
"type": "integer"
},
"uniqueVisitors": {
"type": "integer"
},
"uniqueCountries": {
"type": "integer"
},
"avgTimeMs": {
"type": "integer"
},
"downloads": {
"type": "integer"
}
}
},
"variants": {
"type": "array",
"description": "Pro only, when the file has link variants: per-variant readership.",
"items": {
"type": "object",
"properties": {
"uuid": {
"type": "string",
"format": "uuid"
},
"label": {
"type": "string",
"description": "Omitted after GDPR redaction."
},
"sessions": {
"type": "integer"
},
"avgTimeMs": {
"type": "integer"
},
"revoked": {
"type": "boolean"
},
"redacted": {
"type": "boolean"
}
}
}
}
},
"additionalProperties": true,
"$defs": {
"File": {
"type": "object",
"properties": {
"uuid": {
"type": "string",
"format": "uuid"
},
"shortId": {
"type": "string",
"description": "Short share-URL alias; absent on files created before short IDs."
},
"slug": {
"type": "string",
"description": "Vanity link name (Pro); absent unless set. Resolves only on the owner's custom domain."
},
"originalName": {
"type": "string"
},
"size": {
"type": "integer",
"format": "int64",
"description": "Bytes"
},
"mimeType": {
"type": "string"
},
"createdAt": {
"type": "string",
"format": "date-time"
},
"updatedAt": {
"type": "string",
"format": "date-time"
},
"deleteAt": {
"type": "string",
"format": "date-time",
"description": "Absent when the file never expires."
},
"viewCount": {
"type": "integer"
},
"totalPages": {
"type": "integer"
},
"viewerMode": {
"type": "string",
"description": "How readers see the document. `scroll` is a continuous vertical column of every page.",
"enum": [
"standard",
"scroll",
"flipbook",
"swipe",
"magazine"
]
},
"protected": {
"type": "boolean",
"description": "True if a password is set."
},
"allowDownload": {
"type": "boolean"
},
"requireEmail": {
"type": "boolean"
},
"notifyOnView": {
"type": "boolean"
},
"commentsEnabled": {
"type": "boolean",
"description": "Reader feedback notes are on (Pro to enable)."
},
"commentsAllowPublic": {
"type": "boolean",
"description": "Commenters may opt into public display of their note."
},
"notifyOnComment": {
"type": "boolean",
"description": "The owner is emailed (throttled) when a note arrives."
},
"askReceipt": {
"type": "boolean",
"description": "Viewers are asked to confirm receipt (Basic+ to enable)."
},
"showExpiry": {
"type": "boolean",
"description": "Readers see a live \"Expires in\" countdown next to Download (default true, every plan). When false the public share-link metadata omits the expiry instant entirely."
},
"marksEnabled": {
"type": "boolean",
"description": "Proofing page marks are on (Pro to enable)."
},
"annotationsEnabled": {
"type": "boolean",
"description": "Proofing annotations are on (Pro to enable)."
},
"viewLimit": {
"type": "integer",
"description": "Self-destruct cap (Basic+). Absent when unlimited."
},
"viewsConsumed": {
"type": "integer",
"description": "Views consumed against `viewLimit` (always present, 0 when no limit)."
},
"burnedAt": {
"type": "string",
"format": "date-time",
"description": "Present once the view-limit sweep destroyed the blob; the row and its readership survive, and content replacement un-burns it."
},
"underReview": {
"type": "boolean",
"description": "Present (true) while the document is paused for abuse review. The owner can still read it (this DTO, the content, readership); every write to it - settings, content, hotspots, assets, link variants, delete - answers 403 with detail \"This document is under review\" (code `forbidden`) until a person has reviewed it. Email support@everypage.co with the link to ask."
},
"pausedAt": {
"type": "string",
"format": "date-time",
"description": "When the pause began. Present with `underReview`."
},
"reviewReasons": {
"type": "array",
"items": {
"type": "string",
"enum": [
"reports",
"unsafe_link",
"automatic_check"
]
},
"description": "Why the document is paused, as distinct kinds in this order - `reports` (readers reported it), `unsafe_link` (Google Web Risk lists a link in it), `automatic_check` (the hosted-page upload scan). Absent when the pause carries no open flag (a manual pause) and when not under review."
},
"gateDomains": {
"type": "array",
"items": {
"type": "string"
},
"description": "Email-gate domain allowlist (Pro). Absent when any domain is accepted."
},
"gateFields": {
"type": "array",
"items": {
"$ref": "#/$defs/GateField"
},
"description": "The stored lead-capture form definition (Pro). Absent when the gate is the plain email prompt."
},
"gateHeading": {
"type": "string",
"description": "The owner's heading for the gate card readers see before the document opens (Pro). Absent when the default wording applies."
},
"gateMessage": {
"type": "string",
"description": "The owner's explanatory line on the gate card (Pro). Absent when the default wording applies."
},
"watermark": {
"type": "boolean",
"description": "Viewer pages are stamped with the reader identity (Pro)."
},
"viewerSettings": {
"type": "object",
"additionalProperties": true,
"description": "The stored appearance/behaviour blob exactly as saved (see the FileSettings.viewerSettings description); `{}` when never customised. Always present for the owner regardless of current plan."
},
"shareDomain": {
"type": "string",
"description": "The owner's verified Pro custom domain that share links and embeds are built on. Absent when links use everypage.co."
},
"folderId": {
"type": "string",
"format": "uuid",
"description": "UUID of the folder the file is filed in. Absent when unfiled."
},
"anonShareable": {
"type": "boolean",
"description": "True for owner-less files that are public-by-link (browser anonymous uploads, Canva imports). Always false once claimed."
},
"revisions": {
"type": "array",
"items": {
"$ref": "#/$defs/Revision"
},
"description": "Replacement history - superseded content versions, newest first. Populated only by GET /api/v1/files/{uuid}; absent in the list and when the content was never replaced."
},
"pageRange": {
"allOf": [
{
"$ref": "#/$defs/PageRange"
}
],
"description": "Present when a page range limits non-owner viewers (absent = the full document serves). Enforced regardless of your current plan (see the setting's description); owners always get the full document.\n"
},
"contentVersion": {
"type": "integer",
"description": "Counts in-place content replacements (1 = the original upload)."
},
"palette": {
"$ref": "#/$defs/Palette"
},
"canvaDesignId": {
"type": "string",
"description": "The Canva design this file was published from. Absent on files with no design binding (including after a detach)."
},
"canvaUpdatesEnabled": {
"type": "boolean",
"description": "Whether a Canva-side republish of the bound design may replace this file's bytes (see the setting). Present only alongside canvaDesignId."
}
},
"description": "The owner's view of a file (`FileResponse`). Optional fields are omitted when empty rather than sent as null. `revisions` is populated only by the single-file GET, never in the list."
},
"GateField": {
"type": "object",
"description": "One field of a lead-capture gate form. A form holds 1-10 fields, exactly one of type email (always first and required).",
"required": [
"key",
"label",
"type"
],
"properties": {
"key": {
"type": "string",
"pattern": "^[a-z][a-z0-9_]{0,39}$",
"description": "Unique snake_case key; submitted values and captured responses are keyed by it."
},
"label": {
"type": "string",
"minLength": 1,
"maxLength": 300
},
"type": {
"type": "string",
"enum": [
"text",
"email",
"phone",
"company",
"select"
],
"description": "`select` is a drop-down: the viewer picks exactly one of `options`. Text, phone and company values are capped at 500 characters."
},
"required": {
"type": "boolean"
},
"options": {
"type": "array",
"minItems": 2,
"maxItems": 20,
"items": {
"type": "string",
"minLength": 1,
"maxLength": 100
},
"description": "The drop-down choices (type `select` only; unique). Omitted for every other type."
}
}
},
"PageRange": {
"type": "object",
"description": "A non-owner page window, 1-based and inclusive. `{\"from\":0,\"to\":0}` is the explicit \"no range\" value (clears the file-level range; as a variant override it serves the full document through that variant).\n",
"properties": {
"from": {
"type": "integer",
"minimum": 0,
"description": "First shared page (1-based)."
},
"to": {
"type": "integer",
"minimum": 0,
"maximum": 20000,
"description": "Last shared page (inclusive; must be >= from)."
}
}
},
"Palette": {
"type": "array",
"description": "Colour palette extracted from the document at import time: hex swatches (\"#rrggbb\"), dominant colour first, at most 6. ADVISORY ONLY - extraction is best-effort (first-page embedded raster images, short time budget), so the field is simply absent for vector-only documents, for files uploaded through non-import paths, for files created before the feature, and whenever extraction fails or times out. Absence is normal, never an error; use the palette for theming (e.g. styling a share card), never for logic.\n",
"items": {
"type": "string"
}
},
"Revision": {
"type": "object",
"description": "One superseded content version of a file (see `File.revisions`).",
"properties": {
"version": {
"type": "integer",
"description": "The content version this entry was (1 = the original upload)."
},
"originalName": {
"type": "string"
},
"size": {
"type": "integer",
"format": "int64",
"description": "Bytes"
},
"totalPages": {
"type": "integer"
},
"createdAt": {
"type": "string",
"format": "date-time",
"description": "When this version was uploaded."
}
}
}
}
}
Work with this as data
Every JSON Schema 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 schemas
4 MCP tools reach this
find_json_schemasBrowse and filter every JSON Schema in the catalog.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.
Call it yourself
curl for this page
curl "https://apis.io/api/v1/json-schemas/everypage-co-readership-report"
curl "https://apis.io/api/v1/json-schemas?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.