Agent Governance Foundation

API Reference

REST API Reference

All endpoints are served from https://api.agentgovernancefoundation.com. Every request requires a Bearer token.

Authentication

Pass your API key as a Bearer token on every request. Keys are scoped to an organisation — you cannot access another org’s data with your key. The Growth and Enterprise tiers unlock additional endpoints — tier requirements are shown on each endpoint below.

Authorization: Bearer agf_live_sk_xxxxxxxxxxxxxxxxxxxxxxxx

Core

POST/v1/decideall tiers

Evaluate an authorization request

The primary endpoint. Sends an agent action to the PDP and receives an ALLOW / DENY / REVIEW_REQUIRED decision with trust score, risk score, and a signed audit artifact ID. The chain field is a list of JWT delegation tokens — use a single-element array for a direct agent call.

Request body
{
  "chain": ["eyJhbGci..."],          // required — JWT delegation chain
  "action_type":     "file:write",   // required — action being attempted
  "action_resource": "s3://corp-data/q2.csv",  // optional — target resource URI
  "context": {                       // optional — arbitrary key-value pairs
    "session_id": "sess_xyz",
    "ip": "10.0.1.5"
  }
}
Response
{
  "decision":    "ALLOW",            // "ALLOW" | "DENY" | "REVIEW_REQUIRED"
  "trust_score":  91,                // 0 – 100
  "risk_score":   12.4,             // 0.0 – 100.0 (higher = riskier)
  "reasoning":   ["scope matched", "trust above threshold"],
  "artifact_id": "dec_1750000000_a1b2c3",
  "approval_request_id": null        // set when decision is REVIEW_REQUIRED
}
POST/v1/agentsall tiers

Register an agent

Creates an agent record and issues a DID (did:agf:…). The DID is used to issue delegation JWTs that go in the chain field of /v1/decide.

Request body
{
  "name":    "report-writer-v2",      // required — human-readable label
  "did":     "did:agf:agt_01abc",    // optional — supply your own DID or let AGF generate one
  "status":  "active",               // optional — default: active
  "metadata": { "team": "finance" }  // optional
}
Response
{
  "id":         "a1b2c3d4-...",
  "did":        "did:agf:agt_01abc",
  "name":       "report-writer-v2",
  "status":     "active",
  "created_at": "2026-06-24T10:00:00Z"
}
GET/v1/agents/{agent_id}all tiers

Get agent details

Returns the current state of an agent.

Response (200)
{
  "id":         "a1b2c3d4-...",
  "did":        "did:agf:agt_01abc",
  "name":       "report-writer-v2",
  "status":     "active",            // active | suspended | retired
  "created_at": "2026-06-24T10:00:00Z"
}
POST/v1/agents/{agent_id}/revokeall tiers

Revoke an agent

Immediately revokes the target agent. All subsequent /v1/decide calls using this agent's DID will be denied. Revocation is propagated to the revocation list checked on every decision.

Response (200)
{
  "agent_id": "did:agf:agt_01abc",
  "status":   "revoked",
  "revoked_at": "2026-06-24T10:10:00Z"
}
GET/v1/auditall tiers

List audit artifacts

Paginated list of signed decision records for your organisation. Filter by decision, date range, or agent. Each artifact contains the full signed payload.

Response (200)
// Query: ?decision=DENY&limit=20&offset=0&from=2026-06-01&to=2026-06-30

{
  "items": [ { "artifact_id": "dec_...", "decision": "DENY", ... } ],
  "total": 1482,
  "limit": 20,
  "offset": 0
}

Webhooks

growth+

Outbound webhooks push real-time events to your infrastructure — SIEM systems, Slack, PagerDuty, or your own handler. Each delivery is signed with HMAC-SHA256.

GET/v1/webhooksgrowth+

List outbound webhook endpoints

Returns all registered webhook endpoints for your organisation.

Response (200)
{
  "items": [
    {
      "id":               "wh_abc123",
      "url":              "https://your-server.io/agf-events",
      "events":           ["decision.deny", "approval.decided"],
      "enabled":          true,
      "failure_count":    0,
      "last_triggered_at": "2026-06-24T10:00:00Z"
    }
  ]
}
POST/v1/webhooksgrowth+

Register a webhook endpoint

Creates a new outbound webhook. The signing_secret is returned once and never shown again — store it immediately to verify incoming event signatures using HMAC-SHA256.

Request body
{
  "url":    "https://your-server.io/agf-events",  // required — HTTPS endpoint
  "events": [                                       // required — event types to subscribe
    "decision.allow",
    "decision.deny",
    "decision.review_required",
    "approval.decided",
    "quota.warning"
  ]
}
Response
{
  "id":             "wh_abc123",
  "url":            "https://your-server.io/agf-events",
  "events":         ["decision.deny"],
  "enabled":        true,
  "signing_secret": "whsec_live_xxxxxxxxxxxxxxxxxxxxxxxx"
  // ↑ shown once only — store securely
}
PATCH/v1/webhooks/{id}growth+

Update a webhook

Enable or disable a webhook, or change its subscribed event types.

Request body
{
  "enabled": false,            // optional
  "events":  ["decision.deny"] // optional — replace the full event list
}
Response
{ "id": "wh_abc123", "enabled": false, "events": ["decision.deny"] }
DELETE/v1/webhooks/{id}growth+

Delete a webhook

Permanently removes the webhook endpoint. In-flight deliveries that are already queued may still fire.

Response (200)
{ "deleted": true, "id": "wh_abc123" }
POST/v1/webhooks/{id}/testgrowth+

Send a test event

Sends a synthetic ping event to the webhook URL so you can verify receipt and signature verification.

Response (200)
{
  "delivered":     true,
  "status_code":   200,
  "latency_ms":    84,
  "event_id":      "evt_test_abc123"
}

Event payload shape

// Every event has the same envelope shape:
{
  "id":        "evt_1750000000_a1b2c3",  // unique event ID
  "type":      "decision.deny",           // event type
  "org_id":    "xxxxxxxx-...",
  "timestamp": 1750000000,               // Unix seconds
  "data": {
    // decision.* events:
    "artifact_id":      "dec_...",
    "agent_id":         "did:agf:agt_01abc",
    "action_type":      "write:external",
    "action_resource":  "https://evil.io/exfil",
    "decision":         "DENY",
    "risk_score":       78.3,
    "trust_score":      55

    // approval.decided events additionally include:
    // "approval_request_id", "decided_by", "outcome"
  }
}

Verifying signatures

Every delivery includes an X-AGF-Signatureheader. Verify it against the raw request body using your endpoint’s signing secret before processing the payload.

// Node.js — verify HMAC-SHA256 signature
import crypto from 'crypto'

function verifyWebhook(rawBody: Buffer, signatureHeader: string, secret: string): boolean {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex')
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signatureHeader))
}

// Python
import hmac, hashlib

def verify_webhook(raw_body: bytes, signature_header: str, secret: str) -> bool:
    expected = 'sha256=' + hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature_header)

JIT Credentials

growth+

Just-in-time credentials are short-lived API keys scoped to a single agent. Use them for ephemeral workloads, CI/CD pipelines, and any scenario where you want automatic key expiry rather than manual rotation.

POST/v1/agents/{agent_id}/credentialsgrowth+

Issue a JIT credential

Issues a short-lived API key scoped to a single agent. The key is returned once and never retrievable again. Use for ephemeral tasks, CI pipelines, and single-session agent runs. Maximum TTL is 3600 seconds (configurable by org admins).

Request body
{
  "label":       "ci-pipeline-run-4821",  // required — human label for the key
  "ttl_seconds": 900                       // required — lifetime; max 3600
}
Response
{
  "api_key":    "agf_jit_xxxxxxxxxxxxxxxxxxxxxxxx",  // shown once only
  "session_id": "sess_abc123",
  "expires_at": "2026-06-24T10:15:00Z",
  "label":      "ci-pipeline-run-4821"
}
GET/v1/agents/{agent_id}/credentialsgrowth+

List active JIT credentials

Returns all non-expired ephemeral keys for the agent. The key value itself is never returned after initial issuance.

Response (200)
{
  "items": [
    {
      "session_id": "sess_abc123",
      "label":      "ci-pipeline-run-4821",
      "expires_at": "2026-06-24T10:15:00Z"
    }
  ]
}
DELETE/v1/agents/{agent_id}/credentials/{session_id}growth+

Revoke a JIT credential early

Immediately invalidates the credential. Subsequent requests using this key receive 401.

Response (200)
{ "revoked": true, "session_id": "sess_abc123" }

Analytics

starter+

Decision trends, risk scoring, and behavior detection across your agent fleet. All analytics endpoints accept a ?days= query parameter (1–90, default 30).

GET/v1/analytics/summarystarter+

Decision summary

Overall counts and rates for the last N days. Add ?days=7 for a 7-day window (default 30, max 90).

Response (200)
{
  "period_days":    30,
  "total":          14820,
  "allow":          13244,
  "deny":           1312,
  "review":         264,
  "allow_rate_pct": 89.4,
  "deny_rate_pct":  8.8,
  "avg_risk":       18.3,
  "avg_trust":      83.1
}
GET/v1/analytics/decisionsstarter+

Daily decision volume breakdown

Day-by-day allow/deny/review counts. Use to build trend charts. ?days=90 for a 90-day window.

Response (200)
{
  "period_days": 30,
  "data": [
    { "day": "2026-06-01", "label": "Jun 1", "allow": 441, "deny": 42, "review": 8, "total": 491 },
    ...
  ]
}
GET/v1/analytics/riskstarter+

Daily average risk and trust scores

Trend data for risk and trust — useful for detecting behavioral drift across your agent fleet.

Response (200)
{
  "period_days": 30,
  "data": [
    { "day": "2026-06-01", "avg_risk": 15.2, "avg_trust": 84.7 },
    ...
  ]
}
GET/v1/analytics/agentsstarter+

Top agents by decision volume

Ranked list of agents with their decision counts and denial rate. Helps identify high-risk or unusually active agents.

Response (200)
{
  "period_days": 30,
  "data": [
    { "agent_id": "did:agf:agt_01abc", "total": 3210, "allow": 2980, "deny": 195, "review": 35 },
    ...
  ]
}
GET/v1/analytics/denialsstarter+

Most frequent denial patterns

Top action+resource combinations that result in DENY. Use to identify misconfigured scopes or policy gaps.

Response (200)
{
  "period_days": 30,
  "data": [
    { "action_type": "write:external", "action_resource": "s3://logs", "count": 142 },
    ...
  ]
}
GET/v1/analytics/behavior-alertsstarter+

Emergent behavior alerts

Detected multi-step threat patterns across your agent fleet — data exfiltration sequences, privilege escalation, resource hijacking, and lateral movement. Alerts are generated by the AGF scheduler every 5 minutes. Add ?days=7 for a shorter window.

Response (200)
{
  "total":           3,
  "unacknowledged":  2,
  "items": [
    {
      "id":           "uuid",
      "pattern_id":   "p001",
      "pattern_name": "Data Exfiltration",
      "agent_id":     "did:agf:agt_01abc",
      "severity":     "medium",          // "high" | "medium"
      "detected_at":  1750000000,
      "acknowledged_at": null
    }
  ]
}

Behavior detection patterns

The behavior-alerts endpoint surfaces detections from AGF’s threat pattern engine. Actions matching these sequences within the time window trigger an alert.

PatternSequenceWindowSeverity
Data Exfiltrationread:data → write:external1 hourmedium
Privilege Escalationread:policy → modify:policy5 minhigh
Resource Hijackingread:resource → create:resource → delete:resource10 minmedium
Lateral Movementread:credentials → authenticate:service5 minhigh

Access Reviews

starter+

Recertification records track when each agent’s access was last reviewed and when the next review is due. AGF sends automated reminder emails before deadlines. Completing a review resets the certification clock.

GET/v1/compliance/reviewsstarter+

List access review records

Returns recertification records for all agents in your org, ordered by urgency (overdue first). Each record shows the certification tier, last certified date, and days until next review.

Response (200)
{
  "total":    12,
  "due":       3,
  "overdue":   1,
  "items": [
    {
      "record_id":     "rec_abc",
      "agent_id":      "did:agf:agt_01abc",
      "agent_name":    "report-writer-v2",
      "tier":           1,                 // 1=90d, 2=180d, 3=365d
      "last_certified": 1747000000,
      "next_due":       1754776000,
      "status":        "overdue",          // "current" | "due" | "overdue"
      "days_remaining": 0,
      "last_reminder_sent_at": 1750000000
    }
  ]
}
POST/v1/compliance/reviews/{agent_id}/completestarter+

Mark a review complete

Resets the recertification clock for an agent — sets last_certified to now and computes the next_due date based on the agent's tier. Clears any pending reminder.

Response (200)
{
  "agent_id":       "did:agf:agt_01abc",
  "agent_name":     "report-writer-v2",
  "status":         "current",
  "last_certified": 1750000000,
  "next_due":       1757776000,
  "days_remaining": 90
}

Deny reasons

When decision is "DENY", the reasoning array contains one or more of these values.

CodeDescription
scope_exceededThe action is outside the agent's declared scope
trust_too_lowtrust_score fell below the policy threshold
agent_suspendedThe agent has been suspended or revoked
policy_not_foundNo policy matches the action/resource combination
delegation_depthThe delegation chain exceeds the org's maximum depth
rate_limitedThe agent exceeded its allowed request rate
credential_expiredThe JIT credential used in the request has expired

HTTP error codes

CodeStatusMeaning
400Bad RequestMissing required field or malformed JSON
401UnauthorizedMissing or invalid API key
403ForbiddenAPI key does not have access to this resource, or tier gate not met
404Not Foundagent_id, webhook ID, or artifact ID does not exist
409ConflictDuplicate operation (e.g. double-approving a request)
429Too Many RequestsRate limit exceeded — see Retry-After header
500Internal ErrorTransient server error — safe to retry with backoff

Rate limits

Rate limits are applied per API key. The current limit and remaining quota are returned in every response header.

X-RateLimit-Limit:     1000        // requests per minute
X-RateLimit-Remaining: 987
X-RateLimit-Reset:     1750590000  // Unix timestamp
Retry-After:           12          // seconds (only on 429)

Need a higher limit? Contact us — Enterprise plans have custom limits.