audit
GET /orgs/{org_id}/audit-events
List an organization's audit events
The organization's full audit feed (WP-A3): org-scoped events plus the events of every project in the org, newest first (occurred_at descending), cursor-paginated (003 §1). All filters are combinable; action is a prefix match (e.g. api_key matches api_key.create and api_key.revoke). Requires org role admin or above; another org's id is 404 not_found (003 §3 — no org enumeration). Console sessions only.
Operation ID: listOrgAuditEvents · Service: gateway-api
Authentication
consoleSession(http (bearer)) — Console session (003 §2): Identity Platform JWT. Data-plane calls addX-Tessera-Project+X-Tessera-Environmentheaders, validated against org membership.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
org_id | path | yes | string | Organization id (org_ ULID). |
action | query | no | string | Action prefix match (WP-A3): api_key matches api_key.create and api_key.revoke; auth.login matches auth.login and auth.login_denied. |
actor_id | query | no | string | Exact actor id (user_ / key_ ULID, or a service identity). |
cursor | query | no | string | Opaque pagination cursor from a previous response's next_cursor. |
limit | query | no | integer | Page size (cursor pagination, 003 §1). Maximum 200. |
occurred_after | query | no | string | Only events with occurred_at strictly after this instant. |
occurred_before | query | no | string | Only events with occurred_at strictly before this instant. |
outcome | query | no | string | Exact outcome. |
resource_id | query | no | string | Exact resource id. |
resource_type | query | no | string | Exact resource type (e.g. api_key, slot, schema_contract). |
Pagination
Cursor pagination (003 §1): pass limit (max 200) and cursor; the
response is the pagination envelope — data plus next_cursor
(null on the last page).
Responses
| Status | Schema | Description |
|---|---|---|
200 | AuditEventPage | Page of audit events, newest first. |
default | ErrorEnvelope | Error response (003 §1). Every non-2xx response uses this envelope; the HTTP status matches error.code. Rate-limited requests get 429 resource_exhausted with retry_after_seconds and a Retry-After header; the X-RateLimit-* headers ride on EVERY response, success or error (003 §1; plan-driven per API key + endpoint class — WP-B2). A 503 unavailable carries retry_after_seconds too for a lock-wait timeout (SQLSTATE 55P03), a rule preview at capacity (preview_capacity_exhausted), or a label preview during which the erasure of every entity holding its censor clock began (label_preview_clock_entity_erased): how long to wait before retrying. |
POST /orgs/{org_id}/audit-events:verify
Verify a range of the organization's audit hash chain
Recomputes the org's hash chain (WP-A8 reqs 4-5) over [from_seq, to_seq] (defaults: 1 and the current head), at most 1000 chain rows per call — continue from next_from_seq. Each record hash is recomputed from the stored audit event and each chain hash from its predecessor: a modified event, a deleted event or a chain-table discontinuity is tampered at exactly first_invalid_seq (tamper_kind names the class). Committed events the stream tailer has not sealed yet are counted in pending_count; a range reaching the head with pending events is pending, never verified. Events older than the 396-day retention floor whose month partition was dropped by retention are expired_count (chain continuity still verified); a missing younger event is always missing_event, since no retention drop removes one. Read-only. Requires org role admin or above; another org's id is 404 not_found. Console sessions only.
Operation ID: verifyOrgAuditEvents · Service: gateway-api
Authentication
consoleSession(http (bearer)) — Console session (003 §2): Identity Platform JWT. Data-plane calls addX-Tessera-Project+X-Tessera-Environmentheaders, validated against org membership.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
Idempotency-Key | header | no | string | Idempotency key accepted by all POSTs (003 §1): 24 h dedup window, keyed per project. POSTs that are reads (batchSlotScores, scoreSlotEvent, deriveSlotBands, validateSourceRawPreset, sampleSource, watchEventFeedHeads and the preview operations: previewSourceMapping, previewCatalogMapping, previewLabel, previewPatternLabel, previewMarker, previewDatasetEligibility, previewSlotAudience, previewSharedCheckpointImport, previewSlotAtlasInquiry) accept the key but never replay a stored response: a retry with the same key is executed again (and metered again) against current data. A stored response that names an entity is removed when that entity is erased. A key that already answered answers only a retry of the request that stored its response: the same caller, environment, operation, path, query, scoping headers and body (a JSON body by its content, a gzip body by its inflated content). The same key with any other request is 409 already_exists with details[0].reason idempotency_key_reused, and that request is not run. The window holds no in-flight marker: two first requests sent at once can both run. A response stored by a release before this rule cannot be matched to its request and is refused the same way until it expires; send the request again with a new key. A body over 8 MiB (ingest: over its 5 MiB request limit) is run and its response is not stored. The ingest batch (POST /events) is the exception, except for an application's credentials: under a key that answered another batch it runs again, uncached, and its events' ids deduplicate them; so it does when its stored response cannot be checked. The operations that return a one-time secret store their response sealed: the stored copy opens only for the same key and credential, and one that cannot be opened is 409 idempotency_key_reused. While the server cannot check a stored response (it cannot read the key that checks it, for one), the request is 503 unavailable with Retry-After: retry with the same key. An operation whose handler claims the key itself answers the same 503, before it runs, while the key-hash pepper cannot be read; any other request sent with a key runs meanwhile, and its response is not stored. |
org_id | path | yes | string | Organization id (org_ ULID). |
Idempotency
This operation accepts an Idempotency-Key header (003 §1): within
24 hours, keyed per project and caller, a retry of the same request
gets the first response, and the same key with another request is
409 already_exists (idempotency_key_reused). See the
Idempotency-Key parameter for the exceptions.
Request body
Responses
| Status | Schema | Description |
|---|---|---|
200 | AuditVerifyResult | The verification outcome for the checked range. |
default | ErrorEnvelope | Error response (003 §1). Every non-2xx response uses this envelope; the HTTP status matches error.code. Rate-limited requests get 429 resource_exhausted with retry_after_seconds and a Retry-After header; the X-RateLimit-* headers ride on EVERY response, success or error (003 §1; plan-driven per API key + endpoint class — WP-B2). A 503 unavailable carries retry_after_seconds too for a lock-wait timeout (SQLSTATE 55P03), a rule preview at capacity (preview_capacity_exhausted), or a label preview during which the erasure of every entity holding its censor clock began (label_preview_clock_entity_erased): how long to wait before retrying. |
GET /orgs/{org_id}/audit-settings
Get the organization's audit settings
The organization's effective audit v2 settings (WP-A8): the retention keep-minimum (audit_retention_days, floor and default 396), the org-level legal hold, and the stream configuration (audit.recorded webhooks and the GCS/S3 sink). Never-configured orgs read the defaults with updated_at: null. Sink credential material is write-only and never returned — only credential_configured. Requires org role admin or above; another org's id is 404 not_found (003 §3). Console sessions only.
Operation ID: getOrgAuditSettings · Service: gateway-api
Authentication
consoleSession(http (bearer)) — Console session (003 §2): Identity Platform JWT. Data-plane calls addX-Tessera-Project+X-Tessera-Environmentheaders, validated against org membership.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
org_id | path | yes | string | Organization id (org_ ULID). |
Responses
| Status | Schema | Description |
|---|---|---|
200 | OrgAuditSettings | The organization's audit settings. |
default | ErrorEnvelope | Error response (003 §1). Every non-2xx response uses this envelope; the HTTP status matches error.code. Rate-limited requests get 429 resource_exhausted with retry_after_seconds and a Retry-After header; the X-RateLimit-* headers ride on EVERY response, success or error (003 §1; plan-driven per API key + endpoint class — WP-B2). A 503 unavailable carries retry_after_seconds too for a lock-wait timeout (SQLSTATE 55P03), a rule preview at capacity (preview_capacity_exhausted), or a label preview during which the erasure of every entity holding its censor clock began (label_preview_clock_entity_erased): how long to wait before retrying. |
PUT /orgs/{org_id}/audit-settings
Configure retention, legal hold and audit streaming
Replaces the organization's audit v2 settings (WP-A8 reqs 7-10). Plan-gated through the org's pinned plan (WP-B2 catalog, deny by default): enabling webhook streaming or a sink requires the audit_stream plan limit, and audit_retention_days above 396 requires audit_retention_max_days at least that high — otherwise 400 failed_precondition with a plan_limit detail naming the plan and limit. Retention is raise-only: it is a keep-minimum for whole-partition drops, never an early purge. A value below the stored one is refused with 400 failed_precondition and a precondition_failure detail (reason audit_retention_cannot_be_lowered, current_minimum_days, requested_days), the stored value is changed only by a conditional update so concurrent writes cannot lower it, and an equal value is accepted even above a plan ceiling lowered since (so other settings and the legal hold can still change). Placing or releasing the legal hold writes audit.legal_hold.place / audit.legal_hold.release in the same transaction as the settings write (every accepted write also records audit_settings.update); an active hold blocks every partition drop covering this org's rows. S3 sinks take write-only credential_secret keys (envelope-encrypted at rest; omitted = keep the stored keys); GCS sinks write the platform exports bucket with workload identity. Enabling webhook streaming also delivers audit.recorded to endpoints subscribed to * in every project. Requires org role admin or above. Console sessions only.
Operation ID: putOrgAuditSettings · Service: gateway-api
Authentication
consoleSession(http (bearer)) — Console session (003 §2): Identity Platform JWT. Data-plane calls addX-Tessera-Project+X-Tessera-Environmentheaders, validated against org membership.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
org_id | path | yes | string | Organization id (org_ ULID). |
Request body
Responses
| Status | Schema | Description |
|---|---|---|
200 | OrgAuditSettings | The stored settings (credential material omitted). |
default | ErrorEnvelope | Error response (003 §1). Every non-2xx response uses this envelope; the HTTP status matches error.code. Rate-limited requests get 429 resource_exhausted with retry_after_seconds and a Retry-After header; the X-RateLimit-* headers ride on EVERY response, success or error (003 §1; plan-driven per API key + endpoint class — WP-B2). A 503 unavailable carries retry_after_seconds too for a lock-wait timeout (SQLSTATE 55P03), a rule preview at capacity (preview_capacity_exhausted), or a label preview during which the erasure of every entity holding its censor clock began (label_preview_clock_entity_erased): how long to wait before retrying. |
GET /projects/{project_id}/audit-events
List a project's audit events
The project's audit feed (WP-A3), newest first (occurred_at descending), cursor-paginated (003 §1). All filters are combinable; action is a prefix match. Sessions require org role member or above; API keys need the admin scope and can read only their own project (another project's id is 404 not_found, 003 §3). An API key, or an application scoped by its headers, holds exactly one environment (003 §2): it reads that environment's events and the project-level events recorded with no environment, never the other environment's. Sessions read both environments' events.
Operation ID: listProjectAuditEvents · Service: gateway-api
Authentication
apiKey(http (bearer)) — Project API key (003 §2):tsk_live_…ortsk_test_…inAuthorization: Bearer. Scoped to exactly one project + environment; scopes are a subset ofingest,read,admin. Keys are stored hashed and shown once at creation.consoleSession(http (bearer)) — Console session (003 §2): Identity Platform JWT. Data-plane calls addX-Tessera-Project+X-Tessera-Environmentheaders, validated against org membership.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
project_id | path | yes | string | Project id (proj_ ULID). |
action | query | no | string | Action prefix match (WP-A3): api_key matches api_key.create and api_key.revoke; auth.login matches auth.login and auth.login_denied. |
actor_id | query | no | string | Exact actor id (user_ / key_ ULID, or a service identity). |
cursor | query | no | string | Opaque pagination cursor from a previous response's next_cursor. |
limit | query | no | integer | Page size (cursor pagination, 003 §1). Maximum 200. |
occurred_after | query | no | string | Only events with occurred_at strictly after this instant. |
occurred_before | query | no | string | Only events with occurred_at strictly before this instant. |
outcome | query | no | string | Exact outcome. |
resource_id | query | no | string | Exact resource id. |
resource_type | query | no | string | Exact resource type (e.g. api_key, slot, schema_contract). |
Pagination
Cursor pagination (003 §1): pass limit (max 200) and cursor; the
response is the pagination envelope — data plus next_cursor
(null on the last page).
Responses
| Status | Schema | Description |
|---|---|---|
200 | AuditEventPage | Page of audit events, newest first. |
default | ErrorEnvelope | Error response (003 §1). Every non-2xx response uses this envelope; the HTTP status matches error.code. Rate-limited requests get 429 resource_exhausted with retry_after_seconds and a Retry-After header; the X-RateLimit-* headers ride on EVERY response, success or error (003 §1; plan-driven per API key + endpoint class — WP-B2). A 503 unavailable carries retry_after_seconds too for a lock-wait timeout (SQLSTATE 55P03), a rule preview at capacity (preview_capacity_exhausted), or a label preview during which the erasure of every entity holding its censor clock began (label_preview_clock_entity_erased): how long to wait before retrying. |
GET /projects/{project_id}/audit-settings
Get the project's read-audit settings
The project's opt-in data-plane read audit (WP-A8 req 9): read_audit_enabled and the uniform sample_rate. Never-configured projects read the defaults (disabled, rate 0) with updated_at: null. Requires org role admin or above; another tenant's project is 404 not_found. Console sessions only.
Operation ID: getProjectAuditSettings · Service: gateway-api
Authentication
consoleSession(http (bearer)) — Console session (003 §2): Identity Platform JWT. Data-plane calls addX-Tessera-Project+X-Tessera-Environmentheaders, validated against org membership.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
project_id | path | yes | string | Project id (proj_ ULID). |
Responses
| Status | Schema | Description |
|---|---|---|
200 | ProjectAuditSettings | The project's read-audit settings. |
default | ErrorEnvelope | Error response (003 §1). Every non-2xx response uses this envelope; the HTTP status matches error.code. Rate-limited requests get 429 resource_exhausted with retry_after_seconds and a Retry-After header; the X-RateLimit-* headers ride on EVERY response, success or error (003 §1; plan-driven per API key + endpoint class — WP-B2). A 503 unavailable carries retry_after_seconds too for a lock-wait timeout (SQLSTATE 55P03), a rule preview at capacity (preview_capacity_exhausted), or a label preview during which the erasure of every entity holding its censor clock began (label_preview_clock_entity_erased): how long to wait before retrying. |
PUT /projects/{project_id}/audit-settings
Configure the project's read audit
Replaces the project's read-audit settings (WP-A8 reqs 9-10). Enabling requires the org plan's audit_read_audit limit (deny by default) — otherwise 400 failed_precondition with a plan_limit detail. Enabled projects record sampled state.read audit events for slot-bound entity-state reads (each read is drawn on a server-minted sampling_id, never on the caller's X-Request-Id; see sample_rate); disabled projects are byte-identical to no read audit, and state_reads metering (002 §11) is unchanged either way. Serving applies changes within 60 seconds (cached settings). The write records audit_settings.update. Requires org role admin or above. Console sessions only.
Operation ID: putProjectAuditSettings · Service: gateway-api
Authentication
consoleSession(http (bearer)) — Console session (003 §2): Identity Platform JWT. Data-plane calls addX-Tessera-Project+X-Tessera-Environmentheaders, validated against org membership.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
project_id | path | yes | string | Project id (proj_ ULID). |
Request body
Responses
| Status | Schema | Description |
|---|---|---|
200 | ProjectAuditSettings | The stored read-audit settings. |
default | ErrorEnvelope | Error response (003 §1). Every non-2xx response uses this envelope; the HTTP status matches error.code. Rate-limited requests get 429 resource_exhausted with retry_after_seconds and a Retry-After header; the X-RateLimit-* headers ride on EVERY response, success or error (003 §1; plan-driven per API key + endpoint class — WP-B2). A 503 unavailable carries retry_after_seconds too for a lock-wait timeout (SQLSTATE 55P03), a rule preview at capacity (preview_capacity_exhausted), or a label preview during which the erasure of every entity holding its censor clock began (label_preview_clock_entity_erased): how long to wait before retrying. |
Errors
Every non-2xx response uses the 003 §1 error envelope; error.request_id
matches the X-Request-Id response header, and the HTTP status always
matches error.code:
{
"error": {
"code": "invalid_argument",
"details": [
{
"type": "field_violation"
}
],
"message": "human-readable",
"request_id": "req_01hxample"
}
}
Closed error-code set (003 §1): invalid_argument, unauthenticated, permission_denied, not_found, already_exists, failed_precondition, resource_exhausted, internal, unavailable.
resource_exhausted responses (HTTP 429) additionally carry
retry_after_seconds. See ErrorEnvelope.