Skip to main content

An API governance framework you can enforce at runtime, not just in a wiki

An API governance framework where every policy maps to an enforced gateway control and evidence, with a YAML mapping, audit log example and maturity checklist.

  • governance
  • api-management
  • compliance
  • platform-engineering
Zerq team

Ask a platform team for its API governance framework and you usually get a link: a wiki page of design rules, a spec linter wired into CI, maybe a catalog spreadsheet. Then ask the compliance officer's question. Which consumers could call the payments API with POST on the first of March, who changed that, and where is the proof? The wiki cannot answer, because it describes how APIs should be designed, not what the gateway actually allowed.

That gap is a common source of audit findings. The spec said read-only and the linter passed, but a client was later granted a write method in production, and nothing in the governance program noticed because nothing in it ran at runtime.

The alternative: every governance policy names the control that enforces it and the evidence that control leaves behind. Below are eight pillars mapped to Zerq controls, the control points on the request and change paths, and a maturity checklist.

Why design-time API governance stops short

Design-time governance is necessary. A style guide and a spec linter keep naming, error shapes and security schemes consistent, and catch problems when they are cheapest to fix. Most API governance best practices stop there: they govern the OpenAPI document and assume the runtime matches.

The tooling market reflects the same split. Apigee and MuleSoft both offer design-time governance tooling that checks specs against rulesets, separate from the policies attached to runtime proxies. Kong enforcement depends on which plugins are attached to each service or route. AWS API Gateway and Azure API Management rely on their clouds' wider services for evidence, so control-plane activity and request logs land in separate logging products. None of these designs is wrong, but each leaves the governance team stitching policy, configuration and evidence together from several places, which is where audits stall.

Runtime API governance treats the gateway configuration as the thing being governed. "Partners get read-only access" is not satisfied by a spec annotation. It is satisfied by a method restriction on the partner's profile, and proven by a 405 in the request log when someone tries POST. Zerq does not ship a spec style linter and nothing here replaces one. Keep linting specs in CI; this framework covers what happens after import.

An API governance framework built on policy, control and evidence

Each governance policy has three parts: the statement, the control that enforces it (named as it appears in the product), and the evidence that control produces. If a policy cannot name a control, it is a guideline; label it so nobody presents it to an auditor as enforced.

Here is the mapping, one policy per pillar. It is illustrative, for your own repository; it is not a Zerq configuration format. Control names match Zerq's fields, roles, statuses and nodes.

# Illustrative governance mapping. NOT a Zerq file format.
policies:
  - pillar: inventory-and-ownership
    policy: "Every reachable API is registered with an owning team."
    control: ["Collection: Name, Description, unique Base Path"]
    evidence: ["Collection JSON Export in version control",
               "Audit log CREATE event (Actor ID)"]
  - pillar: lifecycle
    policy: "Nothing is reachable until deliberately published."
    control: ["Draft / Published on the collection and on each proxy"]
    evidence: ["Audit log entry for PUT /api/v1/collections/:id/status",
               "Audit log entry for PUT /api/v1/proxies/:id"]
  - pillar: access
    policy: "Consumers reach only approved APIs, methods and networks."
    control: ["Client: Collections", "Profile: Auth Type, Allowed Methods, IP Restrictions"]
    evidence: ["Request logs by Client ID and Profile ID",
               "Deny probes returning 401, 403, 405"]
  - pillar: contract-conformance
    policy: "Write endpoints reject non-conforming bodies before the backend."
    control: ["Proxy Parameters (Required, Type) on path and query",
              "validate_node on the request body in the proxy workflow"]
    evidence: ["Request log entries with status 400",
               "Workflow invalid-branch responses in request logs"]
  - pillar: change-control
    policy: "Reviewers cannot make changes; every change is attributable."
    control: ["OIDC roles: viewer, modifier, auditor, admin"]
    evidence: ["Audit log: Actor ID, Action, Resource type, Request body"]
  - pillar: runtime-limits
    policy: "Every external consumer has a rate limit and a quota."
    control: ["Policy (Rate limit + Quota) attached to the Client"]
    evidence: ["Audit log entries for the Policy and its client assignment",
               "Recorded over-limit probe returning 429",
               "Quota usage on the Client detail page"]
  - pillar: observability-and-evidence
    policy: "Evidence is kept for the regulated period."
    control: ["Retention on the MongoDB deployment you operate",
              "SIEM retention for exported audit logs"]
    evidence: ["Database retention or archival configuration",
               "SIEM retention policy", "Audit log API export to SIEM"]
  - pillar: non-human-consumers
    policy: "AI agents use the same identities, limits and logs as apps."
    control: ["Gateway MCP: X-Client-ID, X-Profile-ID, Bearer token",
              "Management MCP: OIDC token, console RBAC"]
    evidence: ["Request log entries for execute_endpoint calls"]

What each pillar enforces in Zerq

Inventory and ownership

The unit of inventory is the collection, with a Name, Description, unique Base Path and Target Endpoint, and proxies beneath it. Import from OpenAPI turns a linted spec into draft proxies; JSON Export returns the inventory as a file. Zerq has no owner field, so name the owning team in the Description and treat the audit log CREATE event as provenance (more on inventory).

Lifecycle

API lifecycle governance rests on two statuses, Draft and Published, set on collections and on each proxy independently; publishing a collection does not publish its proxies. OpenAPI imports and duplicates land in draft; a JSON collection import keeps the exported status. A new version is a separate collection: duplicate v1, give the copy its own base path, publish when ready. There is no built-in version history or one-click rollback, so commit a JSON export at every publish.

Access

Clients carry the collection assignment and an active or inactive status. Profiles carry the Auth Type (token, jwt, oidc, mtls or none), Allowed Methods and IP Restrictions. The security model gives each denial its own status: 401 for authentication, 403 for IP, 404 for a path outside the client's collections, 405 for methods. For mtls profiles, certificates are validated at your ingress, so govern that configuration too.

Contract conformance

Proxy Parameters declare Type, Required and Enum, and on proxies without a workflow the gateway rejects path or query values that are missing or of the wrong type with 400. A workflow-enabled proxy hands the request straight to its workflow, so validate path and query values there too. The request schema (JSON Schema draft-07) documents the body for the portal and the OpenAPI export. To stop a non-conforming body before the backend, put a validate_node at the start of the proxy's workflow, check {{ $json['http_trigger'].request.body }} against the schema, and send the invalid branch to a response_node that returns 400. Response schemas are documentation only, so response conformance needs another control, usually backend contract tests. The same validate_node can check values other than the raw body and branches to valid or invalid (example).

Change control

Management access runs through OIDC. Roles come from the claim at OIDC_ROLE_CLAIM_PATH and map into four tiers via OIDC_VIEWER_ROLES, OIDC_MODIFIER_ROLES, OIDC_AUDITOR_ROLES and OIDC_ADMIN_ROLES, checked by the backend on every management request. Separation of duties comes from the auditor role, which sees Audit Logs and nothing else. Auditors cannot change configuration. The shipped default also grants auditor to admin, so remove admin from OIDC_AUDITOR_ROLES before relying on this. Only admins can delete log entries, including request logs, and each deletion is itself recorded in the audit log, so reconcile admin membership as part of the evidence review. Zerq has no maker-checker step: any modifier can publish a draft. Two-person approval stays a process control, checked afterwards against the audit log. For agents that make these changes through Management MCP, see AI agent change control.

Runtime limits

A Policy combines a Rate limit (windows of 1m, 5m or 1h) with a Quota (1d, 7d or 30d) and attaches to the client, so its active profiles share one bucket. Exceeding either returns 429; the rate limit's body carries rate_limit_exceeded, and the quota's body carries a separate quota error code. Over-limit rejections are returned before the request logger runs, so they do not appear in request logs; keep the 429 output from your probe scripts as evidence. Toggling a policy inactive stops enforcement, and that toggle is itself an audited change.

Observability and evidence

Request logs record Request ID (also returned as X-Request-ID), Method, Path, Status code, Latency, Client ID, Profile ID, Collection and Client IP. The observability dashboard rolls the same data into Total Requests, Success Rate, Avg Response Time and Error Count. Zerq has no retention setting of its own: request logs and audit logs stay in the MongoDB you operate until you remove them, so enforce the regulated period there and in the SIEM that pulls the audit log API. One caveat: request logs are written asynchronously, so an abrupt process termination can drop a few in-flight writes.

Non-human consumers

AI agents should not get a side door. Gateway MCP gives agents the same client, profile, limits and request log as REST callers. Management MCP requires an OIDC bearer token and enforces console RBAC, and Zerq Copilot for Management acts as the signed-in user. Give each agent its own client, profile and IdP identity, and every pillar applies unchanged. AI gateway, LLM gateway or agent API gateway explains how Gateway MCP works and which direction of agent traffic these controls cover.

How to enforce API governance at runtime: the control points

A policy is enforceable only when it lands on a control point in the path.

The request path

Caller (app, partner or AI agent)
  -> Ingress TLS (validates client certificates for mtls)
  -> Client Policy: rate limit, quota (keyed on X-Client-ID)  429
  -> X-Client-ID / X-Profile-ID format                  401
  -> Client and profile exist and are active            401
  -> Credential check for the Auth Type                 401
  -> Profile IP Restrictions                            403
  -> Profile Allowed Methods                            405
  -> Published collection and published proxy           404
  -> Collection assigned to the client                  404
  -> Workflow, if enabled (validate_node valid | invalid)
  -> Otherwise: path and query parameters (Required, Type)  400
  -> Upstream Target Endpoint
  -> Request log (Request ID, Client ID, Profile ID, status)

The order is fixed in code: policy limiter, credential, IP, methods, then collection. The limiter is keyed on the X-Client-ID header before the credential is checked, and auth and policy decisions precede any workflow node. What matters is that each control runs before the upstream and returns a status code you can probe. The architecture overview shows how the surfaces fit together.

The change path

Operator, CI job, Zerq Copilot or Management MCP client
  |  OIDC bearer token with role claim
  v
Management API role check                              401 / 403
  v
Write lands in draft (OpenAPI import, duplicate)
  |--> Audit log: Actor ID, Action, Resource type, Request body
  |--> Live update on /api/v1/events/stream (actor_sub)
  v
Publish: PUT /api/v1/collections/:id/status
  |--> Audit log: status change on collection
  v
Auditor reviews Audit Logs; audit log API feeds the SIEM

What a governed change leaves behind

This is the audit log entry for a modifier publishing a collection through the management API. Values are illustrative; the fields are the ones Zerq records.

Timestamp        2026-10-08T14:32:07Z
Actor ID         [email protected]   (email claim of the signed-in user)
Actor type       modifier            (roles from the token)
Action           toggle_status
Resource type    collection
URL              /api/v1/collections/6650f1c2a9e4b3d2c1f0a987/status
IP address       10.20.4.17
User agent       Mozilla/5.0 (...)
Request ID       b3e0c6f1-52d4-4a8e-8f0b-6c9a1d27e4f3
Request body     {"active":true}
Response status  200
Response body    {...}

The entry names the actor, the resource, the exact management call and the submitted body. It does not hold an approver, a justification or a before-and-after diff. For any change, infer the previous state from the prior event on the same URL, or from the JSON export committed at the last publish. Correlate change tickets on Actor ID and Timestamp.

An API governance maturity checklist

Level 1: written

  • Each governance policy has an ID, a pillar and an owner.
  • Specs pass your linter before Import from OpenAPI.
  • Every collection Description names its owning team.

Level 2: enforced

  • Every policy names a Zerq control: a field, role, status or node.
  • Every external client has a Policy, or a documented exception.
  • Every profile sets Allowed Methods, plus IP Restrictions for static egress.
  • Write-capable proxies validate the body with a validate_node.
  • Modifier, auditor and admin map to separate IdP groups; nobody holds both modifier and auditor.
  • Each AI agent has its own client and profile, plus its own OIDC identity if it uses Management MCP.

Level 3: evidenced

  • Each access policy has one allow probe and one deny probe on record, with Request IDs.
  • Audit logs flow to the SIEM on a schedule through the audit log API.
  • Request log and audit log retention in your database and SIEM match the regulated period.
  • A JSON export is committed at every publish as the rollback reference.
  • Audit log Actor IDs are reconciled against IdP role membership quarterly.

Pair it with what regulators ask when auditing an API platform.

What this looks like in practice

Illustrative scenario, not a specific customer deployment.

A consumer lending platform had a governance program that looked mature: a long design guide, a spec linter blocking merges, quarterly API reviews. A partner audit asked them to prove a credit-bureau partner had been read-only on the account data API for a year. The spec said GET only, but the gateway configuration had been hand-edited twice by people nobody could name, and request logs lived apart from the change history. The answer took weeks.

After moving those APIs into Zerq, the team rewrote the governance document in the policy, control and evidence shape. The partner's profile carries Allowed Methods set to GET. The quarterly evidence pack is now three queries: audit log entries filtered to Resource type client and profile, request logs filtered on the partner's Client ID, and a recorded deny probe where a POST returns 405. Compliance staff hold the auditor role for the audit log and the viewer role for request logs; neither lets them change configuration, and they run the queries themselves. The linter still runs in CI; it just no longer carries claims it cannot prove.

The short version

An API governance framework earns the name when each policy points at something the platform enforces and something it records. Keep the linter for design-time quality and put the rest on the gateway: collections and Draft / Published for inventory and lifecycle, clients, profiles and policies for access and limits, validate_node for contracts, OIDC roles and the audit log for change control, request logs for proof, and the same controls for AI agents, so the compliance officer's question becomes an audit log and request log query.


Zerq is an enterprise API gateway built for regulated industries — one platform for API management, AI agent access, compliance audit, and developer portal, running entirely in your own infrastructure. See how it works or request a demo to walk through your specific requirements.