Skip to content

Advanced

Retention audits

File a data-retention audit report after each cleanup run.

If your organization runs its own data-retention cleanup against its own database, it must file an audit report after each cleanup run by calling this endpoint. Reports are stored immutably under a prefix derived from your organization id.

Endpoint#

Request
POST https://core-api.heysadie.ai/v1/retention/audits
Content-Type: application/json
Authorization: ApiKey YOUR_ORG_API_KEY

This is a /v1 path

Unlike the rest of the API, the audit endpoints live under /v1. Authenticate with your organization-level API key — this endpoint is org-scoped, so no X-Tenant-Id header is required. Tenant-level keys are rejected with 401. See Organization-level access.

Payload#

The body is any JSON object you like — it is stored exactly as you send it. Your cleanup process is yours; report it in whatever shape it produces. Only three rules:

RuleDetail
runId (required)UUID, unique per cleanup run. It names the stored file — re-sending the same runId overwrites the same file, so retries are idempotent
finishedAt (recommended)ISO 8601. Anchors the year/month folder your audit is filed under; if omitted, the time of receipt is used
SizeMax 10MB per payload

source is not part of the payload — it is derived server-side from your authenticated organization id. You cannot write into another organization's audit prefix (any source you send is overwritten).

For reference, this is a reasonable template if you're starting from scratch:

Example payload
{
  "runId": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
  "retentionDays": 90,
  "cutoffDate": "2026-03-13T00:00:00.000Z",
  "startedAt": "2026-06-11T03:00:00.000Z",
  "finishedAt": "2026-06-11T03:01:30.000Z",
  "status": "completed",
  "callsScrubbed": 19080,
  "batchesExecuted": 39,
  "oldestCallDate": "2025-07-31T09:02:45.000Z",
  "newestCallDate": "2026-03-13T18:31:28.000Z",
  "scrubbedFields": ["transcript", "recording_url", "summary", "analysis", "messages"],
  "callIds": ["<scrubbed-call-id>", "..."]
}

Responses#

A successful submission returns the standard envelope with { "stored": true, "runId": "..." }.

StatusMeaningWhat to do
200Audit storedMark the run as reported
400Missing/invalid runId, payload over 10MB, or body is not a JSON objectFix the payload; do not retry as-is
401 / 403Bad or missing keyCheck your org API key
503Storage temporarily unavailable (RETENTION_AUDIT_STORAGE_FAILED)Keep the run marked unreported; re-send on your next cleanup run

Expected cadence#

Run your cleanup nightly (off-peak) and report each run right after it finishes. If a report fails, re-send it on your next run — runId idempotency makes this safe. OnCore alerts when an organization goes quiet for several days, so consistent reporting avoids false alarms.

Churned-customer cleanups

Cleaning up a churned customer's data (as opposed to the ongoing retention window) is reported to a separate endpoint — see Churn audits.