v1

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.

Read-first API with inbound evidence. The v1 API provides read access to your compliance data plus a focused write surface for pushing evidence into assessment questions (see Pushing Evidence In). All other write operations (creating assessments, updating findings) are managed through the AUDIGYD web application.

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

  1. Navigate to Workspace → API Keys in your AUDIGYD tenant
  2. Click Create API Key
  3. Enter a name (e.g., "Power BI Integration")
  4. Select the scopes your key needs (see Scope Reference)
  5. Optionally set an expiration date
  6. Copy the key immediately — it will only be shown once
Keep your API key secret. API keys grant access to your workspace data. Never commit them to version control or expose them in client-side code.

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:

HeaderDescription
X-RateLimit-LimitMaximum requests allowed per window (100)
X-RateLimit-RemainingRequests remaining in the current window
Retry-AfterSeconds 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:

ParameterDefaultDescription
page1Page number (1-indexed)
per_page25Items 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
  }
}
StatusMeaning
400Bad Request — invalid parameters
401Unauthorized — missing or invalid API key
403Forbidden — insufficient scopes
404Not Found — resource doesn't exist
429Too Many Requests — rate limit exceeded
500Internal Server Error

Overview

Get a high-level summary of your workspace's compliance posture.

GET /v1/overview Compliance summary with counts and breakdowns

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.

GET /v1/assessments List assessments with filters

Required scopes: assessments:read

Query Parameters

ParameterTypeDescription
statusstringFilter by status: draft, submitted, underReview, finalized, archived
updated_afterISO 8601Only return assessments updated after this date
updated_beforeISO 8601Only return assessments updated before this date
pageintegerPage number (default: 1)
per_pageintegerItems 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
  }
}
GET /v1/assessments/:id Get assessment details

Required scopes: assessments:read

Path Parameters

ParameterDescription
idAssessment 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"
  }
}
GET /v1/assessments/:id/responses List question responses for an assessment

Required scopes: assessments:read

Query Parameters

ParameterTypeDescription
pageintegerPage number (default: 1)
per_pageintegerResults per page (default: 25, max: 100)
created_afterISO 8601Filter responses created after this date
created_beforeISO 8601Filter responses created before this date
updated_afterISO 8601Filter 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.

GET /v1/findings List findings with filters

Required scopes: findings:read

Query Parameters

ParameterTypeDescription
statusstringopen, acknowledged, resolved, accepted_risk
severitystringcritical, high, medium, low, info
assessment_idUUIDFilter findings by assessment
updated_afterISO 8601Only return findings updated after this date
updated_beforeISO 8601Only 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
  }
}
GET /v1/findings/:id Get finding details

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.

GET /v1/reports List reports

Required scopes: reports:read

Query Parameters

ParameterTypeDescription
statusstringdraft, generating, ready, failed
updated_afterISO 8601Only return reports updated after this date
updated_beforeISO 8601Only 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
  }
}
GET /v1/reports/:id/summary Get report summary and snapshot

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.

GET /v1/templates List templates

Required scopes: templates:read

Query Parameters

ParameterTypeDescription
statusstringdraft, 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.

POST /v1/assessments/:assessmentId/questions/:questionId/evidence Direct write — attach evidence to a specific question

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)

FieldTypeDescription
filefileThe evidence file (max 100MB)
sourcestringOptional. Free-text label for where the evidence came from (e.g. okta-export)
collected_atstring (ISO 8601)Optional. When the evidence was collected from the source system
notesstringOptional. Free-text reviewer-facing note
resultstringOptional. 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

StatusCodeWhen
404NOT_FOUNDAssessment or question not found in your tenant
409ASSESSMENT_FINALIZEDTarget assessment is finalized or archived
413PAYLOAD_TOO_LARGEJSON body > 1MB or file > 100MB
POST /v1/assessments/:assessmentId/evidence/push Push/match — let AUDIGYD find the right question by name

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

FieldTypeDescription
control_refstring (required)Substring of a domain or control area name in the assessment
question_matchstring (required)Substring of the question text
titlestring (required)Display title for the evidence (used for the JSON filename, sanitized)
sourcestringOptional source-system identifier
collected_atstring (ISO 8601)Optional collection timestamp
resultstringOptional pass | fail | info display-only badge
notesstringOptional reviewer-facing note
payloadobjectOptional arbitrary structured payload (stored as JSON evidence)
allow_multiplebooleanIf true and multiple questions match, attach to all of them (capped at 25)

Outcomes

  • One match201 with the attached evidence and matched question.
  • Multiple matches + allow_multiple: true201 with N evidence rows attached. The evidence.added webhook fires once per question.
  • Multiple matches without allow_multiple422 MULTIPLE_MATCHES with the candidate list so you can narrow question_match.
  • No match422 NO_MATCH with available_domains and available_control_areas for 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:

ScopeGrants Access To
assessments:readList assessments, get assessment details, get assessment responses
assessments:writePush evidence into assessment questions (direct-write and push/match endpoints)
findings:readList findings, get finding details
reports:readList reports, get report summaries
templates:readList templates
webhooks:writeManage webhook endpoints (create, update, delete, test)

The /v1/overview endpoint requires all three read scopes: assessments:read, findings:read, and reports:read.

Principle of least privilege. Only grant the scopes your integration actually needs. You can always create additional keys with different scope sets.

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

  1. Navigate to Workspace → Webhooks in your AUDIGYD tenant
  2. Click Add Endpoint
  3. Enter your HTTPS endpoint URL
  4. Select the events you want to receive
  5. Save — copy the signing secret (starts with whsec_)
  6. Use the Send Test button to verify your endpoint receives events
HTTPS required. Webhook endpoints must use HTTPS. Your server must respond with a 2xx status code within 10 seconds.

Event Types

EventTriggered When
assessment.createdA new assessment is created
assessment.submittedAn assessment is submitted for review
assessment.finalizedAn assessment review is completed and finalized
assessment.score_updatedAn assessment's compliance score changes
finding.createdA new finding/gap is identified
finding.status_changedA finding's status is updated (e.g., open → resolved)
finding.resolvedA finding is marked as resolved
report.generatedReport generation begins
report.readyA report is ready for download
evidence.addedEvidence 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:

HeaderDescription
X-AUDIGYD-SignatureHMAC-SHA256 signature of the request body
X-AUDIGYD-EventEvent type name (e.g., assessment.finalized)
Content-Typeapplication/json
User-AgentAUDIGYD-Webhooks/1.0

Retry Policy

Failed deliveries (non-2xx or timeout) are retried up to 5 times with exponential backoff:

AttemptDelay
1st retry1 minute
2nd retry5 minutes
3rd retry30 minutes
4th retry2 hours
5th retry6 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

ToolDescription
get_overviewHigh-level compliance summary with counts and breakdowns
list_assessmentsSearch and filter assessments by status, template, and date
get_assessmentDetailed scores and metadata for a specific assessment
get_assessment_responsesIndividual question answers, verdicts, and domain scores
list_findingsAudit issues and gaps, filterable by severity and status
get_score_trendHistorical compliance trajectory data

Connect with Claude.ai

Follow these steps to connect your AUDIGYD workspace to Claude:

  1. Create an API key in AUDIGYD with the scopes: assessments:read, findings:read, reports:read, templates:read
  2. Open Claude.ai → Settings → MCP Servers
  3. Click Add Server
  4. Enter the following configuration:
    {
      "mcpServers": {
        "audigyd": {
          "url": "https://audigyd.com/api/v1/mcp",
          "transport": "sse",
          "headers": {
            "X-API-Key": "aug_live_your_key_here"
          }
        }
      }
    }
  5. Save and start a new conversation — Claude will now have access to your AUDIGYD tools
Data access is scoped. The MCP server only has access to the data allowed by your API key's scopes. Create a dedicated key for AI access with read-only scopes.

Example Queries

Once connected, you can ask Claude questions like:

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:

The connection always requires:

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

  1. Open Power BI Desktop → Get DataWeb
  2. Select Advanced and enter:
    • URL: https://audigyd.com/api/v1/overview
    • HTTP request header: X-API-Key with your API key value
  3. Click OK — Power BI will fetch the JSON response
  4. Use Power Query to expand the nested data object into columns
  5. Repeat for /v1/assessments, /v1/findings, and /v1/reports to build a complete data model
  6. Set up scheduled refresh to keep your dashboards current
Tip: Create a Power Query parameter for your API key so you can manage it centrally and avoid hardcoding it into queries.

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

  1. Create a new Automated Cloud Flow
  2. Add the "When an HTTP request is received" trigger
  3. Copy the generated HTTP POST URL
  4. In AUDIGYD, create a webhook endpoint with this URL and subscribe to events like finding.created
  5. 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

  1. Create a new Scheduled Cloud Flow (e.g., daily at 8 AM)
  2. Add an HTTP action:
    • Method: GET
    • URI: https://audigyd.com/api/v1/overview
    • Header: X-API-Key: your_key
  3. 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>
  );
}
Security note: Never expose your API key in client-side code. Use a backend proxy that injects the API key server-side.

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.