Sessions and Results API Reference

This page is not available in the language you requested. You have been redirected to the English version of the page.
Link to this page copied to clipboard

Retrieve session lists and full accessibility results programmatically using the REST API

Not for use with personal data

The Sessions and Results API gives you programmatic access to your Axe Developer Hub sessions and their accessibility results. Use the Sessions endpoint to discover sessions for a project, then use the Results endpoint to retrieve the detailed results for any specific session.

Both endpoints require a project ID. Find it in Axe Developer Hub, or look it up by project name with the Projects API.

Authentication

All requests require an API key. Provide it using the X-API-Key header:

X-API-Key: <DEQUE_API_KEY>

Find your API key in the Axe Account Portal. Choose an Axe Developer Hub API key for web or CI/CD projects, or an Axe DevTools Mobile API key for mobile projects.

Treat your API key as a secret: store it in an environment variable or your CI/CD platform's secret store rather than hardcoding it in your requests.

Access Control

The following access rules apply to both endpoints:

  • Project members can access sessions and results for any project they belong to.
  • Org Admins with an active Axe Developer Hub or Axe DevTools Mobile subscription can access sessions and results for any project in their organization, regardless of project membership. Access is scoped to the API key's product: an Axe Developer Hub API key returns only Axe Developer Hub data, and an Axe DevTools Mobile API key returns only Axe DevTools Mobile data. An Org Admin cannot use an Axe DevTools Mobile API key to retrieve Axe Developer Hub data, or an Axe Developer Hub API key to retrieve Axe DevTools Mobile data.
  • Non-member, non-admin users receive an access-denied response.
  • An inactive subscription returns 401 Unauthorized.

Sessions Endpoint

Returns a paginated, filterable list of sessions for a given project.

Request

  • Endpoint: GET https://axe.deque.com/api-pub/v1/results/projects/{project_id}/sessions
  • Headers (required):
    • X-API-Key: <DEQUE_API_KEY>
    • Accept: application/json

Replace {project_id} with the ID of the project whose sessions you want to retrieve. Find your project ID in Axe Developer Hub.

Query Parameters

All query parameters are optional.

Parameter Description
page_size Number of sessions to return per page. Default: 30. Maximum: 100. Values above the maximum are clamped to 100.
after Cursor value from the previous response, used to retrieve the next page. See Cursor Pagination.
created_after Returns only sessions created after this timestamp (ISO 8601 UTC, half-open; excludes the exact boundary). Example: 2025-01-01T00:00:00Z
created_before Returns only sessions created before this timestamp (ISO 8601 UTC, half-open; excludes the exact boundary). Example: 2026-01-01T00:00:00Z
is_canonical_source When true, returns only sessions marked as a canonical source. Must be true or false.
git_branch Returns only sessions associated with the given Git branch name. Gitless sessions will not match.
commit_sha Returns only sessions associated with the given Git commit SHA. Gitless sessions will not match.
git_url Returns only sessions associated with the given Git repository URL. Gitless sessions will not match.
created_by_user_email Returns only sessions created by the user with this email address. See Email Filter Limitation.

Response Body

A successful response returns a JSON object with a sessions array. Each session object contains the following fields:

Field Type Description
session_id String Unique identifier for the session.
name String Human-readable name for the session, if one was set. Omitted when unset; no synthetic fallback is provided.
created_at String ISO 8601 UTC timestamp for when the session was created.
is_canonical_source Boolean Whether this session is marked as a canonical source.
git_branch String Git branch associated with the session. null for gitless sessions.
git_url String Git repository URL associated with the session. null for gitless sessions.
commit_sha String Git commit SHA associated with the session. null for gitless sessions.
created_by_user_name String Display name of the user who created the session. Omitted if the user's API key has been deleted.
created_by_user_email String or null Email address of the user who created the session. null for sessions created before creator emails were stored.
created_by_user_api_key_name String Name of the API key used to create the session. Returns "Unknown Member" if the API key has been deleted.

Example Response Body

{
  "sessions": [
    {
      "session_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "name": "Main CI run for PR 451",
      "created_at": "2026-06-01T14:23:00.000Z",
      "is_canonical_source": true,
      "git_branch": "feature/new-nav",
      "git_url": "https://github.com/example/webapp",
      "commit_sha": "9eabf5b536662000f79978c4d1b6e4eff5c8d785",
      "created_by_user_name": "Jane Smith",
      "created_by_user_email": "jane.smith@example.com",
      "created_by_user_api_key_name": "CI Pipeline Key"
    },
    {
      "session_id": "f0e1d2c3-b4a5-6789-0123-456789abcdef",
      "created_at": "2026-05-30T09:00:00.000Z",
      "is_canonical_source": false,
      "git_branch": null,
      "git_url": null,
      "commit_sha": null,
      "created_by_user_email": null,
      "created_by_user_api_key_name": "Unknown Member"
    }
  ]
}

Cursor Pagination

The Sessions endpoint uses cursor-based pagination. When there are more results beyond the current page, an opaque cursor value is returned in the x-pagination-cursor response header. Pass this value as the after query parameter in your next request to retrieve the next page.

When the x-pagination-cursor header is absent from the response, you have reached the last page.

Email Filter Limitation

important

The created_by_user_email filter only matches sessions created after a specific date when server-side persistence of creator emails was introduced. Sessions created before that date do not have a stored creator email and will not appear in email-filtered results. As more new sessions accumulate, the filter becomes progressively more complete.

Sessions Endpoint Error Responses

Status Cause
400 Bad Request A query parameter value is invalid (for example, a malformed ISO 8601 timestamp or a page_size above the maximum).
401 Unauthorized The API key is invalid, missing, or the associated subscription is inactive.
403 Forbidden The API key does not have access to the specified project.
404 Not Found The specified project ID does not exist.

Results Endpoint

Returns the accessibility results for a specific session. The results are returned asynchronously: if the results are not yet ready, the endpoint returns 204 No Content and you poll until they are.

tip

Results are Brotli-compressed by default. Send Accept-Encoding: br with every request for the fastest, most reliable downloads, especially with format=full and large sessions. See Response Compression.

Deduplication

For web projects, both response formats return deduplicated results. When the same issue is found in more than one page state in the session, it's reported once, under the first page state where it was found. Two results count as the same issue when they have the same rule and page URL and the same element, matched by CSS selector, XPath, or ancestry. See Duplicate for the full matching rules.

  • format=summary: the issue counts by impact and by rule count each unique issue once.
  • format=full: each unique issue appears once in the issues list, and the header's summary counts are unique counts.

Deduplication happens only within a single session: results aren't compared with other sessions, and the response doesn't say how many duplicates were removed or whether an issue is new. Mobile results are not deduplicated.

Request

  • Endpoint: GET https://axe.deque.com/api-pub/v1/results/sessions/{session_id}/results
  • Headers (required):
    • X-API-Key: <DEQUE_API_KEY>
    • Accept: application/json
  • Headers (recommended):
    • Accept-Encoding: br: requests the Brotli-compressed response, which downloads fastest. See Response Compression.

Replace {session_id} with the session_id value returned by the Sessions endpoint. It must be a valid UUID.

Query Parameters

Parameter Required Description
format No Response format. summary (default) returns the same JSON shape as the legacy downloadable-report endpoint. full returns the complete Universal JSON (Common Export Format).

Response Compression

The Results endpoint compresses its response based on your request's Accept-Encoding header. It uses Brotli (br) if you accept it, otherwise gzip, otherwise no compression. The response's Content-Encoding header tells you which encoding was used.

Use Brotli whenever possible. Results are stored Brotli-compressed, so a Brotli response is sent as is. A gzip or uncompressed response has to be decompressed and re-encoded on the server first, which is much slower: large format=full downloads, or several downloads at the same time, can fail before they finish.

If you can't use Brotli (for example, a proxy or VPN on your network removes br from Accept-Encoding), gzip and uncompressed responses still work. Expect slower downloads, and download large results one session at a time.

Most HTTP clients don't request Brotli by default:

  • curl: Add --compressed. curl then requests every encoding it supports and decompresses the response for you. It only requests Brotli if your curl build supports it: run curl -V and check for brotli in the Features line. Some builds, including the curl that ships with macOS, don't include Brotli and fall back to gzip. A curl installed from a package manager such as Homebrew typically includes it. If your curl doesn't support Brotli, request it with -H "Accept-Encoding: br" (without --compressed) and decompress the saved file with brotli -d.
  • Python requests: Install the brotli package (pip install brotli). With it installed, requests asks for Brotli and decompresses the response automatically.
  • Other clients: Set Accept-Encoding: br and make sure your client decompresses Brotli responses. If it doesn't, save the response and decompress it yourself, for example with brotli -d.

Session State and the Polling Pattern

When a session's results have not yet been processed, the Results endpoint triggers processing automatically and responds with 204 No Content (no response body). Your client must poll the same endpoint until it receives a 200 OK response.

State HTTP Response What to do
done 200 OK with the results payload Results are ready. Consume the response body.
processing 204 No Content Results are still being generated. Wait briefly and retry.
error 422 Unprocessable Entity with an error body (see below) Processing failed for this session. Retrying the request starts processing again, so you can retry and resume polling.

Response body for error

{
  "state": "ERROR",
  "message": "We were unable to process your session. Please try again, if the issue persists contact helpdesk."
}

Handling 429 Too Many Requests

During periods of heavy load, the Results endpoint may respond with 429 Too Many Requests instead of triggering processing immediately. This does not mean your request was lost: the underlying work stays queued, and retrying does not create duplicate processing for the same session.

A 429 response includes a Retry-After header, in seconds. Wait at least that long before retrying — the example below handles this alongside the normal 204 polling case.

Response body

{
  "error": "Too many requests. Retry after the Retry-After interval."
}

Example: Polling for Results

#!/bin/bash

SESSION_ID="a1b2c3d4-e5f6-7890-abcd-ef1234567890"
URL="https://axe.deque.com/api-pub/v1/results/sessions/$SESSION_ID/results"
MAX_ATTEMPTS=20
DELAY=5
TEMP_FILE=$(mktemp)

for ((i=1; i<=MAX_ATTEMPTS; i++)); do
    echo "Attempt $i..."

    HEADERS_FILE=$(mktemp)
    # --compressed requests Brotli (if your curl supports it) and decompresses the response
    STATUS=$(curl -s -w '%{http_code}' -L --compressed \
      -H "Accept: application/json" \
      -H "X-API-Key: $API_KEY" \
      -D "$HEADERS_FILE" \
      -o "$TEMP_FILE" \
      "$URL?format=full")

    case $STATUS in
        200)
            echo "Results ready!"
            cat "$TEMP_FILE"
            rm "$TEMP_FILE" "$HEADERS_FILE"
            exit 0
            ;;
        204)
            echo "Still processing, waiting ${DELAY}s..."
            sleep $DELAY
            ;;
        429)
            RETRY_AFTER=$(grep -i '^retry-after:' "$HEADERS_FILE" | tr -d '\r' | awk '{print $2}')
            RETRY_AFTER=${RETRY_AFTER:-$DELAY}
            echo "Too many requests, waiting ${RETRY_AFTER}s per Retry-After..."
            sleep "$RETRY_AFTER"
            ;;
        *)
            echo "Error: HTTP $STATUS"
            cat "$TEMP_FILE"
            rm "$TEMP_FILE" "$HEADERS_FILE"
            exit 1
            ;;
    esac
    rm -f "$HEADERS_FILE"
done

echo "Timeout after $MAX_ATTEMPTS attempts"
rm "$TEMP_FILE"
exit 1

Response Formats

format=summary (default)

Returns the same JSON shape as the legacy downloadable-report endpoint. Use this format if you have existing tooling built against the downloadable-report endpoint and want a drop-in replacement.

format=full

Returns the full issue-level results in Universal JSON (Common Export Format). This format includes every accessibility issue found during the session, including page-level and rule-level detail.

Full results can be very large, so request them Brotli-compressed (Accept-Encoding: br, or --compressed with a Brotli-enabled curl). The response's Content-Encoding is negotiated from your Accept-Encoding header; see Response Compression.

important

Sessions created before July 15, 2026 return 404 Not Found for format=full, because Universal JSON (Common Export Format) capture was not enabled until that date. These sessions have no universal-format data to return. Use format=summary to retrieve results for sessions created before this date.

Results Endpoint Error Responses

Status Cause
400 Bad Request The format parameter value is not summary or full, or the session_id is not a valid UUID.
401 Unauthorized The API key is invalid, missing, or the associated subscription is inactive.
403 Forbidden The API key does not have access to the project that owns this session.
404 Not Found The specified session ID does not exist.
422 Unprocessable Entity Processing failed for this session. See Session State and the Polling Pattern.
429 Too Many Requests The system is under heavy load. See Handling 429 Too Many Requests.

Common Workflows

Retrieve All Sessions for a Project and Download Full Results

This example uses curl and jq to page through all sessions for a project and download the full Universal JSON results for each one. For web projects, each file contains the session's deduplicated issues; see Deduplication.

#!/bin/bash

# Set these environment variables before running:
# API_KEY: your Axe Developer Hub API key
# PROJECT_ID: your project ID

BASE_URL="https://axe.deque.com/api-pub/v1/results"
CURSOR=""

while true; do
    QUERY="page_size=100"
    if [ -n "$CURSOR" ]; then
        QUERY="$QUERY&after=$CURSOR"
    fi

    RESPONSE=$(curl -s -D - -H "Accept: application/json" -H "X-API-Key: $API_KEY" \
      "$BASE_URL/projects/$PROJECT_ID/sessions?$QUERY")

    NEXT_CURSOR=$(echo "$RESPONSE" | grep -i "x-pagination-cursor:" | tr -d '\r' | awk '{print $2}')
    BODY=$(echo "$RESPONSE" | sed -n '/^\r\{0,1\}$/,$p' | tail -n +2)

    SESSION_IDS=$(echo "$BODY" | jq -r '.sessions[].session_id')

    for SESSION_ID in $SESSION_IDS; do
        echo "Fetching results for session $SESSION_ID..."

        while true; do
            # --compressed requests Brotli (if your curl supports it) and decompresses the response
            STATUS=$(curl -s -w '%{http_code}' -L --compressed \
              -H "Accept: application/json" \
              -H "X-API-Key: $API_KEY" \
              -o "${SESSION_ID}.json" \
              "$BASE_URL/sessions/$SESSION_ID/results?format=full")

            if [ "$STATUS" = "200" ]; then
                echo "Saved ${SESSION_ID}.json"
                break
            elif [ "$STATUS" = "204" ]; then
                echo "  Still processing, waiting..."
                sleep 5
            else
                echo "  Error: HTTP $STATUS"
                break
            fi
        done
    done

    if [ -z "$NEXT_CURSOR" ]; then
        break
    fi
    CURSOR="$NEXT_CURSOR"
done