Back to Integrations Guides

Introduction

Every AAArdvark webhook message follows the same structure: a common envelope that tells you which event fired, when, and on which site – and a data section that holds the details specific to that event.

This guide breaks down each part. Once you’ve read the envelope once, all the other event types will feel familiar.


The common wrapper

Here’s the envelope every message arrives in:

{
  "version": "1.0",
  "event": "issue.created",
  "timestamp": "2026-06-04T21:32:50.209952Z",
  "site": {
    "id": 1428,
    "name": "site care",
    "url": null,
    "base_url": "https://sitecare.com",
    "workspace": {
      "id": 1,
      "name": "Abdulkhalek's workspace"
    }
  },
  "data": {
    "...": "event-specific payload — see the per-event sections below"
  }
}
FieldTypeWhat does it tell you
versionstringThe version of this message format. Right now it’s always "1.0". If we ever change the shape in a way that could break things, we’ll bump this number and document the change.
eventstringWhich event happened, e.g. issue.created.
timestampISO-8601 stringThe moment we queued the message (UTC, down to fractions of a second).
site.idintegerThe numeric ID of the site in AAArdvark.
site.namestringThe site’s friendly name.
site.urlstring | nullThe site URL is set in your dashboard.
site.base_urlstringThe starting point we crawl from for this site.
site.workspace.idintegerThe numeric ID of the workspace the site lives in.
site.workspace.namestringThe workspace’s friendly name.
dataobjectThe event-specific details. What’s inside depends on which event fired – see the sections below.
is_replaybooleanOnly appears when the message is part of a “Sync all existing data” backfill. When present, it’s always true; on normal real-time messages, it isn’t sent at all.

When a new issue is found

This message (issue.created) arrives the first time a particular kind of accessibility problem is logged for your site.

{
  "version": "1.0",
  "event": "issue.created",
  "timestamp": "2026-06-04T21:32:50.209952Z",
  "site": {
    "id": 1428,
    "name": "site care",
    "url": null,
    "base_url": "https://sitecare.com",
    "workspace": { "id": 1, "name": "Abdulkhalek's workspace" }
  },
  "data": {
    "type": "created",
    "issue": {
      "id": 2745,
      "unique_site_issue_id": 1,
      "site_id": 1428,
      "first_scan_id": 1271,
      "scan_id": 1512,
      "status": "active",
      "issue_type": "automatic",
      "failure": "color-contrast",
      "principle": "WCAG2:perceivable",
      "success_criteria": "1.4.3",
      "severity": "Very High",
      "priority": "5",
      "message": "Elements must meet minimum color contrast ratio thresholds",
      "recommended_techniques": ["G18", "G145", "G148", "G174"],
      "assignee_name": "Unassigned",
      "user_id": null,
      "assignee": null,
      "reporter_id": null,
      "custom_severity": null,
      "original_severity": null,
      "original_failure": null,
      "custom_issue_id": null,
      "level": "",
      "converted": 0,
      "previous_status": null,
      "created_at": "2025-08-07T22:46:15.000000Z",
      "updated_at": "2025-09-26T01:44:59.000000Z",
      "link": "https://staging.aaardvarkaccessibility.com/dashboard/site/1732da/issues/2745",
      "payload": { "...": "axe/htmlcs/ace runner output" }
    }
  }
}

Inside data.issue, the fields worth knowing are:

FieldTypeWhat does it tell you
idintegerOur internal ID for the issue – unique across the whole system.
unique_site_issue_idintegerThe friendly per-site number you see in the dashboard (#1, #2, #3…).
site_idintegerWhich site this belongs to (matches site.id in the envelope).
first_scan_idintegerThe scan that first spotted this issue.
scan_idintegerThe most recent scan that included it.
statusstringWhere the issue stands: activeresolved_pendingresolvedresolved_manual, or ignored.
issue_typestringautomatic (found by a scan) or manual (logged by a person).
failurestringThe kind of WCAG failure, e.g. color-contrast or image-alt.
principlestringThe WCAG principle it rolls up to, e.g. WCAG2:perceivable.
success_criteriastringThe specific WCAG success criterion, e.g. 1.4.3.
severitystringHow serious it is: Critical, Very High, High, Moderate, Low, Warning, or Notice.
prioritystringA priority from 1 to 5 (5 is highest), sent as text.
messagestringA plain-language summary of the problem.
recommended_techniquesarray of stringsWCAG technique IDs (like G18) suggested for fixing it.
assignee_namestringUnassigned, or the name of whoever it’s assigned to.
user_idinteger | nullThe numeric ID of the assignee, if there is one.
linkstringA direct link to view the issue in AAArdvark.
payloadobjectThe raw output from the scanner. Useful bits include selectorcontextboundingBox, and helpUrl. Handy for pinpointing and reproducing the problem; otherwise you can ignore it.
created_at / updated_atISO-8601 stringWhen the issue was first logged, and last changed.
previous_statusoriginal_severityoriginal_failurestring | nullFilled in only when an issue is reclassified.
data.typestringAlways "created" here.

When an issue changes status

The issue.status_changed message arrives whenever an issue moves from one state to another – for example, when a team member marks it Resolved Pending, or when a scan confirms all its instances are fixed. The two fields data.previous_status and data.new_status tell you exactly what changed.

{
  "version": "1.0",
  "event": "issue.status_changed",
  "timestamp": "2026-06-04T21:32:50.229250Z",
  "site": { "id": 1428, "name": "site care", "url": null, "base_url": "https://sitecare.com", "workspace": { "id": 1, "name": "Abdulkhalek's workspace" } },
  "data": {
    "type": "status_changed",
    "previous_status": "active",
    "new_status": "resolved_pending",
    "issue": {
      "id": 2745,
      "unique_site_issue_id": 1,
      "status": "resolved_pending",
      "...": "(same shape as issue.created — full issue object)"
    }
  }
}
FieldTypeWhat does it tell you
data.typestringAlways "status_changed".
data.previous_statusstringWhere the issue was before the change. Same set of values as issue.status.
data.new_statusstringWhere it is now. Matches data.issue.status.
data.issueobjectThe full issue, same shape as on a new-issue message.

Two “previous status” fields – what’s the difference? data.previous_status is the status the issue had just before this particular change – the “from” side of the move you’re being told about. data.issue.previous_status is something else: it’s set when an issue was reclassified (say, its severity changed). The two often hold different values, so don’t treat them as the same thing.


When a new issue instance is found

An issue is the type of problem; an instance is one real occurrence of it on a page. The same issue can have many instances – one for every element that trips the same rule. This message (issue_instance.created) fires when a new one of those occurrences is logged.

{
  "version": "1.0",
  "event": "issue_instance.created",
  "timestamp": "2026-06-04T21:32:50.232343Z",
  "site": { "id": 1428, "name": "site care", "url": null, "base_url": "https://sitecare.com", "workspace": { "id": 1, "name": "Abdulkhalek's workspace" } },
  "data": {
    "type": "created",
    "issue_instance": {
      "id": 197377,
      "unique_issue_instance_id": 1,
      "site_id": 1428,
      "page_id": 15209,
      "issue_id": 2745,
      "first_scan_id": 1271,
      "scan_id": 1272,
      "status": 0,
      "ignored": 0,
      "needs_review": 0,
      "code": "color-contrast",
      "runner": "axe",
      "severity": "Very High",
      "custom_severity": null,
      "original_severity": null,
      "converted": 0,
      "issue_type": "automatic",
      "selector": "#cp_popup_id_21429 > div:nth-child(2) > div > span",
      "context": "<span class=\"cp-open-toggle-content\">Check My Site Health </span>",
      "instance_details": "Fix any of the following:\n Element has insufficient color contrast of 4.07 (foreground color: #ffeefa, background color: #e00099, font size: 12.0pt (16px), font weight: normal). Expected contrast ratio of 4.5:1",
      "note": "",
      "steps_to_visible": "",
      "test_mode": null,
      "recommended_techniques": ["G18", "G145", "G148", "G174"],
      "fingerprint": null,
      "created_at": "2025-08-07T22:46:16.000000Z",
      "updated_at": "2026-01-22T03:18:55.000000Z"
    }
  }
}

Inside data.issue_instance:

FieldTypeWhat does it tell you
idintegerOur internal ID for this instance.
unique_issue_instance_idintegerThe friendly per-issue number shown in the dashboard.
site_idintegerWhich site is it on?
page_idintegerWhich page does it appear on?
issue_idintegerThe parent issue this is an example of.
first_scan_idintegerThe scan that first found this exact occurrence.
scan_idintegerThe most recent scan that saw it.
statusintegerA numeric state: -1 Reopened, 0 Unfixed, 1 Fixed Pending, 2 Fixed.
ignoredinteger (0/1)1 if someone dismissed this occurrence.
needs_reviewinteger (0/1)1 if it’s been flagged for a human to look at.
codestringThe scanner’s code for the failure, e.g. color-contrast.
runnerstringWhich scanner caught it: axehtmlcs, or ace.
severitystringCritical, Very High, High, Moderate, Low, Warning, or Notice.
issue_typestringautomatic or manual.
selectorstringA CSS selector pointing right at the offending element.
contextstringThe HTML of that element (trimmed to a sensible length).
instance_detailsstringThe scanner’s plain explanation of why this one fails – e.g. the exact contrast ratio.
notestringAny free-text note someone added. Empty if none.
steps_to_visiblestringNotes on how to make this element visible on the page (e.g., “click the menu first”).
recommended_techniquesarray of stringsSuggested WCAG technique IDs for fixing it.
fingerprintstring | nullAn internal de-duplication marker; not usually useful to you.
created_at / updated_atISO-8601 stringWhen it was first logged and last changed.
data.typestringAlways "created" here.

When an instance changes status

This message (issue_instance.status_changed) arrives when one specific occurrence moves between states – for instance, when a scan notices a previously Unfixed element has now been fixed.

{
  "version": "1.0",
  "event": "issue_instance.status_changed",
  "timestamp": "2026-06-04T21:38:25.883650Z",
  "site": { "id": 1428, "name": "site care", "url": null, "base_url": "https://sitecare.com", "workspace": { "id": 1, "name": "Abdulkhalek's workspace" } },
  "data": {
    "type": "status_changed",
    "previous_status": "0",
    "new_status": "2",
    "issue_instance": {
      "id": 197377,
      "status": 2,
      "...": "(same shape as issue_instance.created — full issue_instance object)"
    }
  }
}
FieldTypeWhat does it tell you
data.typestringAlways "status_changed".
data.previous_statusstringWhere it was before, as the numeric code in quotes (e.g. "0""2").
data.new_statusstringWhere it is now, same quoted-number format. Matches data.issue_instance.status (which is sent as a plain number).
data.issue_instanceobjectThe full instance, same shape as on a new-instance message.

One small quirk to watch for: the instance status comes through as a number in data.issue_instance.status, but as a quoted string in data.previous_status and data.new_status. They mean the same thing either way – "-1" Reopened, "0" Unfixed, "1" Fixed Pending, "2" Fixed.


When a scan finishes

This message (scan.completed) lands when a scan wraps up – whether it succeeded or ran into trouble. It includes the full scan record, so you can see at a glance how many issues were added, resolved, or reopened.

{
  "version": "1.0",
  "event": "scan.completed",
  "timestamp": "2026-06-04T21:32:50.237500Z",
  "site": { "id": 1428, "name": "site care", "url": null, "base_url": "https://sitecare.com", "workspace": { "id": 1, "name": "Abdulkhalek's workspace" } },
  "data": {
    "type": "completed",
    "scan": {
      "id": 1271,
      "workspace_id": 1,
      "site_id": 1428,
      "type": 0,
      "status": 1,
      "source": "Manual",
      "batch_id": "9f949f36-164c-46d3-a16c-7be940300a9e",
      "statistics": {
        "errors": 11,
        "warnings": 8,
        "notices": 0,
        "new_issues": 19,
        "active_issues": 19,
        "reopened_issues": 0,
        "new_instances": 279,
        "total_instances": 279,
        "total_pages": 141,
        "example_pages": []
      },
      "crawl_successes": 141,
      "crawl_errors": 0,
      "processing_errors": 0,
      "started_at": null,
      "finished_at": null,
      "created_at": "2025-08-07T22:45:49.000000Z",
      "updated_at": "2025-08-07T22:54:03.000000Z",
      "message": null,
      "page_ids_to_scan": null,
      "chunk_offset": 0,
      "total_pages_to_scan": 0
    }
  }
}

Inside data.scan:

FieldTypeWhat does it tell you
idintegerOur internal ID for the scan.
workspace_idintegerThe workspace it belongs to.
site_idintegerThe site it ran against.
typeintegerThe scan type. 0 means a full whole-site scan; other values are partial scans.
statusinteger0 In Progress, 1 Completed, -1 Failed. A finished-scan message always carries 1 or -1.
sourcestringWhat kicked it off: ManualAutomated, and so on.
batch_idstring (UUID)An internal batch ID from our worker layer.
statistics.errorsintegerHow many error-level issues did this scan find?
statistics.warningsintegerHow many warning-level issues?
statistics.noticesintegerHow many notice-level issues?
statistics.new_issuesintegerIssues seen for the first time on this site.
statistics.active_issuesintegerIssues active on the site when the scan finished.
statistics.reopened_issuesintegerPreviously resolved issues that turned up again.
statistics.new_instancesintegerOccurrences found for the first time in this scan.
statistics.total_instancesintegerAll occurrences are active when the scan finishes.
statistics.total_pagesintegerHow many pages were crawled?
crawl_successesintegerPages crawled successfully.
crawl_errorsintegerPages that couldn’t be crawled.
processing_errorsintegerInternal hiccups while saving (usually 0).
created_atISO-8601 stringWhen the scan was queued.
updated_atISO-8601 stringWhen the record last changed (usually when it finished).
data.typestringAlways "completed" here.


Still stuck?

File a support ticket with our five-star support team to get more help.

File a ticket

  • This field is for validation purposes and should be left unchanged.
  • Please provide any information that will be helpful in helping you get your issue fixed. What have you tried already? What results did you expect? What did you get instead?

Related Guides