Skip to main content
Browse docs
By Audience
Getting Started
Configuration
Use Cases
IDE Integration
Third-Party Integrations
Engineering Cache
Console
API Reference
Gateway
Workflow Guides
Templates
Providers and SDKs
Industry Guides
Advanced Guides
Browse by Role
Deployment Guides
In-Depth Guides
Tutorials
FAQ

API Design with AI Governance Built In

Building APIs that incorporate AI governance from the design phase prevents costly retrofits. This guide covers contract-first development patterns, API versioning strategies that align with policy versioning, and techniques for maintaining backward compatibility as governance requirements evolve.

Use this page when

  • You are designing a new REST API that will make LLM calls through the Keeptrusts gateway
  • You need to version API contracts alongside policy configuration versions
  • You want to standardize how consumers handle 409 policy violation responses
  • You are adding governance metadata (x-keeptrusts-policy) to an OpenAPI specification

Primary audience

  • Primary: Technical Engineers
  • Secondary: AI Agents, Technical Leaders

Contract-First API Design

Define your OpenAPI specification before implementation. The gateway enforces policies against the same contract your consumers rely on:

# openapi.yaml — AI-powered endpoint with governance metadata
openapi: 3.1.0
info:
title: Document Analysis API
version: 2.1.0
paths:
/v1/documents/analyze:
post:
summary: Analyze document with AI
x-keeptrusts-policy: document-analysis
x-keeptrusts-cost-tier: high
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AnalyzeRequest'
responses:
'200':
description: Analysis complete
content:
application/json:
schema:
$ref: '#/components/schemas/AnalyzeResponse'
'409':
description: Policy violation — blocked by governance rules
content:
application/json:
schema:
$ref: '#/components/schemas/PolicyViolation'

The 409 response is a first-class part of your API contract. Document it so consumers handle governance blocks gracefully.

Routing Through the Gateway

Your API service forwards LLM calls through the gateway rather than calling providers directly:

# app/services/ai_client.py
import httpx

GATEWAY_URL = "http://localhost:41002" # kt gateway sidecar

async def analyze_document(content: str, user_id: str) -> dict:
"""Route AI calls through the governance gateway."""
async with httpx.AsyncClient(timeout=30.0) as client:
response = await client.post(
f"{GATEWAY_URL}/v1/chat/completions",
json={
"model": "gpt-4o",
"messages": [
{"role": "system", "content": "Analyze the following document."},
{"role": "user", "content": content}
]
},
headers={
"Authorization": f"Bearer {GATEWAY_API_KEY}",
"X-User-Id": user_id,
"X-Request-Source": "document-analysis-api"
}
)
if response.status_code == 409:
raise PolicyViolationError(response.json())
response.raise_for_status()
return response.json()

Policy-Aware API Versioning

API versions and policy versions evolve independently but must remain compatible. Use a version matrix to track alignment:

API VersionPolicy Config VersionGateway ConfigBreaking Changes
v1.01.0.0policy-v1.yamlInitial release
v1.11.1.0policy-v1.yamlNew fields, same policies
v2.02.0.0policy-v2.yamlNew content categories

Versioned Policy Configurations

Bind policy versions to API versions in your gateway config:

# policy-config.yaml
gateway:
port: 41002
secret_key_ref:
env: OPENAI_API_KEY

policies:
- name: document-analysis-v2
version: "2.0.0"
input:
- type: content_safety
action: block
categories: [hate, violence, self_harm, sexual]
- type: pii_detection
action: redact
entities: [ssn, credit_card, phone_number]
output:
- type: disclaimer
text: "AI-generated analysis. Verify before acting."

- name: document-analysis-v1
version: "1.0.0"
input:
- type: content_safety
action: block
categories: [hate, violence]

Backward Compatibility Patterns

When adding governance requirements to existing API versions:

# Additive policy change — backward compatible
policies:
- name: summarization
input:
- type: content_safety
action: block
categories: [hate, violence]
# New: PII redaction added without breaking existing consumers
- type: pii_detection
action: redact
entities: [email, phone_number]

Breaking policy changes (changing action: redact to action: block) require a new API version. Consumers expecting redacted output will break if they receive a 409 block instead.

Validating Contracts in CI

Use kt policy lint to catch policy misconfigurations before deployment:

#!/bin/bash
# scripts/validate-governance.sh
set -euo pipefail

echo "Validating policy configurations..."
kt policy lint --file policy-config.yaml

echo "Checking OpenAPI spec against policy references..."
for policy in $(yq '.policies[].name' policy-config.yaml); do
if ! grep -q "x-keeptrusts-policy: ${policy}" openapi.yaml; then
echo "WARNING: Policy '${policy}' not referenced in OpenAPI spec"
fi
done

echo "Governance validation passed."

Error Envelope Design

Standardize governance error responses across your API:

{
"error": {
"code": "POLICY_VIOLATION",
"message": "Request blocked by content safety policy",
"details": {
"policy": "document-analysis-v2",
"rule": "content_safety",
"action": "block",
"categories_triggered": ["violence"]
},
"request_id": "req_abc123",
"event_id": "evt_def456"
}
}

The event_id links back to the decision event in the Keeptrusts console, enabling consumers to reference specific governance decisions in support requests.

Rate Limiting and Cost Controls

Layer API rate limits with gateway spend controls:

# policy-config.yaml — cost governance
policies:
- name: public-api-tier
input:
- type: spend_limit
max_tokens_per_request: 4096
max_requests_per_minute: 60
- type: model_allowlist
models: [gpt-4o-mini, gpt-3.5-turbo]

Your API enforces application-level rate limits while the gateway enforces token and cost budgets independently. Both layers log events for audit.

API Documentation Generation

Include governance behavior in generated API docs:

# openapi.yaml — document governance responses
components:
schemas:
PolicyViolation:
type: object
required: [error]
properties:
error:
type: object
properties:
code:
type: string
enum: [POLICY_VIOLATION, SPEND_LIMIT_EXCEEDED, MODEL_NOT_ALLOWED]
message:
type: string
details:
type: object
properties:
policy:
type: string
event_id:
type: string
description: Reference ID for the decision event in Keeptrusts console

Key Takeaways

  • Define 409 policy violation responses as first-class API contract elements
  • Version policies alongside API versions using a compatibility matrix
  • Additive policy changes (new redaction rules) are backward compatible; action changes (redact → block) are breaking
  • Use kt policy lint in CI to catch misconfigurations before deployment
  • Include event_id in error responses so consumers can reference specific governance decisions

For AI systems

For engineers

  • Prerequisites: A running kt gateway instance (port 41002), an OpenAPI spec for your service, and a policy-config.yaml
  • Validate with: kt policy lint --file policy-config.yaml and check for the 409 response schema in your OpenAPI spec
  • Key pattern: Route all LLM calls through http://localhost:41002/v1/chat/completions with X-User-Id and X-Request-Source headers
  • Breaking change rule: Changing a policy from action: redact to action: block is breaking — requires a new API version

For leaders

  • Contract-first governance means policy violations are documented as first-class API responses — not surprises
  • Policy versioning aligned with API versioning reduces cross-team coordination overhead during rollouts
  • The event_id in error responses enables consumers to reference specific governance decisions in support tickets, reducing escalation resolution time

Next steps