Skip to Content
Elido is in closed beta — APIs are stable but rate-limits and quotas may change before GA. Request access →
GuidesSOC 2 / HIPAA evidence

SOC 2 / HIPAA evidence pack

The evidence endpoint snapshots a workspace’s live state — compliance mode + retention, members per role, custom roles, IP allowlist status, SSO / SCIM bindings, API key count, and audit-log volume over the trailing 30 / 90 days. It’s the artefact your auditor asks for when they say “show me on date X”, and the source-of-truth answer to ~80% of vendor security questionnaires.

The endpoint is read-only and gated on the compliance.view permission, so a “compliance officer” custom role can produce evidence without holding any other workspace mutations.

What you get

Two surfaces — same snapshot, different shape:

MethodPathShape
GET/v1/workspaces/{ws}/compliance/evidenceJSON
GET/v1/workspaces/{ws}/compliance/evidence.zipZIP archive

The JSON is the structured snapshot for tools (Vanta / Drata / your internal evidence tracker). The ZIP is what you hand a human auditor — same JSON inside, plus the trailing 90 days of audit events as CSV, current membership as CSV, the IP allowlist as CSV, and a README.md mapping each file to the SOC 2 control it covers.

JSON snapshot

curl 'https://api.elido.app/v1/workspaces/1/compliance/evidence' \ -H "Authorization: Bearer $ELIDO_TOKEN"
{ "workspace_id": 1, "collected_at": "2026-05-01T12:00:00Z", "controls_matrix_url": "https://docs.elido.app/compliance/SOC2", "posture": { "mode": "soc2", "audit_retention_days": 2190, "default_audit_retention_days": 730, "ip_allowlist_enabled": true, "ip_rules_count": 4 }, "access": { "members_total": 18, "members_by_role": { "owner": 1, "admin": 3, "editor": 9, "viewer": 5 }, "custom_roles_count": 2, "pending_invitations": 0, "api_keys_active": 6, "api_keys_last_created": "2026-04-12T08:30:00Z" }, "auditing": { "events_last_30_days": 4812, "events_last_90_days": 14201, "oldest_retained": "2024-04-30T00:00:00Z", "newest_event": "2026-05-01T11:58:43Z" }, "integrations": { "sso_bound": true, "scim_bound": true, "scim_enabled": true, "baa_signed_count": 1 } }

ZIP bundle

curl -OJ 'https://api.elido.app/v1/workspaces/1/compliance/evidence.zip' \ -H "Authorization: Bearer $ELIDO_TOKEN"

Bundle layout:

elido-evidence-1-20260501.zip ├── evidence.json (the snapshot above) ├── audit-events-90d.csv (trailing 90d audit log) ├── members.csv (current workspace membership) ├── ip-rules.csv (current IP allowlist) └── README.md (file → SOC 2 control mapping)

audit-events-90d.csv is hard-capped at 90 days because evidence packs are reviewed point-in-time; longer trails should come from your SIEM webhook firehose (webhooks guide) which streams every event in near-real-time to your own SIEM.

Mapping to SOC 2 controls

The bundle’s README.md maps each file to the AICPA Trust Services Criteria your auditor will tick off. Summary:

FileMaps to
evidence.json (whole snapshot)CC1.5 (accountability), CC6.1 (logical access), CC7.1 (monitoring)
audit-events-90d.csvCC1.5 (accountability evidence), CC4.1 (monitoring), CC7.1 (event detection)
members.csvCC6.1 (restrict access), CC6.3 (authorise users), CC6.5 (deprovision)
ip-rules.csvCC6.6 (logical access — protect external)

The full control-matrix narrative lives at docs/compliance/SOC2 — the controls_matrix_url field in the snapshot points there.

Self-hosting note

The endpoint is part of services/api-core and runs on the same Postgres pool as the rest of the API — no extra moving parts. The trailing-90d audit-log stream is bounded by your workspace’s audit_retention_days; a HIPAA workspace at 2190d retention can produce a 6-year history if you ever need it (export the bundle multiple times across the window).

SDK

import { ElidoApi } from "@elido/sdk"; const api = new ElidoApi({ baseUrl, token }); const snap = await api.compliance.evidence(workspaceId); console.log(snap.access.members_by_role); // For the ZIP, hand the URL to a download mechanism — fetch + stream // to disk, or `<a href download>` in a browser. window.location.href = api.compliance.evidenceBundleUrl(workspaceId);
import "github.com/elidoapp/elido/packages/sdk-go/elido" c, _ := elido.New(elido.Options{BaseURL: baseURL, Token: token}) snap, _ := c.Compliance.Evidence(ctx, workspaceID) fmt.Println(snap.Posture.Mode) // ZIP URL — caller streams the body with its own auth header. zipURL := c.Compliance.EvidenceBundleURL(workspaceID)
import elido client = elido.Client(base_url=base_url, token=token) snap = client.compliance.evidence(workspace_id) print(snap["access"]["members_by_role"]) zip_url = client.compliance.evidence_bundle_url(workspace_id)

Endpoint reference

MethodPath
GET/v1/workspaces/{ws}/compliance/evidence
GET/v1/workspaces/{ws}/compliance/evidence.zip