API Reference
Submit a scan, follow its progress, and retrieve the completed result.
Guide baseline: v0.9.11. Source contracts reviewed September 15, 2026.
Server URL and authentication
# API origin, without a route prefix
export AELIRA_API_URL="http://localhost:8000"
# Production: use your deployment's HTTPS API origin.
# Supply AELIRA_API_KEY through your secret manager or CI secrets.
# Request header: Authorization: Bearer your-api-keyThe direct application routes start with /education. API key clients send the key in the Authorization header on submission, progress and result requests. Production requires authentication; access is limited to the authenticated workspace and any applicable course scope.
Local evaluation can explicitly enable ENV=development and ALLOW_MOCK_AUTH=true. Mock authentication is restricted to development and is blocked in production and staging. The example below uses a real API key.
Inspect your running server at /docs and /openapi.json for its deployed request parameters. Some responses are declared as generic dictionaries, so consult the pinned route sources below for the nested response fields.
Complete PDF scan example
Start the API and worker, then save this as a Bash script and run it with a PDF path. It disables optional AI description generation for this scan. The script stops on HTTP errors, malformed responses, failed jobs, polling timeout, missing scores or a score below the example threshold. It prints the retrieved JSON only after validating the completed result.
#!/usr/bin/env bash
set -euo pipefail
# Requires bash, curl 7.76+ and jq. Supply an API key from your secret store.
: "${AELIRA_API_KEY:?Set AELIRA_API_KEY}"
API_URL="${AELIRA_API_URL:-http://localhost:8000}"
API_URL="${API_URL%/}"
PDF_FILE="${1:-document.pdf}"
test -f "$PDF_FILE" || { echo "PDF file not found" >&2; exit 1; }
request() {
curl --fail-with-body --silent --show-error \
--connect-timeout 10 --max-time 60 \
-H "Authorization: Bearer $AELIRA_API_KEY" "$@"
}
# Submit once. AI options are query parameters; file is multipart.
submitted=$(request -X POST \
"$API_URL/education/pdf/scan?generate_alt_text=false&enhance_descriptions=false" \
-F "file=@$PDF_FILE")
scan_id=$(jq -er '.scan_id | select(type == "string" and length > 0)' <<< "$submitted")
# Encode the identifier as one URL path segment.
scan_path=$(jq -rn --arg id "$scan_id" '$id | @uri')
# Poll for at most five minutes (each HTTP request is also bounded).
deadline=$((SECONDS + 300))
while true; do
if (( SECONDS >= deadline )); then
echo "Scan timed out: $scan_id" >&2
exit 1
fi
progress=$(request "$API_URL/education/scans/$scan_path/progress")
status=$(jq -er '.status | select(type == "string") | ascii_upcase' <<< "$progress")
case "$status" in
COMPLETED) break ;;
FAILED)
jq -r '.error_message // .progress_message // "Scan failed"' <<< "$progress" >&2
exit 1 ;;
PENDING|PROCESSING) sleep 2 ;;
*) echo "Unexpected scan status: $status" >&2; exit 1 ;;
esac
done
# Retrieve completed details. A successful POST is not a passing scan.
result=$(request "$API_URL/education/scans/$scan_path")
jq -e '.success == true and .scan.status == "COMPLETED"' <<< "$result" >/dev/null
if ! score=$(jq -er '.scan.result.compliance_score |
select(type == "number" and . >= 0 and . <= 100)' <<< "$result"); then
echo "Score unavailable or invalid: $scan_id" >&2
exit 1
fi
jq . <<< "$result"
# Example policy: fail when the completed score is below 80.
if ! jq -en --argjson score "$score" '$score >= 80' >/dev/null; then
echo "Score $score is below threshold 80" >&2
exit 1
fiThe polling deadline is checked between requests; the final in-flight request may take up to 60 additional seconds. A client timeout does not cancel the server job. Keep the scan ID for investigation instead of automatically submitting the file again.
The score path is scan.result.compliance_score; findings are in scan.result.issues, and severity totals in scan.result.summary. Individual finding fields vary by scanner. A numeric threshold is an example automation policy, not proof of accessibility or legal compliance.
Scan and history endpoints
| Method | Path | Contract |
|---|---|---|
| POST | /education/pdf/scan | Multipart file (.pdf). Query: generate_alt_text=false, enhance_descriptions=true by default. |
| POST | /education/powerpoint/scan | Multipart file (.pptx). Query: generate_alt_text=false, validate_alt_text=false. |
| POST | /education/word/scan | Multipart file (.docx). Query: generate_alt_text=false, validate_alt_text=false. |
| POST | /education/excel/scan | Multipart file (.xlsx). Query: generate_chart_descriptions=false, generate_alt_text=false. |
| POST | /education/latex/scan | Multipart file. Query: use_ollama=true by default; requires a configured provider when enabled. |
| POST | /education/latex/convert | Multipart file containing LaTeX; not an inline equation JSON endpoint. Query: use_ollama=true by default. |
| POST | /education/web/scan | JSON: url, mode, max_depth, max_pages and optional analysis settings. Returns an asynchronous scan handle. |
| GET | /education/scans/{scan_id}/progress | Top-level status, progress, progress_message and error_message. |
| GET | /education/scans/{scan_id} | Scan details in scan; completed result in scan.result, which can be null before results exist. |
| GET | /education/scans | Query: limit (default: 50), offset (default: 0), scan_type. Recognized filters: pdf, powerpoint/pptx, latex/tex. |
For document scans, upload the file multipart field and put the listed scalar options in the query string. Do not assume every format accepts the same options. Provider-dependent options require a configured provider. For multiple PDFs, use the CLI directory scan or submit and track each file separately.
Web request body
Send this JSON to POST /education/web/scan with your bearer header and Content-Type: application/json, then poll and retrieve using the returned scan_id as above. Replace the URL with a site you are authorized to scan.
{
"url": "https://example.edu",
"mode": "quick",
"max_depth": 1,
"max_pages": 1,
"generate_code_fixes": false,
"capture_screenshots": false
}max_depth: 1 selects a single page. The model also accepts scan_images, scan_multimedia, scan_math and validate_alt_text. See the Web Scanner guide for mode and review boundaries.
Errors and rate limits
API keys have a configured hourly rate limit, including on self-hosted deployments. Exceeding it returns HTTP 429 with rate-limit headers. Account quotas and feature permissions can impose additional restrictions; there is no universal per-operation allowance.
HTTP 401 indicates missing or invalid credentials. Access and feature restrictions may return 403; a scan lookup can return 404. Invalid upload or request data may return 400 or 422. Treat every non-success HTTP response as an error. A successfully submitted job can later report FAILED; read its error_message. The example stops on 429, so an operator can inspect the headers and choose a suitable retry delay.