# Create an ad visibility analysis Source: https://developers.eyequant.com/api-reference/create-ad-visibility POST /ad-visibility Submit an ad image to score how visible it is. Create an ad visibility analysis from an ad image. The request returns immediately with an `id` — analyses are processed asynchronously, so poll [Get an ad visibility analysis](/api-reference/get-ad-visibility) for the score. The ad to analyze. The ad image, encoded as a base64 string. The title of the ad or its analysis. The unique identifier for the new ad visibility analysis. The full URL where the result can be retrieved. ```bash cURL theme={null} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ -H "Content-Type: application/json" \ -d '{ "input": { "content": "iVBORw0KGgoAAA[...]", "title": "Example ad analysis" } }' \ https://api.eyequant.com/v2/ad-visibility ``` ```json 201 theme={null} { "location": "https://api.eyequant.com/v2/ad-visibility/3bdecb551a40414d9e80198744df08a5", "id": "3bdecb551a40414d9e80198744df08a5" } ``` ```json 400 theme={null} { "error": { "code": "invalid_configuration", "message": "The value you provided as content is not a valid image." } } ``` # Create an analysis Source: https://developers.eyequant.com/api-reference/create-analysis POST /analyses Submit a web page URL or an uploaded image to start a visual attention analysis. Create an analysis for an image or a web page URL. The request returns immediately with `201 Created`, the new analysis `id`, and a `location` URL (also returned in the `Location` response header). Poll [Get an analysis](/api-reference/get-analysis) with the returned `id` to retrieve the result. For the underlying concepts, see the [Input model](/concepts/input-model) and [Predictions model](/concepts/predictions-model). The input to analyze. `image` or `webPageUrl`. For `image`, a Base64-encoded PNG or JPEG. For `webPageUrl`, the page URL. `desktopWeb`, `mobileWeb`, or `generic`. A label for the analysis (1–2048 characters). `webPageUrl` only. Attempt to remove cookie banners before capture. Which predictions to run and which outputs to return. Defaults to `{ "attention": { "outputs": ["attentionMap"] } }`. Any of `attentionMap`, `perceptionMap`, `hotspotsMap`. Any of `score`, `map`. Any of `score`, `map`. The id of the new analysis. Use it to poll for results. The URL where the analysis result can be retrieved (also returned in the `Location` header). ```bash cURL theme={null} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ -H "Content-Type: application/json" \ -d '{ "input": { "type": "image", "content": "iVBORw0KGgoAAAANSUhE....FTkSuQmCC", "medium": "desktopWeb", "title": "Example" }, "predictions": { "attention": { "outputs": ["attentionMap", "perceptionMap"] }, "clarity": { "outputs": ["score", "map"] } } }' \ https://api.eyequant.com/v2/analyses ``` ```json 201 theme={null} { "id": "611457618c1d4283a830d10a9ad4f8ae", "location": "https://api.eyequant.com/v2/analyses/611457618c1d4283a830d10a9ad4f8ae" } ``` ```json 400 theme={null} { "error": { "code": "invalid_request", "message": "Invalid request." } } ``` # Create a video analysis Source: https://developers.eyequant.com/api-reference/create-video-analysis POST /analyses/video Submit a video for per-frame visual saliency analysis. Create a visual saliency analysis for a video. The request returns `201 Created` with the new `id` and a `location` URL (also returned in the `Location` response header). Poll [Get a video analysis](/api-reference/get-video-analysis) with the returned `id` to retrieve the result. Video analysis is gated by the `dynamic-saliency` add-on. If it is not enabled for your account, this endpoint returns `404`. Contact [sales@eyequant.com](mailto:sales@eyequant.com) to enable it. The video `content` must be an AWS S3 URL presigned by EyeQuant. See [Analyze videos](/guides/analyzing-videos) for how to obtain one and the supported video requirements. The video input specification. The URL to the video. Currently only AWS S3 URLs presigned by EyeQuant are allowed. The title of the video. The id of the new video analysis. The URL where the result can be retrieved (also returned in the `Location` header). ```bash cURL theme={null} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ -H "Content-Type: application/json" \ -d '{"input":{ "content":"https://s3.example.com/video-test-eyequant/users/EQWML/7ee3f6ce-a259-46e9-8eae-7964b56ca004-vi-0", "title":"The video title." }}' \ https://api.eyequant.com/v2/analyses/video ``` ```json 201 theme={null} { "id": "eddec58c-b843-4c8e-a6dd-19155094a1a7", "location": "https://api.eyequant.com/v2/analyses/video/eddec58c-b843-4c8e-a6dd-19155094a1a7" } ``` ```json 400 theme={null} { "error": { "code": "invalid_request", "message": "Invalid request." } } ``` ```json 404 theme={null} { "error": { "code": "resource_not_found", "message": "We could not find an analysis for the given id." } } ``` # Generate recommendations Source: https://developers.eyequant.com/api-reference/generate-recommendations POST /analyses/recommendations/{analysis-id} Trigger asynchronous generation of actionable design recommendations for an analysis. Trigger asynchronous generation of recommendations — a set of concrete, actionable suggestions for improving the design. After triggering, poll [Get recommendations](/api-reference/get-recommendations) until `status` is `completed`. For richer recommendations, set context first with [Update analysis metadata](/api-reference/update-analysis-meta). The `analysis-id` path parameter is the analysis id returned as `_internal_exposed_id` from [Get an analysis](/api-reference/get-analysis) — not the top-level `id` returned when you create an analysis. The analysis id (`_internal_exposed_id` from Get an analysis). Whether the request was accepted. Generation status: `started` or `processing`. Human-readable status message. ```bash cURL theme={null} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ https://api.eyequant.com/v2/analyses/recommendations/$analysisId ``` ```javascript JavaScript theme={null} const baseUrl = 'https://api.eyequant.com/v2'; const response = await fetch(`${baseUrl}/analyses/recommendations/${analysisId}`, { method: 'POST', headers: { Authorization: `Bearer ${apiKey}` }, }); const recommendationsStatus = await response.json(); ``` ```json started theme={null} { "success": true, "status": "started", "msg": "Recommendation generation started" } ``` ```json 404 theme={null} { "success": false, "msg": "analysis_not_found" } ``` # Generate a summary Source: https://developers.eyequant.com/api-reference/generate-summary POST /analyses/summary/{analysis-id} Trigger asynchronous generation of a written summary for an analysis. Trigger asynchronous generation of a written summary for an analysis. After triggering, poll [Get a summary](/api-reference/get-summary) until `status` is `completed`. For richer summaries, set context first with [Update analysis metadata](/api-reference/update-analysis-meta). The `analysis-id` path parameter is the analysis id returned as `_internal_exposed_id` from [Get an analysis](/api-reference/get-analysis) — not the top-level `id` returned when you create an analysis. The analysis id (`_internal_exposed_id` from Get an analysis). Whether the request was accepted. Generation status: `started` or `processing`. Human-readable status message. ```bash cURL theme={null} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ https://api.eyequant.com/v2/analyses/summary/$analysisId ``` ```javascript JavaScript theme={null} const baseUrl = 'https://api.eyequant.com/v2'; const response = await fetch(`${baseUrl}/analyses/summary/${analysisId}`, { method: 'POST', headers: { Authorization: `Bearer ${apiKey}` }, }); const summaryStatus = await response.json(); ``` ```json started theme={null} { "success": true, "status": "started", "msg": "Summary generation started" } ``` ```json 404 theme={null} { "success": false, "msg": "analysis_not_found" } ``` ```json 410 theme={null} { "success": false, "status": "expired", "msg": "analysis_expired" } ``` # Get an ad visibility analysis Source: https://developers.eyequant.com/api-reference/get-ad-visibility GET /ad-visibility/{id} Retrieve the status and ad visibility score of a submitted ad analysis. Retrieve an ad visibility analysis by its `id`. Poll until `status` is `success` or `failed`. On success, `outputs` contains the visibility `score` and a link to the input ad image. Analyses become unavailable one hour after completion, returning `410 Gone` (see [Result expiry](/concepts/result-expiry)). The request ID returned when the ad visibility job was created. The analysis identifier. The current state: `pending`, `success`, or `failed`. Present when `status` is `success`. Contains the ad visibility `score` and the `input` image URL. Present when `status` is `failed`. Contains an error `code` and `message`. ```bash cURL theme={null} curl \ -H "Authorization: Bearer $apikey" \ -H "Content-Type: application/json" \ -X GET \ https://api.eyequant.com/v2/ad-visibility/611457618c1d4283a830d10a9ad4f8ae ``` ```json pending theme={null} { "id": "611457618c1d4283a830d10a9ad4f8ae", "status": "pending" } ``` ```json success theme={null} { "id": "611457618c1d4283a830d10a9ad4f8ae", "status": "success", "outputs": { "score": 78, "input": "https://s3.amazonaws.com/api-eyequant/..." } } ``` ```json failed theme={null} { "id": "611457618c1d4283a830d10a9ad4f8ae", "status": "failed", "error": { "code": "unreadable_input_image", "message": "We were unable to read the input image, either because the format is not supported, or because the image is truncated or corrupted." } } ``` # Get an analysis Source: https://developers.eyequant.com/api-reference/get-analysis GET /analyses/{analysis-id} Retrieve the status and outputs of a previously submitted analysis. Retrieve an analysis by its id. Because analyses are processed asynchronously, poll this endpoint until `status` is `success` or `failed`. Output URLs are time-limited — download and store them promptly. See [Result expiry](/concepts/result-expiry). Which keys appear under `outputs` depends on the predictions you requested. See the [Predictions model](/concepts/predictions-model). **`id` vs `_internal_exposed_id`** — `id` is the screenshot id (the same id returned by [Create an analysis](/api-reference/create-analysis) and used to request this analysis). `_internal_exposed_id` is the analysis id, which you need to [update metadata](/api-reference/update-analysis-meta) or request a [summary](/api-reference/get-summary) or [recommendations](/api-reference/get-recommendations). The screenshot id returned by Create an analysis. The screenshot id. The analysis id. Use this when updating analysis metadata or requesting generated summaries and recommendations. Present on success. The current state of the analysis: `pending`, `success`, or `failed`. Present when `status` is `success`. The keys depend on the predictions requested. `attentionMap`, `perceptionMap`, `hotspotsMap`, and `roiMap` (when regions of interest are defined) image URLs. The clarity `score` (0–100) and `map` image URL. The excitingness `score` (0–100) and `map` image URL. The analyzed input `image` URL. Present when `status` is `failed`. Contains an error `code` and `message`. ```bash cURL theme={null} curl \ -H "Authorization: Bearer $apikey" \ -H "Content-Type: application/json" \ -X GET \ https://api.eyequant.com/v2/analyses/611457618c1d4283a830d10a9ad4f8ae ``` ```json success theme={null} { "id": "611457618c1d4283a830d10a9ad4f8ae", "_internal_exposed_id": "0b9c2e7a1f4d4a9e8c2b6d5f3a1e7c90", "status": "success", "outputs": { "attention": { "attentionMap": "https://s3.amazonaws.com/api-eyequant/...", "perceptionMap": "https://s3.amazonaws.com/api-eyequant/...", "hotspotsMap": "https://s3.amazonaws.com/api-eyequant/..." }, "clarity": { "score": 71, "map": "https://s3.amazonaws.com/api-eyequant/..." }, "excitingness": { "score": 64, "map": "https://s3.amazonaws.com/api-eyequant/..." }, "input": { "image": "https://s3.amazonaws.com/api-eyequant/..." } } } ``` ```json pending theme={null} { "id": "611457618c1d4283a830d10a9ad4f8ae", "status": "pending" } ``` ```json failed theme={null} { "id": "611457618c1d4283a830d10a9ad4f8ae", "status": "failed", "error": { "code": "unreadable_input_image", "message": "We were unable to read the input image, either because the format is not supported, or because the image is truncated or corrupted." } } ``` ```json 410 theme={null} { "error": { "code": "resource_gone", "message": "This resource is no longer available." } } ``` # Get recommendations Source: https://developers.eyequant.com/api-reference/get-recommendations GET /analyses/recommendations/{analysis-id} Retrieve generated recommendations, or their current generation status. Retrieve generated recommendations, or the current generation status. When `status` is `completed`, the `data` field holds the recommendations as a Markdown string. Tasks older than one hour return `410 Gone`. The `analysis-id` path parameter is the analysis id returned as `_internal_exposed_id` from [Get an analysis](/api-reference/get-analysis). The analysis id (`_internal_exposed_id` from Get an analysis). Whether the request succeeded. One of `started`, `processing`, `completed`, `failed`, or `expired`. The recommendations content as a Markdown string. Present only when `status` is `completed`. Human-readable status message. Present when `status` is not `completed`. ```bash cURL theme={null} curl \ -H "Authorization: Bearer $apikey" \ -X GET \ https://api.eyequant.com/v2/analyses/recommendations/$analysisId ``` ```javascript JavaScript theme={null} const baseUrl = 'https://api.eyequant.com/v2'; const response = await fetch(`${baseUrl}/analyses/recommendations/${analysisId}`, { headers: { Authorization: `Bearer ${apiKey}` }, }); const recommendations = await response.json(); if (recommendations.status === 'completed') { renderMarkdown(recommendations.data); } ``` ```json completed theme={null} { "success": true, "status": "completed", "data": "## Recommendations\n\n1. Increase contrast on the primary call to action..." } ``` ```json processing theme={null} { "success": true, "status": "processing", "msg": "Recommendation generation in progress" } ``` # Get a summary Source: https://developers.eyequant.com/api-reference/get-summary GET /analyses/summary/{analysis-id} Retrieve a generated summary, or its current generation status. Retrieve a generated summary, or the current generation status. When `status` is `completed`, the `data` field holds the summary as a Markdown string. Tasks older than one hour return `410 Gone`. The `analysis-id` path parameter is the analysis id returned as `_internal_exposed_id` from [Get an analysis](/api-reference/get-analysis). The analysis id (`_internal_exposed_id` from Get an analysis). Whether the request succeeded. One of `started`, `processing`, `completed`, `failed`, or `expired`. The summary content as a Markdown string. Present only when `status` is `completed`. Human-readable status message. Present when `status` is not `completed`. ```bash cURL theme={null} curl \ -H "Authorization: Bearer $apikey" \ -X GET \ https://api.eyequant.com/v2/analyses/summary/$analysisId ``` ```javascript JavaScript theme={null} const baseUrl = 'https://api.eyequant.com/v2'; const response = await fetch(`${baseUrl}/analyses/summary/${analysisId}`, { headers: { Authorization: `Bearer ${apiKey}` }, }); const summary = await response.json(); if (summary.status === 'completed') { renderMarkdown(summary.data); } ``` ```json completed theme={null} { "success": true, "status": "completed", "data": "## Summary\n\nThe page directs attention primarily to the hero and the primary call to action..." } ``` ```json processing theme={null} { "success": true, "status": "processing", "msg": "Summary generation in progress" } ``` # Get a video analysis Source: https://developers.eyequant.com/api-reference/get-video-analysis GET /analyses/video/{analysis-id} Retrieve the status and outputs of a video analysis. Retrieve a video analysis by its `id`. Poll until `status` is `success` or `failed`. On success, `outputs` contains the generated attention map, along with the `title` you supplied and the `created_at` timestamp. Unlike image and URL analyses (which return `410 Gone` one hour after completion), video analyses remain retrievable. Video analysis is gated by the `dynamic-saliency` add-on. If it is not enabled for your account, this endpoint returns `404`. Contact [sales@eyequant.com](mailto:sales@eyequant.com) to enable it. The id for the video analysis received upon its creation. The analysis identifier. The current state: `pending`, `success`, or `failed`. The title you supplied when creating the analysis. When the analysis was created. Present when `status` is `success`. Contains the attention map for the video. Present when `status` is `failed`. Contains an error `code` and `message`. ```bash cURL theme={null} curl \ -H "Authorization: Bearer $apikey" \ -H "Content-Type: application/json" \ -X GET \ https://api.eyequant.com/v2/analyses/video/611457618c1d4283a830d10a9ad4f8ae ``` ```json success theme={null} { "id": "611457618c1d4283a830d10a9ad4f8ae", "status": "success", "title": "The video title.", "outputs": { "attention": { "attentionMap": "https://s3.amazonaws.com/api-eyequant/..." } }, "created_at": "2026-06-01T09:12:43.512000" } ``` ```json pending theme={null} { "id": "611457618c1d4283a830d10a9ad4f8ae", "status": "pending", "created_at": "2026-06-01T09:12:43.512000" } ``` ```json failed theme={null} { "id": "611457618c1d4283a830d10a9ad4f8ae", "status": "failed", "created_at": "2026-06-01T09:12:43.512000", "error": { "code": "input_error", "message": "There's been an error that is related to the provided input medium, e.g. image or video. Please make sure it meets its specific requirements like length, dimensions or file size." } } ``` ```json 404 theme={null} { "error": { "code": "resource_not_found", "message": "We could not find an analysis for the given id." } } ``` # API Reference Source: https://developers.eyequant.com/api-reference/overview A REST API for generating visual attention heatmaps, clarity scores, and excitingness scores for images, web pages, and video. The EyeQuant API is a REST API that runs machine-perception models on your designs and returns visual attention heatmaps, clarity scores, and excitingness scores. Use it to analyze a live web page, an uploaded image, or a video. ## Base URL All endpoints are served under a single versioned base URL: ```text theme={null} https://api.eyequant.com/v2 ``` ## Authentication Every request must include your API key as a bearer token in the `Authorization` header: ```bash theme={null} Authorization: Bearer $apikey ``` You can confirm your credentials and that the service is reachable with [Check API status](/api-reference/status). For full details, see [Authentication](/authentication). ## How analyses work Analyses are processed asynchronously, so working with the API follows a three-step lifecycle: Create an analysis with [Create an analysis](/api-reference/create-analysis) (image or URL) or [Create a video analysis](/api-reference/create-video-analysis). The response returns an `id` immediately. Retrieve the analysis by its `id` until `status` is `success` or `failed`. Poll every few seconds rather than in a tight loop. On success, download the output maps from the URLs in the `outputs` object and store them on your own infrastructure — the links are time-limited. See [Result expiry](/concepts/result-expiry). Every endpoint page below includes an interactive playground. Enter your API key once and send a real request straight from the docs. ## Endpoints Submit a web page URL or an uploaded image for analysis. Poll for status and retrieve the output maps and scores. Run per-frame visual saliency analysis on a video. Verify your credentials and service availability. # Check API status Source: https://developers.eyequant.com/api-reference/status GET / Verify your credentials and confirm the EyeQuant API is operational. Check service availability and verify that your authentication credentials are correct. On success it returns a short confirmation message. Because this endpoint is lightweight and requires authentication, it is a convenient way to verify your API key — for example, in a CI pipeline or at the start of a batch job, before issuing analysis requests. A human-readable confirmation that authentication succeeded and the service is operational. ```bash cURL theme={null} curl \ -X GET \ -H "Authorization: Bearer $apikey" \ https://api.eyequant.com/v2/ ``` ```json 200 theme={null} { "message": "Welcome to the EyeQuant API. You have been authenticated successfully and the service is operational." } ``` ```json 401 theme={null} { "error": { "code": "authentication_failed", "message": "We were unable to authenticate you. Please check your credentials." } } ``` # Search tags Source: https://developers.eyequant.com/api-reference/tag-search GET /tag-search/{resource_type} Search the tags available for a given resource type. Search the tags available for a given resource type. This endpoint was only partially defined in the source API specification. Confirm the exact path, parameters, and response shape against the live API before publishing. The type of resource to search tags for. The tag name. ```bash cURL theme={null} curl \ -X GET \ -H "Authorization: Bearer $apikey" \ https://api.eyequant.com/v2/tag-search/analysis ``` ```json 200 theme={null} [ { "name": "Europe" }, { "name": "Africa" } ] ``` # Get tag summary Source: https://developers.eyequant.com/api-reference/tag-summary GET /tag-summary Get a summary of the tags used across your account. Return a summary of the tags in your account, including how often each tag is used. The tag name. The number of resources that use this tag. ```bash cURL theme={null} curl \ -X GET \ -H "Authorization: Bearer $apikey" \ https://api.eyequant.com/v2/tag-summary ``` ```json 200 theme={null} [ { "name": "Europe", "usageNumber": 987 } ] ``` # Update analysis metadata Source: https://developers.eyequant.com/api-reference/update-analysis-meta PUT /update-meta/screenshot/{analysis-id} Add context such as description, goal, audience, or brand guidelines to an existing analysis. Update metadata for an existing image or URL analysis. Use this to add context — a description, goal, target audience, or brand guidelines — that is stored with the analysis and used by generated [summaries](/api-reference/get-summary) and [recommendations](/api-reference/get-recommendations). This endpoint updates metadata only. It does not rerun the analysis or change the maps and scores returned by [Get an analysis](/api-reference/get-analysis). The `analysis-id` path parameter is the analysis id returned as `_internal_exposed_id` from [Get an analysis](/api-reference/get-analysis) — **not** the top-level `id` returned when you create an analysis. The analysis id (`_internal_exposed_id` from Get an analysis). What the creative, page, or screen is. The user or business outcome the design should support. The audience the design is intended for. Brand, messaging, or design constraints to consider. Supported fields are merged into the existing metadata. Unsupported fields are ignored and returned in `ignored_keys`. The body must be a JSON object up to 64 KB, with individual string values up to 10,000 characters; deeply nested objects are rejected. Whether the update succeeded. The metadata fields accepted by the API. Any unsupported fields that were ignored. ```bash cURL theme={null} curl \ -X PUT \ -H "Authorization: Bearer $apikey" \ -H "Content-Type: application/json" \ -d '{ "description": "Homepage hero", "goal": "Increase sign-ups" }' \ https://api.eyequant.com/v2/update-meta/screenshot/$analysisId ``` ```javascript JavaScript theme={null} const baseUrl = 'https://api.eyequant.com/v2'; await fetch(`${baseUrl}/update-meta/screenshot/${analysisId}`, { method: 'PUT', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${apiKey}`, }, body: JSON.stringify({ description: 'Homepage hero', goal: 'Increase sign-ups', }), }); ``` ```json updated theme={null} { "success": true, "meta": { "description": "Homepage hero", "goal": "Increase sign-ups" } } ``` ```json ignored keys theme={null} { "success": true, "meta": { "description": "Homepage hero" }, "ignored_keys": ["unsupported_field"] } ``` ```json 404 theme={null} { "error": "Resource not found", "resource_type": "screenshot", "resource_id": "0b9c2e7a1f4d4a9e8c2b6d5f3a1e7c90" } ``` # EyeQuant API Authentication: Bearer Tokens and HTTPS Source: https://developers.eyequant.com/authentication EyeQuant uses Bearer token authentication over HTTPS. Learn how to attach your API key to every request and handle off-domain resource links. Every request to the EyeQuant API must be authenticated using Bearer token authentication transmitted over HTTPS. You attach your API key directly to each HTTP request via an `Authorization` header — there are no session cookies, no OAuth flows, and no intermediate login steps. Keep your API key secret and treat it with the same care as a password. All requests to the EyeQuant API must be made over **HTTPS**. Plain HTTP requests will not be accepted. This ensures your API key and all response data remain encrypted in transit. ## Add the Authorization header To authenticate, include the following header in every API request, replacing `$apikey` with your actual API key: ```http theme={null} Authorization: Bearer $apikey ``` Here is a complete cURL example that retrieves the details of an existing analysis: ```bash theme={null} curl \ -X GET \ -H "Authorization: Bearer $apikey" \ https://api.eyequant.com/v2/analyses/YOUR_ANALYSIS_ID ``` Apply this same `Authorization: Bearer $apikey` header pattern to every endpoint you call — `POST`, `GET`, or otherwise. ## Authenticate follow-up links API responses frequently include URLs that point to further resources. The rules for authenticating those URLs differ depending on where they live: * **Links under `api.eyequant.com`** — These are first-party API resources. Send the same `Authorization: Bearer $apikey` header when requesting them, exactly as you would for any other API call. * **Off-domain links (e.g. AWS S3)** — Analysis outputs such as attention heatmap images are served directly from external storage. These URLs already contain time-limited authorization tokens embedded in the query string. Do **not** attach any additional `Authorization` header when downloading them; doing so may cause the request to fail. ## Obtain your API credentials API credentials are not self-serve. To get your API key, reach out to the EyeQuant team at [sales@eyequant.com](mailto:sales@eyequant.com). Once you have your key, store it securely — for example, in an environment variable or a secrets manager — and avoid committing it to source control. # Image Format Requirements, Dimensions, and Size Limits Source: https://developers.eyequant.com/concepts/input-formats EyeQuant accepts PNG and JPEG images up to 5 MB, between 40px and 2000px on any side. PNG is strongly recommended for best results. EyeQuant image analyses require images in a specific format and within certain size limits to produce accurate predictions. Submitting an image that falls outside these boundaries is likely to result in an error or unreliable results, so it is worth validating your images before sending them to the API. ## Supported Formats and Size Requirements To be accepted for analysis, your image must meet all of the following criteria: * **Format:** PNG or JPEG * **File size:** 5 MB or less * **Minimum dimension:** 40px on the shortest side * **Maximum dimension:** 2000px on the longest side PNG is **strongly recommended** over JPEG. Lossy JPEG compression can introduce visual artifacts that affect prediction accuracy. Where you have the choice, always supply a PNG. ## What Happens If Limits Are Exceeded If your image falls outside these criteria, EyeQuant's predictions are unlikely to be accurate. The API will return an error rather than silently produce unreliable results. If your use case requires images that don't fit within these limits — for example, very large or very small canvases — contact EyeQuant to discuss your specific requirements. For the full list of image-related error codes, including `unreadable_input_image`, `invalid_input_image_dimensions`, and `blank_input_image`, see the [Errors reference](/reference/errors). ## Web Page URL Screenshots These format limits apply to directly uploaded images using `type: image`. When you use `type: webPageUrl`, the screenshot is captured by EyeQuant's own screenshot service, which handles sizing and format internally — you do not need to manage image dimensions yourself in that case. # EyeQuant Input Model: Types, Media, and Parameters Source: https://developers.eyequant.com/concepts/input-model Understand EyeQuant's input object — how to specify the type, content, medium, and optional parameters when requesting an analysis. When you create an analysis, you send an `input` object that tells EyeQuant what to analyze and how. This object captures everything the API needs to locate or receive your image, understand how it will be seen by real viewers, and apply any pre-processing steps before predictions are run. ## Input Types The `type` field determines what form your content takes. EyeQuant currently supports two input types: | type | Description | | ------------ | ---------------------------------------------------------------------- | | `webPageUrl` | A URL of a web page. EyeQuant fetches the page and takes a screenshot. | | `image` | A Base64-encoded PNG or JPEG image. | When you use `webPageUrl`, EyeQuant's screenshot service loads the page in a simulated browser and captures the result automatically. When you use `image`, you supply the image data directly as a Base64-encoded string in the `content` field. ## Medium The `medium` field tells EyeQuant's algorithms how the analyzed image is presented to its viewers. Setting this correctly ensures predictions are calibrated to the right viewing context. | medium | Description | | ------------ | ------------------------------------------------- | | `desktopWeb` | Web page viewed in a desktop browser. | | `mobileWeb` | Web page viewed in a mobile browser. | | `generic` | The target medium doesn't fit any other category. | When using the `webPageUrl` input type, only `desktopWeb` and `mobileWeb` are valid medium values. Because the screenshot is always taken from a browser simulation, a `generic` medium is not applicable. ## Title The `title` field is a human-readable label for your input. It is used for display purposes in the EyeQuant web interface and does not affect how predictions are calculated. Giving each input a descriptive title makes it easier to identify analyses later. ## removeCookieBanner The `removeCookieBanner` boolean parameter controls whether EyeQuant's screenshot service attempts to dismiss or remove a cookie consent banner before capturing the page. This is only relevant when using the `webPageUrl` input type. Set it to `true` if you want the screenshot to reflect the page content without an overlay obscuring it. ## Examples The following examples show two common configurations for the `input` object. **Taking a screenshot of a URL and simulating a mobile browser:** ```json theme={null} { "type": "webPageUrl", "content": "http://example.com", "medium": "mobileWeb", "title": "Example" } ``` **Uploading a Base64-encoded PNG of a desktop web mockup:** ```json theme={null} { "type": "image", "content": "iVBORw0KGgo...rkJggg==", "medium": "desktopWeb", "title": "Example" } ``` For details on the image dimensions and file size limits that apply when using `type: image`, see [Image Format Requirements and Size Limits](/concepts/input-formats). # Predictions Model: Attention, Clarity, and Excitingness Source: https://developers.eyequant.com/concepts/predictions-model EyeQuant supports three prediction types — attention, clarity, and excitingness. Learn what each predicts and what outputs are available. The `predictions` field gives you detailed control over what is calculated in an analysis and how results are presented to you. If you omit it entirely, EyeQuant runs an attention analysis with its default outputs. When you include it, you can select one or more prediction types and, optionally, specify exactly which outputs you want back. ## Available Predictions EyeQuant currently supports three prediction types: | Prediction | Description | Default outputs | | -------------- | ---------------------------------------------- | --------------- | | `attention` | Which elements attract viewer attention? | `attentionMap` | | `clarity` | How clear or cluttered is the image perceived? | `score` | | `excitingness` | How exciting is the image perceived? | `score` | ## Attention The attention prediction models which parts of the image are most likely to capture a viewer's gaze. It produces up to three visual outputs: | Output | Description | | --------------- | ---------------------------------------------------------------------------------------- | | `attentionMap` | Heatmap showing predicted fixation density across the image. | | `perceptionMap` | Visualises which areas immediately attract a viewer's attention. | | `hotspotsMap` | Circles mark the most attention-grabbing spots — larger circles indicate more attention. | ## Clarity The clarity prediction measures how clear or cluttered your image is perceived to be. It produces the following outputs: | Output | Description | | ------- | ------------------------------------------------------------------------------------------- | | `score` | 0–100 score quantifying the clarity rating. | | `map` | Highlights how individual areas contribute to the overall perception of clarity or clutter. | ## Excitingness The excitingness prediction estimates how exciting your image is perceived to be. It produces one output: | Output | Description | | ------- | --------------------------------------------------- | | `score` | 0–100 score quantifying the predicted excitingness. | ## Configuring Predictions You configure predictions by passing a `predictions` object where each key is a prediction name and its value is a configuration object. To use a prediction's default outputs, pass an empty object `{}`. To request specific outputs, include an `outputs` array. **Default attention analysis (returns `attentionMap` only):** ```json theme={null} { "attention": {} } ``` **Multiple predictions with specific outputs — clarity with both score and map, plus excitingness with its default:** ```json theme={null} { "clarity": { "outputs": ["score", "map"] }, "excitingness": {} } ``` Currently, all available outputs are returned regardless of which specific outputs you request in the `outputs` array. This behavior may change to returning only the requested outputs without notice in a future version. Build your integration to handle all possible output fields defensively. # Result Expiry: How to Store Your EyeQuant Analysis Outputs Source: https://developers.eyequant.com/concepts/result-expiry EyeQuant analysis results and output maps are stored for a limited time. Download and store all heatmaps and scores on your own infrastructure. EyeQuant stores analysis results for a fixed period after they are produced. Once that window closes, the outputs — including heatmap image URLs and numeric scores — are no longer accessible through the API. It is your responsibility to download and persist any results you need before they expire. ## What Expires The following are all subject to expiry: * **Heatmap and map image URLs** — these are hosted on S3 with time-limited authentication tokens and will stop resolving after the expiry window * **Map downloads** — any visual output file linked from the analysis response * **The analysis resource itself** — the analysis object returned by the API will become unavailable ## What You Need to Do Once an analysis reaches `status: success`, you should immediately download and store: * All map and heatmap image files (fetch each URL and save the file to your own storage) * Any numeric scores returned in the `outputs` object Do not rely on storing just the analysis ID and fetching results later. The outputs will expire and the URLs will stop working. Download everything as soon as the analysis succeeds. ## The `resource_gone` Error If you attempt to retrieve an analysis that has already expired, the API returns a `resource_gone` error code. This is a permanent state — the data cannot be recovered once it has expired. See the [Errors reference](/reference/errors) for the full list of error codes and their meanings. ## Best Practice: Download Inside Your Polling Loop The safest approach is to build result downloading directly into the loop where you check analysis status. That way, you never reach a point where an analysis succeeds but you have not yet captured its outputs. Follow these steps as soon as your polling detects a completed analysis: 1. Poll until `status === 'success'` 2. Extract all URLs from the `outputs` object in the response 3. Download and save each file to your own storage infrastructure 4. Store any numeric scores in your database By handling downloads immediately in step 3, you eliminate the risk of expiry affecting your integration entirely. # Upload a PNG or JPEG Image for Visual Attention Analysis Source: https://developers.eyequant.com/guides/analyzing-images Upload any PNG or JPEG image to EyeQuant as a Base64-encoded string to get full control over exactly which design or asset is analyzed. When you have a design mockup, an exported screenshot, or any other PNG or JPEG asset you want to evaluate, you can upload it directly to EyeQuant rather than relying on a live URL. This gives you complete control over exactly what is analyzed — the image is encoded as a Base64 string and sent in the request body alongside the rest of your analysis configuration. ## Encoding your image Before submitting, you need to convert your image file into a Base64 string. Any standard Base64 encoder will work. On Linux and macOS, you already have the `base64` command-line utility available. Run the following to encode an image and write the result to a file: ```bash theme={null} base64 -i /path/to/image.png > image.png.base64 ``` You can then copy the contents of `image.png.base64` into the `content` field of your request. Convert your PNG or JPEG file to a Base64 string using the tool or library of your choice. The full encoded string — without any line breaks — becomes the value of the `content` field in your request body. Send a `POST` request to `/v2/analyses` with an input `type` of `image`. Paste your Base64-encoded image as the `content` value, and set `medium` to reflect the context in which the design will be viewed. Replace `$apikey` with your API credentials. ```bash theme={null} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ -H "Content-Type: application/json" \ -d '{ "input": { "type": "image", "content": "iVBORw0KGgoAAAANSUhE....FTkSuQmCC", "medium": "desktopWeb", "title": "Example" } }' \ https://api.eyequant.com/v2/analyses ``` The API returns HTTP `201 Created` with the ID and `location` of your new analysis, exactly as it does for URL-based analyses. Poll the `location` URL returned in the previous step with a `GET` request until the `status` field changes from `pending` to `success`. Once the analysis completes, the response body contains output URLs for each requested prediction — by default, an attention heatmap at `outputs.attention.attentionMap`. For a detailed walkthrough of the polling flow, refer to the [Analyze URLs guide](/guides/analyzing-urls). For information on supported file formats, maximum image dimensions, and file size limits, see the [Input Formats reference](/concepts/input-formats). # Submit a Web Page URL for Visual Attention Analysis Source: https://developers.eyequant.com/guides/analyzing-urls Submit any public web page URL to EyeQuant and receive a visual attention heatmap — desktop or mobile browser simulation supported. When you submit a URL to EyeQuant, the API automatically takes a screenshot of the page — simulating either a desktop or mobile browser — and runs its machine perception models against the resulting image. This means you can analyze any live web page with a single API call, without needing to capture or upload a screenshot yourself. Send a `POST` request to `/v2/analyses` with an input `type` of `webPageUrl`. Set `content` to the page you want to analyze, and set `medium` to either `desktopWeb` or `mobileWeb` to control which browser viewport EyeQuant simulates. Replace `$apikey` with your API credentials. ```bash theme={null} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ -H "Content-Type: application/json" \ -d '{ "input": { "type": "webPageUrl", "content": "http://www.google.com", "medium": "desktopWeb", "title": "Example" } }' \ https://api.eyequant.com/v2/analyses ``` A successful request returns HTTP `201 Created` along with the ID and location of the new analysis resource: ```json theme={null} { "location": "https://api.eyequant.com/v2/analyses/611457618c1d4283a830d10a9ad4f8ae", "id": "611457618c1d4283a830d10a9ad4f8ae" } ``` Save the `location` URL — you'll use it to check on progress in the next step. Taking a screenshot and running the analysis both take a few seconds to complete. Send a `GET` request to the `location` URL to check the current status. ```bash theme={null} curl \ -X GET \ -H "Authorization: Bearer $apikey" \ -H "Content-Type: application/json" \ https://api.eyequant.com/v2/analyses/611457618c1d4283a830d10a9ad4f8ae ``` While processing is still underway, the response will show a `pending` status: ```json theme={null} { "id": "611457618c1d4283a830d10a9ad4f8ae", "status": "pending" } ``` Once the analysis finishes successfully, the status changes to `success` and the response includes your output URLs: ```json theme={null} { "id": "611457618c1d4283a830d10a9ad4f8ae", "status": "success", "outputs": { "attention": { "attentionMap": "https://s3.amazonaws.com/api-eyequant/attentionHeatmap.png" } } } ``` Keep polling until the status is no longer `pending`. Once the status is `success`, the `outputs.attention.attentionMap` field contains a URL pointing directly to your generated attention heatmap image. Download or display that image to see where viewers' eyes are predicted to be drawn on the page. ## Additional options **Removing cookie banners:** Pass `"removeCookieBanner": true` in the `input` object to instruct EyeQuant to strip cookie consent banners from the screenshot before running analysis. This is useful when banners would otherwise dominate the predicted attention. **Supported media types:** Only `desktopWeb` and `mobileWeb` are valid values for `medium` when using a `webPageUrl` input. The `generic` media type is only available for image uploads. The URL you submit must be publicly accessible on the internet. EyeQuant's servers cannot reach private networks, localhost addresses, or pages that require authentication. If your URL is not reachable, the analysis will fail. For the full list of accepted parameters — including optional fields for controlling viewport size and more — see the [Input Model reference](/concepts/input-model). # Submit a WebM Video File for Per-Frame Attention Analysis Source: https://developers.eyequant.com/guides/analyzing-videos Upload a .webm video to EyeQuant using a presigned storage URL and poll for per-frame visual attention analysis results across every frame. EyeQuant's video analysis lets you run machine perception predictions across every frame of a recorded screen capture or design walkthrough. You upload your `.webm` file to a secure presigned storage URL associated with your account, then create an analysis that references that upload. Once processing completes, you receive per-frame attention predictions you can use to evaluate your video content. Video files must meet the following requirements before upload: * **Format:** `.webm` only * **Size:** 100 MB or less * **Duration:** 60 seconds or less Install the `requests` library if you haven't already, then define a `BearerTokenAuth` helper class that attaches your API token to every request. Create a persistent session so your credentials carry across all subsequent calls. ```python theme={null} import requests import json import time import os import sys access_token = "YOUR-API-ACCESS-TOKEN" base_url = "https://api.eyequant.com/v2" class BearerTokenAuth(requests.auth.AuthBase): def __init__(self, access_token): self.access_token = access_token def __call__(self, request): request.headers["Authorization"] = "Bearer {}".format(self.access_token) return request api = requests.Session() api.auth = BearerTokenAuth(access_token) ``` Before you can upload your video, you need a presigned URL pointing to the secure storage bucket associated with your EyeQuant account. Fetch one by sending a `GET` request to `/v2/upload-urls`. ```python theme={null} upload_url_response = api.get( base_url + "/upload-urls", data=json.dumps({}), headers={"Content-Type": "application/json"}, ) upload_url = upload_url_response.json()["url"] ``` The `url` value in the response is the destination for your video file in the next step. Send a `PUT` request directly to the presigned URL with your video's raw binary content as the request body. Note that this request goes to the presigned storage URL — not to the EyeQuant API — so you do not need to include your API token here. ```python theme={null} with open("VIDEO.webm", "rb") as video_file: response = requests.put(upload_url, data=video_file.read()) response.raise_for_status() ``` With the video now uploaded, create a video analysis by sending a `POST` request to `/v2/analyses/video`. Pass the same presigned `upload_url` as the `content` field so EyeQuant knows where to find your file. ```python theme={null} analysis_configuration = { "input": { "content": upload_url, "title": "Video Analysis", } } create_response = api.post( base_url + "/analyses/video", data=json.dumps(analysis_configuration), headers={"Content-Type": "application/json"}, ) create_response.raise_for_status() analysis_url = create_response.json()["location"] ``` Save the `location` value from the response — you'll poll that URL to track progress. Video processing takes longer than image or URL analysis depending on the length and size of your file. Poll the `analysis_url` every 30 seconds until the `status` field is no longer `pending`. ```python theme={null} analysis = {"status": "pending"} while analysis["status"] == "pending": time.sleep(30) analysis_response = api.get(analysis_url) analysis_response.raise_for_status() analysis = analysis_response.json() if analysis["status"] == "success": print("Video analysis complete!") ``` When `status` is `success`, the response body contains your per-frame prediction outputs. Video analysis may take several minutes to complete, depending on the duration and file size of your upload. Poll the status endpoint every 30 seconds rather than more frequently to avoid unnecessary requests. # Generated summaries and recommendations Source: https://developers.eyequant.com/guides/generated-summaries-and-recommendations Generate natural-language summaries and actionable recommendations for an analysis, and learn which analysis id to use. Beyond attention heatmaps and clarity scores, the EyeQuant API can generate natural-language **summaries** and **recommendations** for an analysis. * **Summary** — a concise description of what the analysis found. * **Recommendations** — concrete, actionable suggestions for improving the design. Both features run asynchronously: trigger generation with a `POST`, then poll with a `GET` until the content is ready. When generation completes, the content is returned in the `data` field as a **Markdown string**. Render it as Markdown to preserve headings and lists. ## Which ID to use This is the most common source of confusion, so it is worth getting right. `POST /analyses` returns the **screenshot id**. Use that id to poll [Get an analysis](/api-reference/get-analysis). When the analysis succeeds, that response also returns `_internal_exposed_id` — the **analysis id**. Use the analysis id for: * [Update analysis metadata](/api-reference/update-analysis-meta) * [Generate](/api-reference/generate-summary) and [Get](/api-reference/get-summary) a summary * [Generate](/api-reference/generate-recommendations) and [Get](/api-reference/get-recommendations) recommendations ```mermaid theme={null} sequenceDiagram participant C as Your client participant A as EyeQuant API C->>A: POST /analyses A-->>C: returns screenshot id C->>A: GET /analyses/{screenshot id} A-->>C: success + _internal_exposed_id (analysis id) C->>A: PUT /update-meta/screenshot/{analysis id} A-->>C: success C->>A: POST /analyses/summary/{analysis id} A-->>C: status started loop until completed C->>A: GET /analyses/summary/{analysis id} A-->>C: status processing end C->>A: GET /analyses/summary/{analysis id} A-->>C: status completed + data (markdown) ``` Before triggering generation, you can attach context to the analysis so the generated content focuses on the page, audience, and business outcome that matter to you. See [Update analysis metadata](/api-reference/update-analysis-meta). ```bash theme={null} curl \ -X PUT \ -H "Authorization: Bearer $apikey" \ -H "Content-Type: application/json" \ -d '{ "description": "Homepage hero", "goal": "Increase sign-ups" }' \ https://api.eyequant.com/v2/update-meta/screenshot/$analysisId ``` Trigger a summary (use the `recommendations` path for recommendations). Calling `POST` again is safe — if generation was already triggered, it returns the current status. ```bash theme={null} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ https://api.eyequant.com/v2/analyses/summary/$analysisId ``` Poll the `GET` endpoint every few seconds until `status` is `completed` (or `failed`, or a `410 Gone`). When complete, the Markdown content is in `data`. ```bash theme={null} curl \ -H "Authorization: Bearer $apikey" \ -X GET \ https://api.eyequant.com/v2/analyses/summary/$analysisId ``` ## JavaScript example ```javascript theme={null} const baseUrl = 'https://api.eyequant.com/v2'; async function requestJson(path, options = {}) { const headers = { Authorization: `Bearer ${apiKey}`, ...options.headers, }; if (options.body) { headers['Content-Type'] = 'application/json'; } const response = await fetch(`${baseUrl}${path}`, { ...options, headers }); const body = await response.json(); if (!response.ok) { throw new Error(body.msg || body.error?.message || 'Request failed'); } return body; } async function waitForGeneratedResult(path) { while (true) { const result = await requestJson(path); if (result.status === 'completed') { return result.data; // Markdown string } if (result.status === 'failed' || result.status === 'expired') { throw new Error(result.msg); } await new Promise((resolve) => setTimeout(resolve, 3000)); } } await requestJson(`/update-meta/screenshot/${analysisId}`, { method: 'PUT', body: JSON.stringify({ description: 'Homepage hero', goal: 'Increase sign-ups', }), }); await requestJson(`/analyses/summary/${analysisId}`, { method: 'POST' }); const summaryMarkdown = await waitForGeneratedResult( `/analyses/summary/${analysisId}` ); ``` To generate recommendations instead, use `/analyses/recommendations/${analysisId}` for both the `POST` trigger and the polling path. ## Result expiry Summary and recommendation tasks become unavailable one hour after they were started, after which the request returns `410 Gone`. If this happens, re-trigger generation with a `POST` and poll again. ## Errors The generated-content endpoints use a `{ "success": false, "msg": "..." }` error shape: * **`404` `analysis_not_found`** — no analysis with that id for your account. * **`404` `summary_not_found`** (or `recommendations_not_found`) — nothing generated yet; trigger one with `POST` first. * **`410` `analysis_expired`** — the task is older than one hour. * **`500` generation failed** — re-trigger with `POST`. # Run Multiple Prediction Types in a Single EyeQuant Call Source: https://developers.eyequant.com/guides/multiple-predictions Request attention, clarity, and excitingness predictions together in one EyeQuant API call and retrieve all outputs in a single response. By default, every EyeQuant analysis returns an attention heatmap — but the API supports several prediction types, and you can request more than one in a single call. By including a `predictions` object in your request body, you can ask for attention, clarity, and excitingness outputs simultaneously, receiving all results together once processing completes rather than making multiple separate requests. ## The `predictions` field The `predictions` field is an optional top-level object in your request body. Each key corresponds to a prediction type (for example, `attention` or `clarity`), and its value is a configuration object with an `outputs` array that specifies exactly which output artifacts you want. If you omit `predictions` entirely, EyeQuant falls back to the default behaviour and returns only an attention heatmap. ## Example: requesting attention and clarity together The following request analyzes a Base64-encoded image and asks for both an attention map and a perception map from the `attention` model, plus a clarity score and clarity map from the `clarity` model — all in one call. ```bash theme={null} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ -H "Content-Type: application/json" \ -d '{ "input": { "type": "image", "content": "iVBORw0KGgoAAAANSUhE....FTkSuQmCC", "medium": "desktopWeb", "title": "Example" }, "predictions": { "attention": { "outputs": ["attentionMap", "perceptionMap"] }, "clarity": { "outputs": ["score", "map"] } } }' \ https://api.eyequant.com/v2/analyses ``` After you poll the returned `location` URL and processing completes, the response body contains a unified `outputs` object with results from every requested prediction type: ```json theme={null} { "id": "611457618c1d4283a830d10a9ad4f8ae", "status": "success", "outputs": { "attention": { "attentionMap": "https://s3.amazonaws.com/api-eyequant/attentionHeatmap.png", "perceptionMap": "https://s3.amazonaws.com/api-eyequant/perceptionMap.png" }, "clarity": { "score": 87, "map": "https://s3.amazonaws.com/api-eyequant/clarityMap.png" } } } ``` ## Available prediction types and outputs EyeQuant currently supports three prediction types. Include any combination of them in the `predictions` object: | Prediction type | Available outputs | | --------------- | ---------------------------------------------- | | `attention` | `attentionMap`, `perceptionMap`, `hotspotsMap` | | `clarity` | `score`, `map` | | `excitingness` | `score` | **Attention** predicts where viewers' eyes are drawn on first glance. `attentionMap` is a heatmap overlay, `perceptionMap` shows predicted visual perception across the design, and `hotspotsMap` highlights the individual hot spots as discrete regions. **Clarity** measures how visually clear and structured the design appears. The `score` is a numeric value from 0–100 and `map` is a spatial clarity heatmap. **Excitingness** predicts the emotional arousal a design is likely to trigger. It returns a single numeric `score`. ### Example: requesting all three prediction types ```bash theme={null} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ -H "Content-Type: application/json" \ -d '{ "input": { "type": "image", "content": "iVBORw0KGgoAAAANSUhE....FTkSuQmCC", "medium": "desktopWeb", "title": "Example" }, "predictions": { "attention": { "outputs": ["attentionMap", "perceptionMap", "hotspotsMap"] }, "clarity": { "outputs": ["score", "map"] }, "excitingness": { "outputs": ["score"] } } }' \ https://api.eyequant.com/v2/analyses ``` ## Default configurations If you include a prediction type in the `predictions` object but pass an empty configuration — for example, `"attention": {}` — EyeQuant uses that prediction's default outputs. You don't need to enumerate every output name if you're happy with the defaults. Currently, all available outputs for a given prediction type are returned regardless of which specific outputs you list in the `outputs` array. The array is accepted but not yet enforced. This behaviour may change in a future API version, so you should still pass the outputs you intend to use. For the complete list of available prediction types and their supported outputs, see the [Predictions Model reference](/concepts/predictions-model). # EyeQuant: Predictive Visual Attention for Any Design Source: https://developers.eyequant.com/introduction EyeQuant is a machine perception API that generates attention heatmaps, clarity scores, and excitingness scores for images and web pages. Everything EyeQuant does in the app is available through the API. Send a design — an image, a live URL, or a video — and get back the same attention heatmaps, scores, and recommendations your team already trusts, in seconds. No user studies, no eye-tracking hardware, no waiting for traffic. Use it to validate creative before it ships, score every asset in your pipeline automatically, or build visual intelligence straight into your own product. ## What you can analyze Upload a PNG or JPEG (Base64) to analyze any static design, mockup, or asset — even ones that aren't publicly hosted. Pass any public URL. EyeQuant captures the screenshot for you — desktop, mobile, or generic viewport — then runs the analysis. Submit a video for frame-by-frame attention analysis of motion content and ads. ## What you get back Every analysis runs the same machine-perception models behind the EyeQuant app, returned as clean JSON with time-limited links to rendered maps. A heatmap of where viewers look first. Outputs: `attentionMap`, `perceptionMap`, `hotspotsMap`. A 0–100 score for how clear and easy to process a design is, with a supporting map. A 0–100 score for the visual and emotional impact of a design. A score for how well a creative stands out and captures attention in context. Need words, not just numbers? Generate an [AI summary](/api-reference/get-summary) and [actionable recommendations](/api-reference/get-recommendations) for any analysis. ## Why build on EyeQuant Attention prediction normally takes years of neuroscience R\&D and millions of eye-tracking data points to get right. EyeQuant's models are already there — trained on real eye-tracking research spanning more than 20,000 experiments and 1.6 million data points. You get tested, accurate visual intelligence you can integrate today, instead of building it from scratch. ## How it works The API is REST over HTTPS, JSON in and JSON out, authenticated with a bearer token. Analyses run asynchronously: submit a design, poll for the result, then download the maps and scores. Run your first analysis end to end in a few minutes. Add your API key to every request. Every endpoint, with an interactive playground. ## Getting API access API credentials aren't self-serve — contact [sales@eyequant.com](mailto:sales@eyequant.com) to request your key. Then head to [Authentication](/authentication) to start making calls. Store your API key securely — in an environment variable or secrets manager — and never commit it to source control. # Quickstart: Analyze Your First Design with EyeQuant Source: https://developers.eyequant.com/quickstart Make your first EyeQuant API call — submit a web page URL, poll for the completed analysis, and download the visual attention heatmap in a few steps. This quickstart walks you through the complete lifecycle of an EyeQuant analysis: submitting a URL for processing, polling for the result, and downloading the visual attention heatmap the API produces. By the end, you will have made real API calls and seen a working response — a solid foundation for integrating EyeQuant into your own application. ## Prerequisites Before you begin, make sure you have your EyeQuant API key available. If you do not have one yet, see the [Authentication](/authentication) page for details on how to obtain credentials. Send a `POST` request to `/v2/analyses` to kick off a new analysis. In the request body, specify the type of input you are providing. For this quickstart, you will analyze the Google homepage using the `webPageUrl` input type on a `desktopWeb` medium — this instructs the API to take a desktop-browser screenshot of the URL and run the full attention analysis pipeline on it. Replace `$apikey` with your actual API key before running this command: ```bash theme={null} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ -H "Content-Type: application/json" \ -d '{ "input": { "type": "webPageUrl", "content": "http://www.google.com", "medium": "desktopWeb", "title": "My First Analysis" } }' \ https://api.eyequant.com/v2/analyses ``` A successful submission returns an HTTP `201 Created` response with the new analysis ID and a `location` URL you will use in the next step: ```json theme={null} { "location": "https://api.eyequant.com/v2/analyses/611457618c1d4283a830d10a9ad4f8ae", "id": "611457618c1d4283a830d10a9ad4f8ae" } ``` Save the `id` value — you will need it to poll for results. Taking a screenshot and running the attention model both take time, so analyses are processed asynchronously. Retrieve the analysis by making a `GET` request to `/v2/analyses/{id}` using the ID returned in the previous step: ```bash theme={null} curl \ -X GET \ -H "Authorization: Bearer $apikey" \ https://api.eyequant.com/v2/analyses/611457618c1d4283a830d10a9ad4f8ae ``` While the analysis is still running, the response status will be `pending`: ```json theme={null} { "id": "611457618c1d4283a830d10a9ad4f8ae", "status": "pending" } ``` Keep polling the same endpoint until the status changes. Once the analysis completes successfully, the response includes an `outputs` object containing links to the generated maps: ```json theme={null} { "id": "611457618c1d4283a830d10a9ad4f8ae", "status": "success", "outputs": { "attention": { "attentionMap": "https://s3.amazonaws.com/api-eyequant/attentionHeatmap.png" } } } ``` Poll the results endpoint every few seconds rather than hammering it in a tight loop. For pages that require a full screenshot and render cycle, analyses can take 10–30 seconds to complete. A 5-second polling interval is a reasonable starting point for most use cases. The `attentionMap` URL in the `outputs` object points directly to the generated heatmap image hosted on AWS S3. Download it using a standard HTTP `GET` — no additional `Authorization` header is needed, because the URL already contains a time-limited access token: ```bash theme={null} curl -o attentionHeatmap.png \ "https://s3.amazonaws.com/api-eyequant/attentionHeatmap.png" ``` Store the downloaded image and any other output data on your own infrastructure as soon as possible. Output URLs are time-limited and will expire — the EyeQuant API does not guarantee long-term availability of these links. ## Next steps You have just completed a full analysis using a web page URL. EyeQuant supports additional input types and media modes to cover a wide range of use cases: * **Uploaded images** — Submit a base64-encoded PNG or JPEG using the `image` input type to analyze static designs or assets that are not publicly hosted. * **Mobile and generic viewports** — Swap `"medium": "desktopWeb"` for `"medium": "mobileWeb"` or `"medium": "generic"` to simulate different viewing contexts. * **Video analysis** — Upload a video file using `GET /v2/upload-urls` to obtain a presigned upload URL, then submit the analysis via `POST /v2/analyses/video`. Head over to the **Guides** section to explore all available input types and learn how to get the most out of the attention, clarity, and excitingness outputs. # EyeQuant API Status, Availability, and Retry Guidance Source: https://developers.eyequant.com/reference/api-status Learn how to check EyeQuant API availability, understand the over_capacity error, and handle service disruptions gracefully in your integration. EyeQuant's API is designed for high availability, but like any cloud service, temporary capacity issues can occur. This page explains how to monitor API status, what the `over_capacity` error means, and how to build a resilient integration that handles disruptions without manual intervention. ## Checking API status When the EyeQuant service is temporarily unavailable, the API responds with an `over_capacity` error code rather than silently failing or hanging. You can use this signal as a reliable indicator that the service is under pressure and that retrying after a delay is the right course of action. For extended outages, reach out to the EyeQuant team directly — the support and sales team can be contacted at **[sales@eyequant.com](mailto:sales@eyequant.com)** and can provide status updates or estimated recovery times if needed. ## The `over_capacity` error When the service is unavailable, you will receive the following JSON error body alongside an HTTP `503 Service Unavailable` status: ```json theme={null} { "error": { "code": "over_capacity", "message": "The service is currently unavailable." } } ``` Treat this error as **transient** — it signals a temporary condition, not a permanent failure. Your integration should catch this code and apply a retry strategy rather than surfacing it as an unrecoverable error to your users. ## Handling outages gracefully Building retry logic into your integration from the start means a temporary capacity issue has little to no impact on your users. Follow these best practices: * **Implement exponential backoff** when retrying failed requests — double the wait time between each attempt to avoid flooding the service. * **Treat `over_capacity` as a transient error** — always retry after a delay rather than surfacing it as a permanent failure. * **Avoid tight retry loops** — retrying immediately in a fast loop can worsen capacity issues for all users. * **Build retry logic into your polling loop** — if you poll for analysis results, your polling code is the right place to absorb transient errors. The following Python example shows a simple retry function with exponential backoff: ```python theme={null} import time import requests def get_analysis_with_retry(api, url, max_retries=5): for attempt in range(max_retries): response = api.get(url) if response.status_code == 200: return response.json() elif response.status_code == 503: # over_capacity — back off and retry wait = 2 ** attempt time.sleep(wait) else: response.raise_for_status() raise Exception("Max retries exceeded") ``` This function doubles the wait time on each attempt — 1 second, 2 seconds, 4 seconds, and so on — giving the service time to recover before each retry. For production integrations, use a job queue to manage analysis submissions and retries rather than polling synchronously. A queue decouples submission from result retrieval and makes exponential backoff straightforward to implement reliably. # EyeQuant API Error Codes and HTTP Status Reference Source: https://developers.eyequant.com/reference/errors EyeQuant returns structured JSON error responses with error codes. Reference all error codes, HTTP status meanings, and how to resolve each error. When something goes wrong with an API request, EyeQuant returns both an HTTP status code and a structured JSON error body so you know exactly what happened and how to fix it. This two-part approach gives you machine-readable codes you can branch on in code, alongside human-readable messages that make debugging fast. ## Error response format EyeQuant communicates errors through two complementary channels: * **HTTP status codes** — A code in the `400`–`499` range indicates a client error you can fix (for example, bad credentials or an invalid request body). A code in the `500`–`599` range indicates a server-side error within EyeQuant's own systems. * **JSON error body** — Where possible, the response body contains an `error` object with two fields: `error.code` (a stable, machine-readable string) and `error.message` (a human-readable explanation). Concrete errors may include additional detail in the `message` field beyond what is listed here. Here is an example of a full error response: ```http theme={null} HTTP/1.1 401 Unauthorized { "error": { "code": "authentication_failed", "message": "We were unable to authenticate you. Please check your credentials." } } ``` Use `error.code` to drive programmatic error handling in your integration, and `error.message` to surface useful context in logs or user-facing feedback. ## Error codes The table below covers all known error codes, what each one means, and how to resolve it. | Code | Description | Resolution | | -------------------------------- | ------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | | `client_error` | Generic client error — something is wrong with the request. | Check the request body, headers, and parameters for mistakes. | | `server_error` | Generic server error — an error occurred in EyeQuant's system. | EyeQuant has been alerted. Retry the request after a short delay. | | `resource_gone` | The requested resource is no longer accessible. | Results have expired. See [Result Expiry](/concepts/result-expiry) for details on retention windows. | | `authentication_failed` | Missing or incorrect API credentials. | Check your API key and ensure the `Authorization` header is set correctly. | | `over_capacity` | The service is currently unavailable. | Retry later. Check the [API Status](/reference/api-status) page for up-to-date availability information. | | `invalid_input_configuration` | The `input` object could not be used to start an analysis. | Review the `error.message` field for specifics. See [Input Model](/concepts/input-model). | | `could_not_grab_web_page` | EyeQuant could not capture the specified web page URL. | Verify the URL is valid and publicly accessible. Retry the request, or use an image input instead. | | `blank_input_image` | The input image is a single solid color. | Provide an image with visual content — solid-color images cannot be analyzed. | | `unreadable_input_image` | The input image could not be read — unsupported format or corrupted file. | Check the file format (PNG or JPEG only) and ensure the file is not truncated or corrupted. | | `invalid_input_image_dimensions` | The image dimensions are too small or too large. | See [Image Formats](/concepts/input-formats) for supported dimension limits. | Server errors (5xx) are logged automatically and the EyeQuant team is notified immediately. If a server error persists across multiple retries, contact support for assistance.