Skip to main content

Signed Compliance Reports: Prove Your Data Posture to Auditors in One API Call

· 6 min read
FoundryDB Team
Engineering @ FoundryDB

Every vendor security questionnaire asks the same questions. Where is the data stored? Is it encrypted at rest? Is it encrypted in transit? When was the last backup? How long do you keep audit logs? Answering them usually means a human logging into a console, taking screenshots, copying values into a spreadsheet, and hoping nobody changed anything between the screenshot and the audit.

The compliance report endpoint replaces that ritual with a single API call. It returns a JSON document describing your data posture across every service in your organization, and it attaches an HMAC-SHA256 signature over that document. An auditor can recompute the signature with a verification key and prove the report came from the platform and was not edited on the way to their desk.

One Call, Live State

The report lives at GET /organizations/{orgId}/compliance-report. Any member of the organization can fetch it.

curl -u $API_KEY:$API_SECRET \
https://api.foundrydb.com/organizations/$ORG_ID/compliance-report

There is nothing to schedule and no agent to run. Everything in the report is assembled from records the platform already keeps about your services: zones, encryption settings, backup history, audit log retention. The report reflects live state at the moment you generate it, so it is always current rather than a stale snapshot from the last time someone remembered to run an export.

What the Report Contains

The document has two halves: a per-service breakdown and an organization-wide summary.

For each service, the report records:

  • Zones and EU residency. Every zone the service runs in, each mapped to its region. The eu_residency flag is true only when all of the service's zones sit in European data centers. One zone outside Europe flips it to false.
  • Storage encryption at rest. Whether the underlying volumes are encrypted.
  • Backup encryption. The cipher protecting your backups (AES-256-GCM).
  • TLS status. Whether connections to the service are encrypted in transit.
  • Last completed backup. The timestamp and type of the most recent successful backup.
  • Backup schedule and retention. How often backups run and how many days they are kept.

The organization summary rolls these up:

  • Service count. How many services are covered.
  • all_services_eu_residency. A single flag that is true only when every service in the org is EU-resident.
  • Audit log coverage. The retention policy, the number of audit entries on record, and the timestamp of the oldest entry.

Here is the shape of a response, trimmed for clarity:

{
"report": {
"organization_id": "9a1b2c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d",
"generated_at": "2026-06-07T10:30:00Z",
"service_count": 2,
"all_services_eu_residency": true,
"services": [
{
"service_id": "d4e5f6a7-8b9c-0d1e-2f3a-4b5c6d7e8f90",
"name": "orders-prod",
"database_type": "postgresql",
"zones": ["se-sto1"],
"regions": ["europe"],
"eu_residency": true,
"storage_encrypted_at_rest": true,
"backup_encryption": "AES-256-GCM",
"tls_enabled": true,
"last_backup_at": "2026-06-07T02:00:14Z",
"last_backup_type": "automated",
"backup_schedule": "daily",
"backup_retention_days": 14
},
{
"service_id": "1f2a3b4c-5d6e-7f8a-9b0c-1d2e3f4a5b6c",
"name": "sessions-cache",
"database_type": "valkey",
"zones": ["fi-hel1"],
"regions": ["europe"],
"eu_residency": true,
"storage_encrypted_at_rest": true,
"backup_encryption": "AES-256-GCM",
"tls_enabled": true,
"last_backup_at": "2026-06-07T02:05:33Z",
"last_backup_type": "automated",
"backup_schedule": "daily",
"backup_retention_days": 7
}
],
"audit_log": {
"retention_policy_days": 365,
"entry_count": 48213,
"oldest_entry_at": "2025-06-12T08:41:09Z"
}
},
"signature": {
"algorithm": "HMAC-SHA256",
"value": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"
}
}

The Signature Is the Point

A JSON report on its own proves nothing. Anyone can hand-edit a field to say eu_residency: true before forwarding it to an auditor. The signature is what makes the document trustworthy.

The signature.value is a hex-encoded HMAC-SHA256 computed over the exact bytes of the report object as it appears in the response. An auditor who holds the verification key recomputes the HMAC over those same bytes and compares. If the values match, the report is authentic and untouched. If a single character of the report was changed, the recomputed signature will not match.

The key detail is "exact bytes." The signature covers the report object as serialized in the response, so verification has to read those bytes directly out of the raw payload rather than re-serializing a parsed object (which could reorder keys or change whitespace and break the comparison). Here is a verification script that extracts the report slice from the raw response and recomputes the HMAC:

import hmac
import hashlib

# The raw response body, exactly as returned by the API (bytes, not re-serialized).
with open("compliance-report.json", "rb") as f:
raw = f.read()

# The verification key, provided to your auditors out of band.
verification_key = b"your-verification-key"

# Extract the exact bytes of the "report" object: everything between
# the "report": marker and the ,"signature" that follows it.
start = raw.index(b'"report":') + len(b'"report":')
end = raw.index(b',"signature"', start)
report_bytes = raw[start:end]

# Recompute the HMAC-SHA256 over those bytes.
expected = hmac.new(verification_key, report_bytes, hashlib.sha256).hexdigest()

# Compare against the signature the platform returned.
import json
signature = json.loads(raw)["signature"]["value"]

if hmac.compare_digest(expected, signature):
print("Signature valid: report is authentic and unmodified.")
else:
print("Signature INVALID: report was modified or key is wrong.")

Use hmac.compare_digest for the comparison so the check runs in constant time and does not leak information through timing. Hand your auditor the signed JSON and the verification key separately, and they can confirm the document's integrity without trusting you, the email it arrived in, or the spreadsheet someone pasted it into.

Where This Fits

The report is built around the European data residency story. FoundryDB runs on EU zones (Stockholm, Helsinki, Frankfurt, and others), and the eu_residency and all_services_eu_residency flags let you assert, with a signature behind the assertion, that customer data never left Europe.

That makes the report a natural fit for several recurring obligations:

  • GDPR and vendor assessments. Most data processing questionnaires ask about residency, encryption at rest, encryption in transit, and backup handling. The report answers all four in one document, with proof attached.
  • SOC-style evidence collection. Auditors collecting control evidence get a signed artifact instead of screenshots, with timestamps they can verify rather than trust.
  • Recurring audits. Because the report is one API call against live state, you can regenerate it on demand or on a schedule. Last quarter's report and this quarter's report are both authentic and both verifiable.

In the Dashboard

If you would rather not script it, the organization page has a Compliance tab that renders the same report in a readable layout and offers a signed-JSON download. The downloaded file is byte-identical to the API response, so the signature on it verifies with the exact script above. Any member of the organization can open the tab and pull the report.

What's Next

Signed compliance reports are available now for every FoundryDB organization. To put one in front of your next auditor:

  • Fetch the report with GET /organizations/{orgId}/compliance-report
  • Run the verification script above to confirm the signature checks out
  • Share the signed JSON and the verification key with your auditor through separate channels
  • Read the Security overview for how residency, encryption, and audit logging are enforced underneath the report

If you are not yet on FoundryDB, sign up and have your first database running on European infrastructure in under five minutes.