AUDIGYD Developer Documentation
Access your audit, compliance, and governance data programmatically through the AUDIGYD REST API, Webhooks, and MCP integration.
The AUDIGYD External Data Platform lets you read assessment results, findings, reports, and templates from your workspace. Use it to build integrations with your existing tools — BI dashboards, automation workflows, SIEM systems, or AI assistants.
Authentication
All API requests are authenticated using API keys. You can create and manage API keys from your workspace under Settings → API Keys.
Creating an API Key
- Navigate to Workspace → API Keys in your AUDIGYD tenant
- Click Create API Key
- Enter a name (e.g., "Power BI Integration")
- Select the scopes your key needs (see Scope Reference)
- Optionally set an expiration date
- Copy the key immediately — it will only be shown once
Passing the API Key
Include your API key in the X-API-Key header of every request:
curl -H "X-API-Key: aug_live_your_key_here" \
https://audigyd.com/api/v1/overview
API keys follow the format aug_live_ followed by a random string. Keys that don't match this prefix will be rejected.
Base URL
All API endpoints are relative to the following base URL:
https://audigyd.com/api/v1
All requests must use HTTPS. HTTP requests will be rejected.
Rate Limiting
The API enforces a sliding-window rate limit of 100 requests per minute per API key. Rate limit information is returned in response headers:
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests allowed per window (100) |
X-RateLimit-Remaining | Requests remaining in the current window |
Retry-After | Seconds until the rate limit resets (only when exceeded) |
When you exceed the limit, the API returns 429 Too Many Requests. Implement exponential backoff or respect the Retry-After header.
Pagination
List endpoints return paginated results. Use these query parameters to control pagination:
| Parameter | Default | Description |
|---|---|---|
page | 1 | Page number (1-indexed) |
per_page | 25 | Items per page (max 100) |
Paginated responses include a meta object:
{
"data": [...],
"meta": {
"page": 1,
"per_page": 25,
"total": 142,
"total_pages": 6
}
}
Error Handling
The API uses standard HTTP status codes. Errors return a consistent JSON structure:
{
"error": {
"code": "INVALID_PARAMETER",
"message": "Invalid status filter. Must be one of: draft, submitted, underReview, finalized, archived",
"status": 400
}
}
| Status | Meaning |
|---|---|
400 | Bad Request — invalid parameters |
401 | Unauthorized — missing or invalid API key |
403 | Forbidden — insufficient scopes |
404 | Not Found — resource doesn't exist |
429 | Too Many Requests — rate limit exceeded |
500 | Internal Server Error |
Overview
Get a high-level summary of your workspace's compliance posture.
Required scopes: assessments:read findings:read reports:read (all required)
Response
{
"data": {
"assessments": {
"total": 47,
"by_status": {
"draft": 5,
"submitted": 8,
"underReview": 12,
"finalized": 20,
"archived": 2
}
},
"findings": {
"total": 163,
"by_status": {
"open": 45,
"acknowledged": 30,
"resolved": 80,
"accepted_risk": 8
},
"by_severity": {
"critical": 3,
"high": 18,
"medium": 52,
"low": 67,
"info": 23
}
},
"reports": {
"total": 34
}
}
}
Assessments
Retrieve assessment data including scores, statuses, and individual question responses.
Required scopes: assessments:read
Query Parameters
| Parameter | Type | Description |
|---|---|---|
status | string | Filter by status: draft, submitted, underReview, finalized, archived |
updated_after | ISO 8601 | Only return assessments updated after this date |
updated_before | ISO 8601 | Only return assessments updated before this date |
page | integer | Page number (default: 1) |
per_page | integer | Items per page (default: 25, max: 100) |
Response
{
"data": [
{
"id": "assess_abc123",
"name": "Q4 2025 SOC 2 Assessment",
"status": "finalized",
"score_envelope": {
"overall": 87.5,
"by_domain": {
"Access Control": 92.0,
"Change Management": 85.0,
"Data Protection": 88.0
}
},
"project_id": "proj_xyz",
"campaign_id": null,
"created_at": "2025-10-15T09:00:00Z",
"updated_at": "2025-12-01T14:30:00Z"
}
],
"meta": {
"page": 1,
"per_page": 25,
"total": 47,
"total_pages": 2
}
}
Required scopes: assessments:read
Path Parameters
| Parameter | Description |
|---|---|
id | Assessment UUID |
Response
{
"data": {
"id": "assess_abc123",
"name": "Q4 2025 SOC 2 Assessment",
"status": "finalized",
"score_envelope": {
"overall": 87.5,
"by_domain": {
"Access Control": 92.0,
"Change Management": 85.0
}
},
"project_id": "proj_xyz",
"campaign_id": null,
"created_at": "2025-10-15T09:00:00Z",
"updated_at": "2025-12-01T14:30:00Z"
}
}
Required scopes: assessments:read
Query Parameters
| Parameter | Type | Description |
|---|---|---|
page | integer | Page number (default: 1) |
per_page | integer | Results per page (default: 25, max: 100) |
created_after | ISO 8601 | Filter responses created after this date |
created_before | ISO 8601 | Filter responses created before this date |
updated_after | ISO 8601 | Filter responses updated after this date |
Response
{
"data": [
{
"id": "resp_abc123",
"question_id": "q_xyz789",
"answer": "Yes, quarterly access reviews are performed and documented.",
"is_na": false,
"computed_score": 1.0,
"computed_verdict": "compliant",
"reviewer_verdict": "compliant",
"reviewer_score": 1.0,
"is_overridden": false,
"saved_at": "2025-10-20T11:00:00Z",
"created_at": "2025-10-20T11:00:00Z",
"updated_at": "2025-10-20T11:05:00Z"
}
],
"meta": {
"page": 1,
"per_page": 25,
"total": 85,
"total_pages": 4
}
}
Findings
Access audit findings and gaps identified across your assessments.
Required scopes: findings:read
Query Parameters
| Parameter | Type | Description |
|---|---|---|
status | string | open, acknowledged, resolved, accepted_risk |
severity | string | critical, high, medium, low, info |
assessment_id | UUID | Filter findings by assessment |
updated_after | ISO 8601 | Only return findings updated after this date |
updated_before | ISO 8601 | Only return findings updated before this date |
Response
{
"data": [
{
"id": "find_abc123",
"title": "MFA not enforced for admin accounts",
"description": "Administrative accounts do not require multi-factor authentication.",
"severity": "critical",
"status": "open",
"assessment_id": "assess_abc123",
"created_at": "2025-10-22T08:30:00Z",
"updated_at": "2025-10-22T08:30:00Z"
}
],
"meta": {
"page": 1,
"per_page": 25,
"total": 163,
"total_pages": 7
}
}
Required scopes: findings:read
Response
{
"data": {
"id": "find_abc123",
"title": "MFA not enforced for admin accounts",
"description": "Administrative accounts do not require multi-factor authentication.",
"severity": "critical",
"status": "open",
"assessment_id": "assess_abc123",
"remediation": "Enable MFA for all admin accounts in the identity provider.",
"created_at": "2025-10-22T08:30:00Z",
"updated_at": "2025-10-22T08:30:00Z"
}
}
Reports
Access generated compliance reports and their summaries.
Required scopes: reports:read
Query Parameters
| Parameter | Type | Description |
|---|---|---|
status | string | draft, generating, ready, failed |
updated_after | ISO 8601 | Only return reports updated after this date |
updated_before | ISO 8601 | Only return reports updated before this date |
Response
{
"data": [
{
"id": "rpt_abc123",
"name": "SOC 2 Type II Annual Report",
"status": "ready",
"created_at": "2025-11-01T10:00:00Z",
"updated_at": "2025-11-01T10:15:00Z"
}
],
"meta": {
"page": 1,
"per_page": 25,
"total": 34,
"total_pages": 2
}
}
Required scopes: reports:read
Response
{
"data": {
"id": "rpt_abc123",
"name": "SOC 2 Type II Annual Report",
"status": "ready",
"summary": "Overall compliance score of 87.5% across 47 assessments...",
"ai_interpretation": "The organization demonstrates strong compliance posture...",
"snapshot": {
"assessment_count": 47,
"finding_count": 163,
"selected_views": ["by_domain", "trend"]
},
"created_at": "2025-11-01T10:00:00Z"
}
}
Templates
List assessment templates available in your workspace.
Required scopes: templates:read
Query Parameters
| Parameter | Type | Description |
|---|---|---|
status | string | draft, published, archived |
Response
{
"data": [
{
"id": "tmpl_abc123",
"name": "SOC 2 Type II",
"description": "Complete SOC 2 Type II assessment template",
"status": "published",
"question_count": 156,
"domain_count": 12,
"created_at": "2025-01-15T09:00:00Z",
"updated_at": "2025-06-20T11:30:00Z"
}
],
"meta": {
"page": 1,
"per_page": 25,
"total": 12,
"total_pages": 1
}
}
Pushing Evidence In
AUDIGYD provides the pipe; you own the relationship with your source systems. Instead of building native connectors to Okta, AWS, Jamf, or whatever else lives in your stack, you script the integration on your side and push evidence into AUDIGYD via two write endpoints. No third-party credentials are stored in AUDIGYD, and you keep full control over the data flow.
Both endpoints require the assessments:write scope, enforce the same tenant isolation as the read API, run files through the same malware-scan pipeline as in-app uploads, and reject pushes to finalized assessments with 409.
Required scopes: assessments:write
Use this endpoint when your integration knows the AUDIGYD assessment and question UUIDs. Accepts either a multipart file upload or a structured JSON payload (auto-detected from Content-Type).
Multipart fields (Content-Type: multipart/form-data)
| Field | Type | Description |
|---|---|---|
file | file | The evidence file (max 100MB) |
source | string | Optional. Free-text label for where the evidence came from (e.g. okta-export) |
collected_at | string (ISO 8601) | Optional. When the evidence was collected from the source system |
notes | string | Optional. Free-text reviewer-facing note |
result | string | Optional. pass, fail, or info. Display-only label — does not change the question's answer or score |
JSON body (Content-Type: application/json, max 1MB)
{
"title": "okta-mfa-enforcement-2026-04-17",
"source": "okta",
"collected_at": "2026-04-17T10:00:00Z",
"result": "pass",
"notes": "All admins enrolled in WebAuthn",
"payload": {
"policy_id": "rul_xxx",
"enforced_factors": ["webauthn"],
"enrolled_users": 42
}
}
Response (201)
{
"data": {
"id": "evd_8f14e45f-ceea-4d6a-8f43-5c7b2e1a3b4d",
"assessment_id": "assess_abc123",
"question_id": "q_xyz789",
"file_name": "okta-mfa-enforcement-2026-04-17.json",
"file_size": 184,
"mime_type": "application/json",
"scan_status": "skipped",
"result": "pass",
"source": "okta",
"collected_at": "2026-04-17T10:00:00Z",
"created_at": "2026-04-17T10:00:01Z"
}
}
Error responses
| Status | Code | When |
|---|---|---|
| 404 | NOT_FOUND | Assessment or question not found in your tenant |
| 409 | ASSESSMENT_FINALIZED | Target assessment is finalized or archived |
| 413 | PAYLOAD_TOO_LARGE | JSON body > 1MB or file > 100MB |
Required scopes: assessments:write
Use this when your automation tool (Power Automate, cron job, n8n) doesn't know AUDIGYD's internal IDs. AUDIGYD finds questions whose domain or control area name contains control_ref AND whose question text contains question_match (both case-insensitive partial match).
JSON body
| Field | Type | Description |
|---|---|---|
control_ref | string (required) | Substring of a domain or control area name in the assessment |
question_match | string (required) | Substring of the question text |
title | string (required) | Display title for the evidence (used for the JSON filename, sanitized) |
source | string | Optional source-system identifier |
collected_at | string (ISO 8601) | Optional collection timestamp |
result | string | Optional pass | fail | info display-only badge |
notes | string | Optional reviewer-facing note |
payload | object | Optional arbitrary structured payload (stored as JSON evidence) |
allow_multiple | boolean | If true and multiple questions match, attach to all of them (capped at 25) |
Outcomes
- One match →
201with the attached evidence and matched question. - Multiple matches +
allow_multiple: true→201with N evidence rows attached. Theevidence.addedwebhook fires once per question. - Multiple matches without
allow_multiple→422 MULTIPLE_MATCHESwith the candidate list so you can narrowquestion_match. - No match →
422 NO_MATCHwithavailable_domainsandavailable_control_areasfor the assessment.
Use Case Examples
Configure an HTTP action with these settings:
Method: POST
URL: https://audigyd.com/api/v1/assessments/@{variables('assessmentId')}/evidence/push
Headers:
X-API-Key: @{secrets('AUDIGYD_KEY')}
Content-Type: application/json
Body:
{
"control_ref": "Access Control",
"question_match": "MFA enforced for admin",
"title": "Okta MFA Policy Snapshot @{utcNow()}",
"source": "okta",
"collected_at": "@{utcNow()}",
"result": "pass",
"payload": @{outputs('Get_Okta_Policy')?['body']}
}
#!/usr/bin/env bash
set -euo pipefail
# Required positional args:
# $1 = AUDIGYD assessment ID
# $2 = AUDIGYD question ID (look up via GET /v1/assessments/:id/questions
# or use the push/match endpoint to resolve by name)
# $3 = path to file to upload
ASSESSMENT_ID="$1"
QUESTION_ID="$2"
EVIDENCE_FILE="$3"
curl -fsS \
-H "X-API-Key: $AUDIGYD_KEY" \
-F "file=@${EVIDENCE_FILE}" \
-F "source=jamf-export" \
-F "collected_at=$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
-F "result=pass" \
"https://audigyd.com/api/v1/assessments/${ASSESSMENT_ID}/questions/${QUESTION_ID}/evidence"
import os, json, requests
API_KEY = os.environ["AUDIGYD_KEY"]
ASSESSMENT_ID = os.environ["AUDIGYD_ASSESSMENT_ID"]
resp = requests.post(
f"https://audigyd.com/api/v1/assessments/{ASSESSMENT_ID}/evidence/push",
headers={"X-API-Key": API_KEY, "Content-Type": "application/json"},
data=json.dumps({
"control_ref": "Logging",
"question_match": "centralized logging",
"title": "CloudTrail multi-region status",
"source": "aws",
"result": "pass",
"payload": {"multi_region": True, "log_file_validation": True},
}),
timeout=30,
)
resp.raise_for_status()
print(resp.json())
Scope Reference
When creating an API key, you select which scopes it should have. Each scope grants access to specific endpoints:
| Scope | Grants Access To |
|---|---|
assessments:read | List assessments, get assessment details, get assessment responses |
assessments:write | Push evidence into assessment questions (direct-write and push/match endpoints) |
findings:read | List findings, get finding details |
reports:read | List reports, get report summaries |
templates:read | List templates |
webhooks:write | Manage webhook endpoints (create, update, delete, test) |
The /v1/overview endpoint requires all three read scopes: assessments:read, findings:read, and reports:read.
Webhooks
Webhooks push real-time event notifications to your endpoints when things happen in AUDIGYD — an assessment is finalized, a finding is created, a report is ready. No polling required.
Setting Up a Webhook
- Navigate to Workspace → Webhooks in your AUDIGYD tenant
- Click Add Endpoint
- Enter your HTTPS endpoint URL
- Select the events you want to receive
- Save — copy the signing secret (starts with
whsec_) - Use the Send Test button to verify your endpoint receives events
Event Types
| Event | Triggered When |
|---|---|
assessment.created | A new assessment is created |
assessment.submitted | An assessment is submitted for review |
assessment.finalized | An assessment review is completed and finalized |
assessment.score_updated | An assessment's compliance score changes |
finding.created | A new finding/gap is identified |
finding.status_changed | A finding's status is updated (e.g., open → resolved) |
finding.resolved | A finding is marked as resolved |
report.generated | Report generation begins |
report.ready | A report is ready for download |
evidence.added | Evidence is attached to an assessment question via the inbound API (fires once per question) |
Payload Structure
Every webhook delivery is an HTTP POST with a JSON body following this structure:
{
"id": "evt_8f14e45f-ceea-4d6a-8f43-5c7b2e1a3b4d",
"event": "assessment.finalized",
"tenant_id": "ten_abc123",
"created_at": "2025-12-01T14:30:00Z",
"data": {
"id": "assess_abc123",
"name": "Q4 2025 SOC 2 Assessment",
"status": "finalized",
"scoreEnvelope": {
"overall": 87.5,
"by_domain": {
"Access Control": 92.0,
"Change Management": 85.0
}
}
}
}
Webhook requests include these headers:
| Header | Description |
|---|---|
X-AUDIGYD-Signature | HMAC-SHA256 signature of the request body |
X-AUDIGYD-Event | Event type name (e.g., assessment.finalized) |
Content-Type | application/json |
User-Agent | AUDIGYD-Webhooks/1.0 |
Retry Policy
Failed deliveries (non-2xx or timeout) are retried up to 5 times with exponential backoff:
| Attempt | Delay |
|---|---|
| 1st retry | 1 minute |
| 2nd retry | 5 minutes |
| 3rd retry | 30 minutes |
| 4th retry | 2 hours |
| 5th retry | 6 hours |
If all 5 retries fail consecutively, the endpoint is automatically deactivated and you will receive an email notification.
Signature Verification
Always verify webhook signatures to ensure the request actually came from AUDIGYD. The signature is an HMAC-SHA256 hash of the raw request body, using your signing secret as the key.
const crypto = require("crypto");
function verifyWebhookSignature(body, signature, secret) {
const expected = crypto
.createHmac("sha256", secret)
.update(body)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
// Express middleware example
app.post("/webhooks/audigyd", express.raw({ type: "application/json" }), (req, res) => {
const signature = req.headers["x-audigyd-signature"];
const isValid = verifyWebhookSignature(req.body, signature, process.env.AUDIGYD_WEBHOOK_SECRET);
if (!isValid) {
return res.status(401).json({ error: "Invalid signature" });
}
const event = JSON.parse(req.body);
console.log(`Received event: ${event.event}`, event.data);
// Process the event...
res.status(200).json({ received: true });
});
import hmac
import hashlib
from flask import Flask, request, jsonify
app = Flask(__name__)
def verify_webhook_signature(body: bytes, signature: str, secret: str) -> bool:
expected = hmac.new(
secret.encode("utf-8"),
body,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(signature, expected)
@app.route("/webhooks/audigyd", methods=["POST"])
def handle_webhook():
signature = request.headers.get("X-AUDIGYD-Signature", "")
is_valid = verify_webhook_signature(
request.get_data(),
signature,
os.environ["AUDIGYD_WEBHOOK_SECRET"]
)
if not is_valid:
return jsonify({"error": "Invalid signature"}), 401
event = request.get_json()
print(f"Received event: {event['event']}", event["data"])
# Process the event...
return jsonify({"received": True}), 200
MCP (AI Integration)
The Model Context Protocol (MCP) lets you connect AUDIGYD directly to AI assistants like Claude, enabling natural-language queries over your compliance data. Instead of building dashboards or writing API calls, just ask questions.
AUDIGYD exposes an MCP-compatible server that translates AI tool calls into API queries. Your data stays secure — every request is authenticated with your API key and scoped to your tenant.
Available MCP Tools
| Tool | Description |
|---|---|
get_overview | High-level compliance summary with counts and breakdowns |
list_assessments | Search and filter assessments by status, template, and date |
get_assessment | Detailed scores and metadata for a specific assessment |
get_assessment_responses | Individual question answers, verdicts, and domain scores |
list_findings | Audit issues and gaps, filterable by severity and status |
get_score_trend | Historical compliance trajectory data |
Connect with Claude.ai
Follow these steps to connect your AUDIGYD workspace to Claude:
- Create an API key in AUDIGYD with the scopes:
assessments:read,findings:read,reports:read,templates:read - Open Claude.ai → Settings → MCP Servers
- Click Add Server
- Enter the following configuration:
{ "mcpServers": { "audigyd": { "url": "https://audigyd.com/api/v1/mcp", "transport": "sse", "headers": { "X-API-Key": "aug_live_your_key_here" } } } } - Save and start a new conversation — Claude will now have access to your AUDIGYD tools
Example Queries
Once connected, you can ask Claude questions like:
- "What's our overall compliance posture right now?"
- "Show me all critical findings that are still open"
- "How has our SOC 2 compliance score trended over the last 6 months?"
- "Summarize the results from our latest ISO 27001 assessment"
- "Which domains have the most findings?"
- "List all assessments that were finalized this quarter"
- "What's the remediation status for our high-severity findings?"
Claude will automatically use the appropriate MCP tools to fetch and analyze your data, providing insights in natural language.
Other MCP Clients
AUDIGYD's MCP server uses the standard HTTP + SSE transport, making it compatible with any MCP-compliant client. While we provide step-by-step instructions for Claude.ai above, the same connection details work with:
- Cursor — Add the server in Cursor's MCP settings with the same JSON configuration
- Windsurf — Configure via the MCP server settings panel
- Custom clients — Any client implementing the MCP specification can connect using the SSE transport
The connection always requires:
- Server URL:
https://audigyd.com/api/v1/mcp - Transport:
sse(Server-Sent Events over HTTP) - Authentication:
X-API-Keyheader with your API key
Quick Start Examples
Get started quickly with these copy-paste examples in your preferred language.
Fetch Compliance Overview
curl -s \
-H "X-API-Key: aug_live_your_key_here" \
https://audigyd.com/api/v1/overview | jq .
const API_KEY = process.env.AUDIGYD_API_KEY;
const BASE_URL = "https://audigyd.com/api/v1";
async function getOverview() {
const response = await fetch(`${BASE_URL}/overview`, {
headers: { "X-API-Key": API_KEY },
});
if (!response.ok) {
throw new Error(`API error: ${response.status}`);
}
const { data } = await response.json();
console.log("Assessments:", data.assessments.total);
console.log("Open findings:", data.findings.by_status.open);
return data;
}
getOverview();
import os
import requests
API_KEY = os.environ["AUDIGYD_API_KEY"]
BASE_URL = "https://audigyd.com/api/v1"
def get_overview():
response = requests.get(
f"{BASE_URL}/overview",
headers={"X-API-Key": API_KEY},
)
response.raise_for_status()
data = response.json()["data"]
print(f"Assessments: {data['assessments']['total']}")
print(f"Open findings: {data['findings']['by_status']['open']}")
return data
get_overview()
List Critical Findings
curl -s \
-H "X-API-Key: aug_live_your_key_here" \
"https://audigyd.com/api/v1/findings?severity=critical&status=open" | jq .
async function getCriticalFindings() {
const params = new URLSearchParams({
severity: "critical",
status: "open",
per_page: "100",
});
const response = await fetch(`${BASE_URL}/findings?${params}`, {
headers: { "X-API-Key": API_KEY },
});
const { data, meta } = await response.json();
console.log(`Found ${meta.total} critical open findings`);
for (const finding of data) {
console.log(`[${finding.severity}] ${finding.title}`);
}
return data;
}
getCriticalFindings();
def get_critical_findings():
response = requests.get(
f"{BASE_URL}/findings",
headers={"X-API-Key": API_KEY},
params={
"severity": "critical",
"status": "open",
"per_page": 100,
},
)
response.raise_for_status()
result = response.json()
print(f"Found {result['meta']['total']} critical open findings")
for finding in result["data"]:
print(f"[{finding['severity']}] {finding['title']}")
return result["data"]
get_critical_findings()
Paginate Through All Assessments
async function getAllAssessments() {
const all = [];
let page = 1;
while (true) {
const params = new URLSearchParams({
page: String(page),
per_page: "100",
status: "finalized",
});
const response = await fetch(`${BASE_URL}/assessments?${params}`, {
headers: { "X-API-Key": API_KEY },
});
const { data, meta } = await response.json();
all.push(...data);
if (page >= meta.total_pages) break;
page++;
}
console.log(`Fetched ${all.length} finalized assessments`);
return all;
}
getAllAssessments();
def get_all_assessments():
all_assessments = []
page = 1
while True:
response = requests.get(
f"{BASE_URL}/assessments",
headers={"X-API-Key": API_KEY},
params={
"page": page,
"per_page": 100,
"status": "finalized",
},
)
response.raise_for_status()
result = response.json()
all_assessments.extend(result["data"])
if page >= result["meta"]["total_pages"]:
break
page += 1
print(f"Fetched {len(all_assessments)} finalized assessments")
return all_assessments
get_all_assessments()
Power BI Integration
Connect AUDIGYD data to Power BI for rich compliance dashboards and executive reporting.
Step-by-Step Setup
- Open Power BI Desktop → Get Data → Web
- Select Advanced and enter:
- URL:
https://audigyd.com/api/v1/overview - HTTP request header:
X-API-Keywith your API key value
- URL:
- Click OK — Power BI will fetch the JSON response
- Use Power Query to expand the nested
dataobject into columns - Repeat for
/v1/assessments,/v1/findings, and/v1/reportsto build a complete data model - Set up scheduled refresh to keep your dashboards current
Power Query M Example
let
ApiKey = Excel.CurrentWorkbook(){[Name="AUDIGYD_API_KEY"]}[Content]{0}[Column1],
Source = Json.Document(
Web.Contents(
"https://audigyd.com/api/v1/findings",
[
Headers = [#"X-API-Key" = ApiKey],
Query = [severity = "critical", status = "open", per_page = "100"]
]
)
),
Data = Source[data],
AsTable = Table.FromList(Data, Splitter.SplitByNothing(), null, null, ExtraValues.Error)
in
AsTable
Power Automate
Use Microsoft Power Automate (formerly Flow) to build automated workflows triggered by AUDIGYD webhooks or scheduled API polls.
Webhook-Triggered Flow
- Create a new Automated Cloud Flow
- Add the "When an HTTP request is received" trigger
- Copy the generated HTTP POST URL
- In AUDIGYD, create a webhook endpoint with this URL and subscribe to events like
finding.created - Add flow actions to:
- Parse the JSON payload
- Send a Teams notification for critical findings
- Create a Jira/ADO ticket for remediation
- Update a SharePoint list for tracking
Scheduled Polling Flow
- Create a new Scheduled Cloud Flow (e.g., daily at 8 AM)
- Add an HTTP action:
- Method: GET
- URI:
https://audigyd.com/api/v1/overview - Header:
X-API-Key: your_key
- Parse the response and route to a Teams channel or email digest
Custom Dashboards
Build your own compliance dashboards using the AUDIGYD API as a data source. Here's a minimal React example:
import { useEffect, useState } from "react";
function ComplianceDashboard() {
const [overview, setOverview] = useState(null);
useEffect(() => {
fetch("/api/proxy/audigyd/overview")
.then((res) => res.json())
.then((json) => setOverview(json.data));
}, []);
if (!overview) return <div>Loading...</div>;
return (
<div className="dashboard">
<div className="metric-card">
<h3>Total Assessments</h3>
<span className="value">{overview.assessments.total}</span>
</div>
<div className="metric-card">
<h3>Open Findings</h3>
<span className="value">{overview.findings.by_status.open}</span>
</div>
<div className="metric-card">
<h3>Critical Issues</h3>
<span className="value danger">
{overview.findings.by_severity.critical}
</span>
</div>
</div>
);
}
For more complex dashboards, consider pairing the API with charting libraries like Recharts, Chart.js, or D3 to visualize compliance trends, finding distributions, and score breakdowns.