Sessions and Results API Reference
Retrieve session lists and full accessibility results programmatically using the REST API
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.
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 | Email address of the user who created the session. Omitted if the user's API key has been deleted. |
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_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
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.
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
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). |
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 |
204 No Content |
Processing encountered an error. You may retry the request. |
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)
STATUS=$(curl -s -w '%{http_code}' -L \
-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 1Response 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.
The response is delivered with Content-Encoding negotiated from the client's Accept-Encoding header.
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. |
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.
#!/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
STATUS=$(curl -s -w '%{http_code}' -L \
-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