Skip to content

Latest commit

 

History

History
1313 lines (1043 loc) · 36.4 KB

File metadata and controls

1313 lines (1043 loc) · 36.4 KB

API Reference — Accellens

Version: 1.0 Update Date: November 23, 2025


1. Overview

Accellens provides REST and GraphQL interfaces for managing accessibility audits, interacting with AI services, and integrating with CI/CD processes.

  • Base URL: https://api.accellens.dev/api/v1
  • Authentication: JWT (Bearer token) or API Key (X-Accellens-Key).
  • Data Isolation: All requests are checked for belonging to the user's organization (organization_id).

2. REST API

2.1 Authentication

Login

POST /api/v1/auth/login

  • Authenticates the user and returns tokens.

  • Body:

    {
      "email": "user@example.com",
      "password": "secret_password"
    }
  • Response 200 OK:

    {
      "accessToken": "ey...",
      "refreshToken": "ey...",
      "user": { "id": "uuid", "email": "...", "name": "..." }
    }

Refresh Token

POST /api/v1/auth/refresh

  • Updates the access token using a refresh token (if stored in a cookie or passed in the body).
  • Response 200 OK: { "accessToken": "ey..." }

2.2 Organizations & Projects

Important: All API endpoints working with organization data (projects, runs, scans, findings, AI endpoints) require passing organization_id in the URI path. This ensures explicit data isolation and a consistent API structure.

List Organizations

GET /api/v1/organizations

  • Returns a list of organizations the current user belongs to.

  • Response 200 OK:

    [
      {
        "id": "01JBP7J3Z8CQ9TV3X6A4X5C5DZ",
        "name": "ACME Corp",
        "slug": "acme-corp",
        "plan": "pro"
      }
    ]

Create Project

POST /api/v1/organizations/{organization_id}/projects

  • Creates a new project in the specified organization.

  • Parameters:

    • organization_id (path) — Organization ID (UUID)
  • Body:

    {
      "name": "E-commerce Store",
      "slug": "shop-v1",
      "complianceTargets": ["wcag22-aa", "section508"]
    }
  • Response 201 Created.

List Projects

GET /api/v1/organizations/{organization_id}/projects

  • Returns a list of projects in the organization.

  • Response 200 OK:

    [
      {
        "id": "shop-v1",
        "name": "E-commerce Store",
        "organizationId": "01JBP7J3Z8CQ9TV3X6A4X5C5DZ",
        "createdAt": "2025-11-20T10:00:00.000Z"
      }
    ]

2.3 Scans & Runs

Start Scan

POST /api/v1/organizations/{organization_id}/projects/{project_id}/scans

  • Triggers a new scan for the project.

  • Parameters:

    • organization_id (path) — Organization ID (UUID)
    • project_id (path) — Project ID (UUID)
  • Body:

    {
      "targetUrl": "https://shop.acme.com",
      "type": "web",
      "triggerSource": "api",
      "platform": "auto"
    }
  • platform (optional, default: auto): Manual target platform/framework selection (html_aria, react, react_native, flutter, angular, vue, svelte). If auto, the platform is detected from the DOM.

  • Response 202 Accepted: { "runId": "01JBP8D8Q9M8K2E8V934A5GJ1C" }

Get Run Status

GET /api/v1/organizations/{organization_id}/runs/{run_id}

  • Returns the current status of a scan run.

  • Parameters:

    • organization_id (path) — Organization ID (UUID)
    • run_id (path) — Run ID (UUID)
  • Response 200 OK:

    {
      "id": "01JBP8D8Q9M8K2E8V934A5GJ1C",
      "status": "completed",
      "aasScore": 85.5,
      "summary": {
        "totalFindings": 42,
        "critical": 3,
        "high": 12,
        "platform": "react"
      },
      "startedAt": "...",
      "finishedAt": "..."
    }

2.4 Findings & Reports

List Findings

GET /api/v1/organizations/{organization_id}/runs/{run_id}/findings

  • Returns a list of accessibility violations found in a run.

  • Parameters:

    • organization_id (path) — Organization ID
    • run_id (path) — Run ID
  • Query Parameters: severity, category, status, limit, offset.

  • Response 200 OK:

    {
      "items": [
        {
          "id": "uuid",
          "ruleId": "color-contrast",
          "severity": "high",
          "category": "perceivable",
          "title": "Insufficient color contrast",
          "description": "...",
          "aiExplanation": "...",
          "impactedUsers": { "blind": true, "low_vision": true },
          "suggestedFix": {
            "technicalDescription": "...",
            "codeBefore": "...",
            "codeAfter": "...",
            "effortEstimation": "low"
          }
        }
      ],
      "total": 42
    }

Generate Report Archive

POST /api/v1/organizations/{organization_id}/projects/{project_id}/runs/{run_id}/reports/archive

  • Generates a report in the specified format and saves it to the organization's archive.

  • Parameters:

    • organization_id, project_id, run_id (path)
  • Body:

    {
      "report_type": "pdf",
      "meta_data": {
        "custom_sections": [{ "title": "Audit Scope", "content": "..." }]
      }
    }
  • Response 201 Created: Meta-data of the saved report (including storage_key and expires_at).

List Report Archives

GET /api/v1/organizations/{organization_id}/projects/{project_id}/reports/archives

  • Returns a list of archived reports for the project.

  • Query Parameters: report_type, run_id, limit, offset.

  • Response 200 OK:

    {
      "items": [
        {
          "id": "uuid",
          "report_type": "pdf",
          "file_size": 102456,
          "created_at": "...",
          "expires_at": "..."
        }
      ],
      "total": 15
    }

Get Report from Archive (Download)

GET /api/v1/organizations/{organization_id}/reports/archives/{report_id}/download

  • Generates a pre-signed S3 URL to download the report.
  • Response 200 OK: { "download_url": "https://s3.accellens..." }
  • Errors:
    • 404 Not Found — report not found
    • 403 Forbidden — no access to organization

SARIF Report

GET /api/v1/reports/{run_id}/sarif

  • Generates a SARIF 2.1.0 report for integration with CI/CD platforms (GitHub Security, Azure DevOps, etc.).

  • Format follows the SARIF 2.1.0 standard.

  • Example response:

    {
      "version": "2.1.0",
      "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
      "runs": [
        {
          "tool": {
            "driver": {
              "name": "Accellens",
              "version": "1.0.0"
            }
          },
          "results": [...]
        }
      ]
    }

Assistive Technology Simulations

GET /api/v1/assistive/{run_id}/audio

  • Returns a list of audio tracks demonstrating screen reader announcements.
  • Purpose: Helps developers hear what a screen reader user would hear.
  • Important: Audio is generated for demonstration only. Announcement clarity analysis is performed via AI analysis of the Accessibility Tree, not TTS.
  • Audio files are generated from Accessibility Tree announcements via TTS providers (OpenAI, ElevenLabs, AWS Polly, or Coqui XTTS v2).

GET /api/v1/assistive/{run_id}/simulations

  • Returns a list of text data for assistive technology announcements.
  • Includes announcements for screen readers (NVDA, JAWS, VoiceOver, TalkBack), voice control, and keyboard navigation.
  • Purpose: Provides a textual representation of what a screen reader would read, based on the Accessibility Tree.

2.5 AI Endpoints

AI endpoints provide intelligent analysis of findings using machine learning. All endpoints require passing organization_id in the URI path.

Explain Finding

POST /api/v1/organizations/{organization_id}/ai/explain

  • Generates an AI explanation for a finding, describing the accessibility problem in simple language.

  • Body:

    {
      "finding_id": "01JBP7J3Z8CQ9TV3X6A4X5C5DZ",
      "force_regenerate": false
    }
  • Response 200 OK:

    {
      "finding_id": "01JBP7J3Z8CQ9TV3X6A4X5C5DZ",
      "explanation": "This image lacks alternative text, making it inaccessible to screen reader users...",
      "cached": false
    }
  • If force_regenerate: true, the explanation will be re-generated even if it already exists.

Analyze Impact

POST /api/v1/organizations/{organization_id}/ai/impact

  • Analyzes which user categories are affected by a finding.

  • Body:

    {
      "finding_id": "01JBP7J3Z8CQ9TV3X6A4X5C5DZ",
      "force_regenerate": false
    }
  • Response 200 OK:

    {
      "finding_id": "01JBP7J3Z8CQ9TV3X6A4X5C5DZ",
      "impacted_users": {
        "blind": true,
        "low_vision": false,
        "motor": false,
        "cognitive": false
      },
      "cached": false
    }

Estimate Effort

POST /api/v1/organizations/{organization_id}/ai/effort

  • Estimates the effort required to fix a finding.

  • Body:

    {
      "finding_id": "01JBP7J3Z8CQ9TV3X6A4X5C5DZ",
      "force_regenerate": false
    }
  • Response 200 OK:

    {
      "finding_id": "01JBP7J3Z8CQ9TV3X6A4X5C5DZ",
      "effort_estimation": {
        "level": "low",
        "estimated_hours": 0.5,
        "complexity": "simple"
      },
      "cached": false
    }

Generate Fix Suggestions

POST /api/v1/organizations/{organization_id}/ai/fix

  • Generates fix suggestions for a finding with code examples for a specific platform/framework.

  • The platform is automatically detected from Run.summary["platform"] (saved during scanning).

  • If the platform is not defined (old runs), the HTML/ARIA generator is used.

  • Body:

    {
      "finding_id": "01JBP7J3Z8CQ9TV3X6A4X5C5DZ",
      "force_regenerate": false
    }
  • Response 200 OK:

    {
      "finding_id": "01JBP7J3Z8CQ9TV3X6A4X5C5DZ",
      "fix_suggestion": {
        "technical_description": "Clear technical explanation of the problem and why it needs to be fixed",
        "code_before": "The problematic code snippet",
        "code_after": "The fixed code snippet with proper accessibility attributes",
        "explanation": "Brief explanation of what changed and why it fixes the issue",
        "confidence": 0.85,
        "additional_notes": "Any additional considerations, edge cases, or best practices"
      },
      "cached": false
    }
  • Supported Platforms:

    • html_aria — HTML/ARIA (default)
    • react — React.js
    • react_native — React Native
    • flutter — Flutter
    • angular — Angular
    • vue — Vue.js
    • svelte — Svelte

Important:

  • All AI endpoints require passing organization_id in the URI path to ensure data isolation between organizations.
  • AI analysis results are cached in the database. Use force_regenerate: true for forced re-generation.
  • AI endpoints automatically check user access to the finding via the organization.

2.6 User Settings

GET /api/v1/user/settings

  • Returns personal settings for the current user (email, name, interface language, timezone, theme).

  • Response:

    {
      "email": "auditor@example.com",
      "name": "Jane Doe",
      "language": "en",
      "timezone": "Europe/Berlin",
      "theme": "system"
    }

PATCH /api/v1/user/settings

  • Partial profile update.
  • Constraints:
    • language ∈ {en, ru, uk}
    • theme ∈ {light, dark, system}
    • timezone — valid IANA identifier (America/New_York, UTC, ...)
  • Users can change only their own settings (actor_id check on the Python service).

GET /api/v1/user/notifications

  • Returns enabled notifications:

    {
      "emailNotifications": true,
      "slackNotifications": false,
      "scanCompleted": true,
      "criticalFindings": true,
      "weeklyDigest": false
    }

PATCH /api/v1/user/notifications

  • Partial update of notification flags (any subset of the five boolean fields).
  • Missing fields are not changed.

2.7 Notification Rules

Important: Notification Rules allow configuring rules for notifications about critical findings based on severity, compliance levels, number of impacted users, and other criteria. Rules can be global for the organization or personal for the user.

Create Notification Rule

POST /api/v1/organizations/{organization_id}/notification-rules

  • Creates a new notification rule for the organization.

  • Parameters:

    • organization_id (path) — Organization ID (UUID)
  • Headers:

    • X-Organization-Id — Organization ID
    • X-Actor-Id — User ID
  • Request Body:

    {
      "name": "Critical Findings Alert",
      "enabled": true,
      "critical_severities": ["critical"],
      "high_severities": ["high"],
      "min_impacted_users": 1,
      "critical_compliance_levels": ["AAA", "AA"],
      "min_rule_frequency": 1,
      "quiet_hours_enabled": false,
      "quiet_hours_start": "22:00",
      "quiet_hours_end": "08:00",
      "notification_priority": "high",
      "additional_config": {},
      "user_id": "01JBP7J3Z8CQ9TV3X6A4X5C5DZ"
    }
  • Fields:

    • name (required) — rule name (1-255 characters)
    • enabled (optional, default: true) — whether the rule is enabled
    • critical_severities (optional, default: []) — list of severity levels considered critical (critical, high, medium, low)
    • high_severities (optional, default: []) — list of severity levels considered high
    • min_impacted_users (optional, default: 1) — minimum number of impacted users (≥1)
    • critical_compliance_levels (optional, default: []) — list of compliance levels considered critical (A, AA, AAA)
    • min_rule_frequency (optional, default: 1) — minimum rule frequency (≥1)
    • quiet_hours_enabled (optional, default: false) — whether quiet hours are enabled
    • quiet_hours_start (optional) — quiet hours start time (HH:MM format, e.g., 22:00)
    • quiet_hours_end (optional) — quiet hours end time (HH:MM format, e.g., 08:00)
    • notification_priority (optional, default: normal) — notification priority (normal, high, urgent)
    • additional_config (optional, default: {}) — additional configuration
    • user_id (optional) — user ID for a personal rule. If not specified, the actor_id from the context is used.
  • Response 201 Created:

    {
      "id": "01JBP7J3Z8CQ9TV3X6A4X5C5DZ",
      "organization_id": "01JBP7J3Z8CQ9TV3X6A4X5C5DZ",
      "user_id": "01JBP7J3Z8CQ9TV3X6A4X5C5DZ",
      "name": "Critical Findings Alert",
      "enabled": true,
      "critical_severities": ["critical"],
      "high_severities": ["high"],
      "min_impacted_users": 1,
      "critical_compliance_levels": ["AAA", "AA"],
      "min_rule_frequency": 1,
      "quiet_hours_enabled": false,
      "quiet_hours_start": null,
      "quiet_hours_end": null,
      "notification_priority": "high",
      "additional_config": {},
      "created_at": "2025-11-10T08:22:14.123Z",
      "updated_at": "2025-11-10T08:22:14.123Z"
    }
  • Errors:

    • 400 Bad Request — invalid data (wrong time format, invalid values)
    • 403 Forbidden — no access to organization
    • 404 Not Found — organization not found

List Notification Rules

GET /api/v1/organizations/{organization_id}/notification-rules

  • Returns a list of notification rules for the organization.

  • Parameters:

    • organization_id (path) — Organization ID (UUID)
    • user_id (query, optional) — filter by User ID
    • enabled (query, optional) — filter by enabled status (true, false)
    • skip (query, optional, default: 0) — number of rules to skip (≥0)
    • limit (query, optional, default: 100, max: 1000) — maximum number of rules
  • Headers:

    • X-Organization-Id — Organization ID
    • X-Actor-Id — User ID
  • Response 200 OK:

    [
      {
        "id": "01JBP7J3Z8CQ9TV3X6A4X5C5DZ",
        "organization_id": "01JBP7J3Z8CQ9TV3X6A4X5C5DZ",
        "user_id": "01JBP7J3Z8CQ9TV3X6A4X5C5DZ",
        "name": "Critical Findings Alert",
        "enabled": true,
        "critical_severities": ["critical"],
        "high_severities": ["high"],
        "min_impacted_users": 1,
        "critical_compliance_levels": ["AAA", "AA"],
        "min_rule_frequency": 1,
        "quiet_hours_enabled": false,
        "quiet_hours_start": null,
        "quiet_hours_end": null,
        "notification_priority": "high",
        "additional_config": {},
        "created_at": "2025-11-10T08:22:14.123Z",
        "updated_at": "2025-11-10T08:22:14.123Z"
      }
    ]

Get Current User Notification Rule

GET /api/v1/organizations/{organization_id}/notification-rules/current-user

  • Returns the notification rule for the current user.
  • Parameters:
    • organization_id (path) — Organization ID (UUID)
  • Headers:
    • X-Organization-Id — Organization ID
    • X-Actor-Id — User ID (required)
  • Response 200 OK: Rule object (format as in the list above).
  • Response 404 Not Found if the rule is not found for the current user.
  • Response 401 Unauthorized if the user is not authenticated.

Get Notification Rule

GET /api/v1/organizations/{organization_id}/notification-rules/{rule_id}

  • Returns a notification rule by ID.
  • Parameters:
    • organization_id (path) — Organization ID (UUID)
    • rule_id (path) — Rule ID (UUID)
  • Headers:
    • X-Organization-Id — Organization ID
    • X-Actor-Id — User ID
  • Response 200 OK: Rule object (format as in the list above).
  • Response 404 Not Found if the rule is not found or does not belong to the organization.

Update Notification Rule

PATCH /api/v1/organizations/{organization_id}/notification-rules/{rule_id}

  • Updates a notification rule (partial update).

  • Parameters:

    • organization_id (path) — Organization ID (UUID)
    • rule_id (path) — Rule ID (UUID)
  • Headers:

    • X-Organization-Id — Organization ID
    • X-Actor-Id — User ID
  • Request Body (all fields optional):

    {
      "name": "Updated Rule Name",
      "enabled": false,
      "critical_severities": ["critical", "high"],
      "quiet_hours_enabled": true,
      "quiet_hours_start": "23:00",
      "quiet_hours_end": "07:00",
      "notification_priority": "urgent"
    }
  • Response 200 OK: Updated rule object.

  • Response 404 Not Found if the rule is not found.

  • Response 400 Bad Request if data is invalid.

Delete Notification Rule

DELETE /api/v1/organizations/{organization_id}/notification-rules/{rule_id}

  • Deletes a notification rule.
  • Parameters:
    • organization_id (path) — Organization ID (UUID)
    • rule_id (path) — Rule ID (UUID)
  • Headers:
    • X-Organization-Id — Organization ID
    • X-Actor-Id — User ID
  • Response 204 No Content on successful deletion.
  • Response 404 Not Found if the rule is not found.
  • Response 403 Forbidden if no permission to delete.

2.8 Notifications

Important: Notifications API provides real-time notifications about critical findings via Server-Sent Events (SSE). Notifications are filtered based on configured Notification Rules.

Stream Critical Findings

GET /api/v1/notifications/critical-findings/stream

  • Establishes an SSE connection to receive real-time notifications about critical findings.

  • Parameters:

    • projectId (query, optional) — Project ID for filtering (UUID). If not specified, notifications come for all organization projects.
  • Headers:

    • Authorization: Bearer <token> or X-Accellens-Key: <key> — authentication
    • X-Organization-Id — Organization ID (required)
  • Response Format: text/event-stream (SSE)

  • Events:

    • connected — connection established:

      event: connected
      data: {"status": "connected"}
      
    • critical_finding — new critical finding:

      event: critical_finding
      data: {
        "finding_id": "01JBP7J3Z8CQ9TV3X6A4X5C5DZ",
        "run_id": "01JBP8D8Q9M8K2E8V934A5GJ1C",
        "project_id": "01JBP8D8Q9M8K2E8V934A5GJ1D",
        "severity": "critical",
        "rule_id": "color-contrast",
        "title": "Color contrast insufficient",
        "description": "Element has insufficient color contrast",
        "impacted_users": {
          "blind": true,
          "low_vision": true,
          "motor": false,
          "cognitive": false
        },
        "compliance_levels": ["AA", "AAA"],
        "in_quiet_hours": false,
        "detected_at": "2025-11-10T08:30:00.000Z"
      }
      
    • disconnected — connection closed:

      event: disconnected
      data: {"status": "disconnected"}
      
    • error — stream error:

      event: error
      data: {"error": "Error message"}
      
  • Behavior:

    • The connection checks for new findings every 10 seconds
    • Notifications are sent only for findings matching active Notification Rules
    • Findings in quiet hours are skipped (if quiet hours are enabled in the rule)
    • Each finding is sent only once (tracked by finding_id)
  • Errors:

    • 401 Unauthorized — not authenticated
    • 400 Bad Request — missing X-Organization-Id or invalid projectId
    • 403 Forbidden — no access to organization
  • Usage Example:

    const eventSource = new EventSource(
      '/api/v1/notifications/critical-findings/stream?projectId=01JBP8D8Q9M8K2E8V934A5GJ1D',
      {
        headers: {
          Authorization: 'Bearer <token>',
          'X-Organization-Id': '<organization_id>',
        },
      },
    );
    
    eventSource.addEventListener('connected', (event) => {
      console.log('Connected to notifications stream');
    });
    
    eventSource.addEventListener('critical_finding', (event) => {
      const finding = JSON.parse(event.data);
      console.log('New critical finding:', finding);
      // Show notification to the user
    });
    
    eventSource.addEventListener('error', (event) => {
      console.error('Stream error:', event.data);
    });
  • Notes:

    • SSE connection automatically reconnects on disconnect
    • Client should handle Retry-After header on errors
    • Connection closes on client request cancellation
    • For production, connection pooling and rate limiting are recommended

2.9 AAS (Accessibility Accuracy Score)

Important: AAS (Accessibility Accuracy Score) is a metric that evaluates the overall accessibility of a project based on findings and compliance rules.

Get Current AAS for Organization

GET /api/v1/organizations/{organization_id}/aas/current

  • Returns the current AAS score for the organization (the latest score across all projects).

  • Parameters:

    • organization_id (path) — Organization ID (UUID)
  • Headers:

    • X-Organization-Id — Organization ID
    • X-Actor-Id — User ID
  • Response 200 OK:

    {
      "aas_score": 85.5,
      "run_id": "01JBP8D8Q9M8K2E8V934A5GJ1C",
      "project_id": "01JBP8D8Q9M8K2E8V934A5GJ1D",
      "created_at": "2025-11-10T08:30:00.000Z",
      "weighting_config": {
        "critical": 1.0,
        "high": 0.7,
        "medium": 0.5,
        "low": 0.3
      }
    }
  • Response 404 Not Found if no AAS data exists for the organization.

Get Current AAS for Project

GET /api/v1/organizations/{organization_id}/projects/{project_id}/aas/current

  • Returns the current AAS score for a specific project.
  • Parameters:
    • organization_id (path) — Organization ID (UUID)
    • project_id (path) — Project ID (UUID)
  • Headers:
    • X-Organization-Id — Organization ID
    • X-Actor-Id — User ID
  • Response 200 OK: similar to organization response, but project_id always matches the requested project.
  • Response 404 Not Found if the project is not found or no AAS data exists for the project.

Get AAS History for Organization

GET /api/v1/organizations/{organization_id}/aas/history

  • Returns the AAS score history for the organization (paginated).

  • Parameters:

    • organization_id (path) — Organization ID (UUID)
    • limit (query, optional, default: 100, max: 1000) — record count
    • offset (query, optional, default: 0) — pagination offset
  • Headers:

    • X-Organization-Id — Organization ID
    • X-Actor-Id — User ID
  • Response 200 OK:

    {
      "items": [
        {
          "id": "01JBP8D8Q9M8K2E8V934A5GJ1E",
          "aas_score": 85.5,
          "run_id": "01JBP8D8Q9M8K2E8V934A5GJ1C",
          "project_id": "01JBP8D8Q9M8K2E8V934A5GJ1D",
          "created_at": "2025-11-10T08:30:00.000Z",
          "weighting_config": {
            "critical": 1.0,
            "high": 0.7
          }
        }
      ],
      "total": 150,
      "limit": 100,
      "offset": 0
    }
  • Records are sorted by created_at in descending order (newest first).

Get AAS History for Project

GET /api/v1/organizations/{organization_id}/projects/{project_id}/aas/history

  • Returns AAS score history for a specific project (paginated).
  • Parameters:
    • organization_id (path) — Organization ID (UUID)
    • project_id (path) — Project ID (UUID)
    • limit (query, optional, default: 100, max: 1000) — record count
    • offset (query, optional, default: 0) — pagination offset
  • Headers:
    • X-Organization-Id — Organization ID
    • X-Actor-Id — User ID
  • Response 200 OK: similar to organization response, but all records belong to the specified project.
  • Response 404 Not Found if the project is not found.

2.10 Compliance Rules

Important: Compliance Rules are accessibility standards compliance rules (WCAG, EN 301 549, etc.). Rules are global (not tied to an organization), but access is controlled via organization authentication.

List Rules

GET /api/v1/organizations/{organization_id}/rules

  • Returns a list of compliance rules with filtering and pagination.

  • Parameters:

    • organization_id (path) — Organization ID (UUID, used for access control)
    • standard (query, optional) — filter by standard (wcag, en_301_549)
    • level (query, optional) — filter by level (a, aa, aaa)
    • category (query, optional) — filter by category (perceivable, operable, understandable, robust)
    • enabled (query, optional) — filter by enabled status (true, false)
    • source (query, optional) — filter by source (axe_core, custom, lighthouse)
    • severity (query, optional) — filter by severity level (critical, high, medium, low)
    • search (query, optional) — search by rule_id, title, description
    • limit (query, optional, default: 100, max: 1000) — record count
    • offset (query, optional, default: 0) — pagination offset
    • sort (query, optional, default: rule_id) — sort field (rule_id, title, standard, created_at)
  • Headers:

    • X-Organization-Id — Organization ID
    • X-Actor-Id — User ID
  • Response 200 OK:

    {
      "items": [
        {
          "id": "01JBP8D8Q9M8K2E8V934A5GJ1F",
          "rule_id": "color-contrast",
          "title": "Color Contrast",
          "description": "Elements must have sufficient color contrast",
          "standard": "wcag",
          "standard_version": "2.1",
          "level": "aa",
          "category": "perceivable",
          "source": "axe_core",
          "enabled": true,
          "severity_default": "high",
          "metadata": {
            "test": true
          },
          "ai_analytics": {
            "explanation": "High contrast is essential for users with low vision.",
            "fix_suggestions": ["Increase contrast ratio to at least 4.5:1"]
          },
          "created_at": "2025-11-10T08:00:00.000Z",
          "updated_at": "2025-11-10T08:30:00.000Z"
        }
      ],
      "total": 500,
      "limit": 100,
      "offset": 0
    }

Get Rule

GET /api/v1/organizations/{organization_id}/rules/{rule_id}

  • Returns details for a specific rule.
  • Parameters:
    • organization_id (path) — Organization ID (UUID, used for access control)
    • rule_id (path) — Rule identifier (string, e.g., color-contrast)
  • Headers:
    • X-Organization-Id — Organization ID
    • X-Actor-Id — User ID
  • Response 200 OK: Rule object (format as in the list above).
  • Response 404 Not Found if rule not found.

Enable Rule

PATCH /api/v1/organizations/{organization_id}/rules/{rule_id}/enable

  • Enables a compliance rule.
  • Parameters:
    • organization_id (path) — Organization ID (UUID)
    • rule_id (path) — Rule identifier
  • Headers:
    • X-Organization-Id — Organization ID
    • X-Actor-Id — User ID
  • Response 200 OK: Updated rule object with enabled: true.
  • Response 404 Not Found if rule not found.

Disable Rule

PATCH /api/v1/organizations/{organization_id}/rules/{rule_id}/disable

  • Disables a compliance rule.
  • Parameters:
    • organization_id (path) — Organization ID (UUID)
    • rule_id (path) — Rule identifier
  • Headers:
    • X-Organization-Id — Organization ID
    • X-Actor-Id — User ID
  • Response 200 OK: Updated rule object with enabled: false.
  • Response 404 Not Found if rule not found.

Update Rule

PATCH /api/v1/organizations/{organization_id}/rules/{rule_id}

  • Updates a compliance rule (enabled status and/or default severity).

  • Parameters:

    • organization_id (path) — Organization ID (UUID)
    • rule_id (path) — Rule identifier
  • Request Body:

    {
      "enabled": false,
      "severity_default": "critical"
    }
  • Headers:

    • X-Organization-Id — Organization ID
    • X-Actor-Id — User ID
  • Response 200 OK: Updated rule object.

  • Response 404 Not Found if rule not found.

Sync Rules

POST /api/v1/organizations/{organization_id}/rules/sync

  • Synchronizes rules from the scanner (dynamic fetch).

  • Requires owner or admin role.

  • Parameters:

    • organization_id (path) — Organization ID
  • Headers:

    • X-Organization-Id — Organization ID
    • X-Actor-Id — User ID
  • Response 200 OK: Sync statistics.

    {
      "checked": 150,
      "new": 5,
      "updated": 2,
      "deleted": 0
    }

Generate AI Analytics

POST /api/v1/organizations/{organization_id}/rules/actions/generate-ai

  • Triggers AI analytics generation for rules (explanation, fix suggestions).

  • Requires owner or admin role.

  • Parameters:

    • organization_id (path) — Organization ID
  • Request Body:

    {
      "rule_ids": ["color-contrast"],
      "force": false,
      "pending_only": true
    }
    • rule_ids (optional) — list of Rule IDs to process. If specified, pending_only is ignored.
    • force (default: false) — overwrite existing analytics.
    • pending_only (default: true) — process only rules marked with the regeneration flag.
  • Response 200 OK:

    {
      "task_id": "01JBP...",
      "status": "triggered"
    }

Custom Rules Management

API for managing custom accessibility rules.

POST /api/v1/organizations/{organization_id}/custom-rules

  • Creates a new custom rule.

  • Parameters:

    • organization_id (path) — Organization ID (UUID)
  • Request Body:

    {
      "rule_id": "custom-button-label",
      "title": "Buttons must have explicit labels",
      "description": "All buttons must have a clean and descriptive label.",
      "category": "operable",
      "severity": "high",
      "standard": "wcag",
      "standard_version": "2.1",
      "level": "aa",
      "metadata": {}
    }
  • Validation:

    • rule_id: unique, lowercase, alphanumeric with hyphens (3-100 chars)
  • Response 201 Created: created rule object.

  • Errors:

    • 409 Conflict: rule with this rule_id already exists.
    • 400 Bad Request: invalid data.

PUT /api/v1/organizations/{organization_id}/custom-rules/{rule_id}

  • Updates a custom rule.

  • Parameters:

    • organization_id (path) — Organization ID
    • rule_id (path) — Rule ID
  • Request Body (partial update):

    {
      "title": "Updated Title",
      "description": "Updated description...",
      "severity": "critical",
      "enabled": true
    }
  • Response 200 OK: updated rule object.

  • Errors:

    • 404 Not Found: rule not found or not a custom rule.

DELETE /api/v1/organizations/{organization_id}/custom-rules/{rule_id}

  • Deletes a custom rule.
  • Parameters:
    • organization_id (path) — Organization ID
    • rule_id (path) — Rule ID
  • Response 204 No Content.
  • Errors:
    • 404 Not Found: rule not found.
    • 403 Forbidden: attempt to delete a system rule (not custom).

2.11 Integrations

GET /api/v1/integrations

  • Returns all integrations connected in the user's organization.

  • Example:

    [
      {
        "id": "01JFAXG3D53B2YDM7QYF6X0TPR",
        "type": "github",
        "name": "GitHub",
        "description": "Integrate with GitHub for automated scan workflows",
        "status": "connected",
        "configuredAt": "2025-11-19T08:15:30.000Z",
        "settings": { "repository": "acme/site" },
        "hasCredentials": true
      }
    ]

POST /api/v1/integrations

  • Creates an integration (github, gitlab, jira, slack, webhook, jenkins, circleci).

  • Body:

    {
      "type": "slack",
      "settings": { "channel": "#a11y-alerts" },
      "credentials": { "webhookUrl": "https://hooks.slack.com/services/..." }
    }
  • credentials are encrypted by the service before saving.

  • Only one instance of each integration type can exist in an organization.

PATCH /api/v1/integrations/{id}

  • Updates name, settings, credentials, status.
  • Empty credentials object → secret deletion and status change to disconnected.

DELETE /api/v1/integrations/{id}

  • Deletes an integration and clears associated secrets.
  • Requires organization membership (verified by gateway middleware).

3. GraphQL API

Endpoint: /graphql, Apollo Federation-ready.

Core Types

  • Project, Run, Finding, AccessibilityTree, AudioSample, SimulationStep.

Query Examples

Get Latest Project Runs

query ProjectRuns($projectId: ID!) {
  project(id: $projectId) {
    id
    name
    runs(limit: 10) {
      id
      type
      status
      summary {
        totalFindings
        critical
        high
        medium
        low
      }
      startedAt
      finishedAt
    }
  }
}

Update Finding Status

mutation UpdateFinding($input: UpdateFindingInput!) {
  updateFinding(input: $input) {
    finding {
      id
      status
      owner {
        id
        email
      }
    }
    errors {
      message
      path
    }
  }
}

Implementation

  • Apollo Server + Strawberry federation; DataLoader for Postgres request batching.
  • Persisted queries for UI. Support for GraphQL Subscriptions (scanProgress).

4. Webhooks & SSE

  • POST /api/v1/webhooks/scansscan.completed, scan.failed, scan.timeout events. Payload:

    {
      "event": "scan.completed",
      "runId": "01JBP8D8Q9M8K2E8V934A5GJ1C",
      "projectId": "shop",
      "status": "completed",
      "metrics": { "critical": 3, "high": 7 }
    }
  • Server-Sent Events /api/v1/projects/{id}/eventsscan-progress event with percentage, currentPhase, message fields.

  • Resending on 5xx is supported; client should handle Retry-After.


5. Errors

FastAPI error format:

{
  "error": {
    "code": "SCAN_NOT_FOUND",
    "message": "Run 123 not found",
    "details": {}
  }
}
  • Tracing: X-Request-Id.
  • Rate limit: 429 with Retry-After headers.
Code Message Reason Solution
PROJECT_NOT_FOUND Project slug does not exist Invalid identifier Check the slug
SCAN_LIMIT_REACHED Concurrent scans exceeded Limit of 5 concurrent scans exceeded Wait for finish/increase limit
UNSUPPORTED_FORMAT Format must be json/pdf/sarif Invalid format Specify a valid format
ASSISTIVE_DISABLED Assistive simulation not enabled Feature is disabled Enable via project settings

6. Versioning

  • REST: /api/v1/ (MVP) — supported for at least 12 months. Breaking changes will go into /api/v2/.
  • GraphQL: schema evolves via @deprecated(reason, removalDate) directive.
  • Webhooks are versioned via X-Accellens-Webhook-Version header.

7. SDK/CLI

  • CLI (accellens) uses REST API (/api/v1/).
  • TypeScript SDK (Nx workspace libs/common/sdk) provides typed clients for REST/GraphQL (beta).
  • Usage examples can be found in docs/api/cli-reference.md.

8. API Security

  • JWT access token with exp ≤ 3600 (60 minutes), refresh tokens (30 days) updated via /api/v1/auth/refresh with rotation.
  • Refresh tokens are stored in httpOnly cookies for XSS protection.
  • API keys are restricted by projects, scopes (scan:write, report:read, admin:manage).
  • Webhook signing with HMAC SHA256 (X-Accellens-Signature) — string: sha256= + hex_digest.
  • All report files are served via signed URLs (AWS S3 pre-signed, expire after 15 minutes).

9. Payload Limits

  • Maximum 20 pages per scan (MVP), 5 concurrent scans per project (configurable).
  • Mobile build ≤ 500 MB, all uploads undergo antivirus scanning.
  • SSE connections are closed after 30 minutes of inactivity.

10. Related Documentation