Skip to content
INFRO

Documentation

Audit log

Every administrative change in your INFRO organization, recorded: the event catalog, GET /v1/org/audit filters, 12-month retention, and CSV export.


Every administrative action in your organization — an invite sent, a role changed, a key revoked, a spend limit edited — is recorded as an audit event. The log is append-only: events cannot be edited or deleted through any API or console surface, so it answers "who changed what, and when" with evidence rather than recollection.

The log covers administration, not traffic. It is readable by owners and admins only, retained for 12 months, queryable with GET /v1/org/audit, and exportable to CSV via the exports API.

What gets recorded

Nine event types. Each fires regardless of where the action originated — console, API, or SCIM provisioning — so the log has no blind spots between surfaces.

EventWhat fires it
member.invitedAn invite is sent from the console or via POST /v1/org/invites. The event fires when the invite is sent, not when it is accepted — acceptance sets the member's joined_at field, covered in Members & roles.
member.removedA member is removed via DELETE /v1/org/members/{id}, the console, or SCIM deprovisioning.
member.role_changedA role changes via PATCH /v1/org/members/{id}, the console, or IdP group mapping through SSO & SCIM.
key.createdAn API key is created in the console — see Authentication.
key.rotatedA key is rotated in the console: the secret is replaced in one step and the old secret stops working. A manual create-then-revoke rotation fires key.created and key.revoked instead.
key.revokedA key is revoked in the console.
policy.updatedA spend limit, model allowlist, or EU routing-zone pin changes at any scope — org, project, member, or key.
project.createdA project is created in the console.
export.createdAn export job is started via POST /v1/exports or the console — see Exports.

API traffic is not audited here — inference requests are recorded per request in the request log and aggregated in analytics. The audit log is only for actions that change your organization.

Event shape

Every event has the same six fields. detail is the only event-specific part.

Audit event
{
  "id": "audit_9f4kq2vx",
  "event": "member.role_changed",
  "actor": {
    "type": "member",
    "id": "mem_c81af3",
    "email": "dana@acme.dev"
  },
  "target": {
    "type": "member",
    "id": "mem_7bq2e9",
    "label": "sam@acme.dev"
  },
  "timestamp": "2026-08-21T14:03:22Z",
  "detail": {
    "from": "developer",
    "to": "admin"
  }
}
idstring
Unique event id, stable across reads. Deduplicate on it if you poll the log into your own SIEM.
eventstring
One of the nine names in the catalog above. New event types may be added over time — skip unknown names rather than erroring on them.
actorobject
Who performed the action. type is member (with the member's id and email) or scim for changes driven by your identity provider, where email is null — see SSO & SCIM.
targetobject
What was acted on: type (member, key, project, org, or export), its id, and a human-readable label — the member's email, the key's label, the project's name.
timestampstring
When the action happened. ISO 8601, always UTC.
detailobject | null
Event-specific fields: member.invited carries email and role; member.role_changed carries from and to; policy.updated carries the policy name, scope, and new value. null when there is nothing to add.

Key events reference keys by id and label only — the secret itself never appears in the log, in detail, or in exports.

Querying the log

GET /v1/org/audit returns events newest first, cursor-paginated. All filters combine with AND.

eventstring
Filter to one event name from the catalog, e.g. key.revoked. Omit for all events.
actorstring
A member id (mem_...) to return only that member's actions, or the literal scim for provisioning-driven events.
fromstring
Inclusive lower bound on timestamp, ISO 8601 UTC. Defaults to the start of the 12-month retention window.
tostring
Exclusive upper bound on timestamp, ISO 8601 UTC. Defaults to now.
cursorstring
The next_cursor from the previous page. Keep the other filters identical between pages.
limitinteger
Events per page. Default 25, maximum 100.
curl "https://api.infro.io/v1/org/audit?event=key.revoked&from=2026-08-01T00:00:00Z&limit=50" \
  -H "Authorization: Bearer $INFRO_API_KEY"
Response (one event shown)
{
  "data": [
    {
      "id": "audit_8xw3n1pd",
      "event": "key.revoked",
      "actor": { "type": "member", "id": "mem_c81af3", "email": "dana@acme.dev" },
      "target": { "type": "key", "id": "key_hj2m8s", "label": "staging-worker" },
      "timestamp": "2026-08-21T13:58:47Z",
      "detail": null
    }
  ],
  "has_more": true,
  "next_cursor": "YXVkaXRfOHh3M24xcGQ="
}

has_more is false and next_cursor null on the last page. Cursors are opaque — don't parse them, and don't reuse one after changing filters.

Who can read it

Only owners and admins can read the audit log — in the console and via GET /v1/org/audit. A key belonging to a developer or analyst gets 403 with type permission_denied in the standard error envelope. Analysts can see dashboards, usage, and most exports, but not the audit log or audit exports — the log records who holds power in the org, which is itself sensitive. Roles are covered in Members & roles.

Retention and export

Events are retained for 12 months on a rolling basis; older events are permanently deleted. If your compliance program needs a longer horizon, export on a schedule — a quarterly export of the previous quarter is the usual cadence.

Export the audit log to CSV
curl https://api.infro.io/v1/exports \
  -H "Authorization: Bearer $INFRO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "kind": "audit",
    "from": "2026-01-01T00:00:00Z",
    "to": "2026-07-01T00:00:00Z"
  }'

This returns an async job in the same envelope as every async job; when it completes, the job yields a signed, expiring CSV URL. Creating a kind: "audit" export requires the owner or admin role, and the export itself fires an export.created event — the log records its own extraction. The full job lifecycle and CSV columns are on the Exports page.

Why it matters for compliance

Access reviews and audits keep asking the same questions: who could create keys, who changed that spend policy, when did the contractor's access end. The audit log answers them from records rather than memory:

  • SOC 2 / ISO 27001 evidence. Auditors ask for proof of access provisioning, deprovisioning, and change management. member.*, key.*, and policy.updated events, exported to CSV, are that proof — INFRO's own certifications are listed on /security.
  • Incident response. A leaked key's story is reconstructable: key.created shows who minted it and when, key.revoked shows how fast you responded.
  • EU AI Act and GDPR reviews. Regulators expect you to show governance over the systems that process data — who could change routing zones, retention behavior, and model access. policy.updated events document exactly that, alongside the request-level records described in EU compliance.
  • SCIM verification. Events with actor scim let you confirm the IdP is actually deprovisioning people — every offboarding should have a matching member.removed. See SSO & SCIM.

For live monitoring rather than retrospective review — spend spikes, error rates, latency — use alerts and analytics; the audit log is the record of how the organization itself changed.