Skip to main content
Matcher’s governance surface groups the three compliance-facing capabilities under /v1/governance: actor mappings (link opaque actor IDs to PII, with GDPR pseudonymize/erasure), archives (download completed audit-log archives from cold storage), and audit logs (immutable, hash-chained history you can independently re-verify). The tenant is always resolved from the JWT — never from a path or body.
Every governance route is scoped to the caller’s tenant. Actor-mapping reads are split into two authorization tiers: the PII-free list versus the single-record de-anonymization read, so identity resolution stays separable from browse access.

Actor mappings


An actor mapping links an opaque actorId (for example user:550e8400-e29b-41d4-a716-446655440000) to human-readable PII (displayName, email). List rows are PII-free by design — only the single-record GET returns cleartext identity.

List actor mappings

Cursor-paginated, PII-free rows. Filter by an actor-ID prefix.
curl -X GET "https://api.matcher.example.com/v1/governance/actor-mappings?actorId=user:&limit=25" \
  -H "Authorization: Bearer $TOKEN"
{
  "items": [
    {
      "actorId": "user:550e8400-e29b-41d4-a716-446655440000",
      "createdAt": "2026-01-15T10:30:00Z",
      "updatedAt": "2026-01-15T10:30:00Z"
    }
  ],
  "limit": 25,
  "nextCursor": "",
  "hasMore": false
}
Query parameters: actorId (prefix filter), limit (default 25, capped at 100), and cursor.

Upsert an actor mapping

Creates or updates the PII for an actor ID. PUT is idempotent — the same call creates the record on first use and updates it thereafter. At least one of displayName or email must be supplied.
curl -X PUT "https://api.matcher.example.com/v1/governance/actor-mappings/{actorId}" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "displayName": "John Doe",
    "email": "john.doe@example.com"
  }'
{
  "actorId": "user:550e8400-e29b-41d4-a716-446655440000",
  "displayName": "John Doe",
  "email": "john.doe@example.com",
  "createdAt": "2026-01-15T10:30:00Z",
  "updatedAt": "2026-01-15T10:30:00Z"
}

Get one actor mapping (de-anonymize)

Returns the cleartext PII for a single actor ID. This is the de-anonymization primitive, so it is gated behind the narrower deanonymize permission rather than plain read.
curl -X GET "https://api.matcher.example.com/v1/governance/actor-mappings/{actorId}" \
  -H "Authorization: Bearer $TOKEN"

Pseudonymize (GDPR)

Replaces displayName and email with [REDACTED] while preserving the record and its actorId link — the audit trail stays intact but the PII is gone. Responds 204 No Content.
curl -X POST "https://api.matcher.example.com/v1/governance/actor-mappings/{actorId}/pseudonymize" \
  -H "Authorization: Bearer $TOKEN"

Delete (right to erasure)

Permanently removes the mapping for GDPR right-to-erasure. Responds 204 No Content.
curl -X DELETE "https://api.matcher.example.com/v1/governance/actor-mappings/{actorId}" \
  -H "Authorization: Bearer $TOKEN"
Pseudonymize keeps the record (PII scrubbed); delete removes it entirely. Choose pseudonymize when you must retain the audit linkage, delete when the record itself must not persist.

Archives


When audit-log partitions age out, they are compressed and moved to object storage. The archives endpoints list completed archives and issue time-limited download URLs.

List archives

Offset-paginated. Filter by date range.
curl -X GET "https://api.matcher.example.com/v1/governance/archives?from=2024-01-01&to=2024-03-31&limit=20&offset=0" \
  -H "Authorization: Bearer $TOKEN"
{
  "items": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "partitionName": "audit_logs_2024_q1",
      "dateRangeStart": "2024-01-01T00:00:00Z",
      "dateRangeEnd": "2024-03-31T23:59:59Z",
      "rowCount": 150000,
      "compressedSizeBytes": 10485760,
      "storageClass": "GLACIER",
      "checksum": "sha256:abc123def456...",
      "status": "COMPLETE",
      "archivedAt": "2024-04-01T02:30:00Z"
    }
  ],
  "limit": 20,
  "hasMore": true
}
Query parameters: from, to (YYYY-MM-DD or RFC 3339), limit (1–200, default 20), and offset. Only COMPLETE archives are listed — in-progress and failed archives are never surfaced.

Download an archive

Returns a presigned URL plus the checksum for integrity verification.
curl -X GET "https://api.matcher.example.com/v1/governance/archives/{id}/download" \
  -H "Authorization: Bearer $TOKEN"
{
  "downloadUrl": "https://s3.amazonaws.com/bucket/archive.gz?X-Amz-Signature=...",
  "expiresAt": "2026-02-05T13:00:00Z",
  "checksum": "sha256:abc123def456..."
}
Archives in GLACIER or DEEP_ARCHIVE storage classes require a restore before the download URL resolves. STANDARD, STANDARD_IA, ONEZONE_IA, INTELLIGENT_TIERING, and GLACIER_IR are immediately readable.

Audit logs


Every governance-relevant change is written to an immutable, per-tenant audit log. Each record is linked into a tamper-evident SHA-256 hash chain (recordHash = SHA-256(prevHash || canonical content)), so a client can independently re-verify integrity.

List audit logs

Cursor-paginated, with rich filters.
curl -X GET "https://api.matcher.example.com/v1/governance/audit-logs?actor=user@example.com&action=CREATE&entity_type=context&date_from=2025-01-01&date_to=2025-01-31&limit=20" \
  -H "Authorization: Bearer $TOKEN"
{
  "items": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "tenantId": "550e8400-e29b-41d4-a716-446655440001",
      "entityType": "reconciliation_context",
      "entityId": "550e8400-e29b-41d4-a716-446655440002",
      "action": "CREATE",
      "actorId": "user@example.com",
      "changes": { },
      "truncated": false,
      "originalSize": 0,
      "createdAt": "2025-01-15T10:30:00Z",
      "tenantSeq": 42,
      "recordHash": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
      "prevHash": "0000000000000000000000000000000000000000000000000000000000000000",
      "hashVersion": 1
    }
  ]
}
Query parameters: actor, action, entity_type, date_from, date_to (YYYY-MM-DD or RFC 3339), limit (1–200, default 20), and cursor. When a diff exceeds the outbox payload cap, changes carries a truncation-marker envelope instead of the full diff, and truncated becomes true with originalSize reporting the pre-truncation byte size.

Verify the audit chain

Re-verifies that every inspected record links to the previous one and matches its stored hash. This is strictly read-only — it proves tamper-evidence, never mutating a record.
curl -X GET "https://api.matcher.example.com/v1/governance/audit-logs/verify?maxRecords=10000" \
  -H "Authorization: Bearer $TOKEN"
{
  "intact": true,
  "verifiedCount": 1024,
  "firstBrokenSeq": 0,
  "truncated": false
}
intact is true when the whole inspected span is unbroken; if a break is found, firstBrokenSeq reports the tenantSeq of the first failing record and verifiedCount reports how many held before it. truncated is true when the chain holds more records than the maxRecords inspection bound allowed.

Get one audit log

curl -X GET "https://api.matcher.example.com/v1/governance/audit-logs/{id}" \
  -H "Authorization: Bearer $TOKEN"
You can also list an entity’s history directly with GET /v1/governance/entities/{entityType}/{entityId}/audit-logs (cursor-paginated), which is convenient when you already know the entity you are auditing.

Response codes


StatusMeaning
200Mapping, archive, or audit data returned
204Actor mapping pseudonymized or deleted
400Invalid input (missing displayName/email, bad date/pagination)
403Missing the required permission tier (e.g. deanonymize for single-record PII)
404Actor mapping, archive, or audit log not found
422Malformed field (e.g. invalid email format)