{
  "openapi": "3.1.0",
  "info": {"title": "AGNT Webhooks", "version": "2026-09-15", "description": "Durable, signed inbound HTTPS endpoints for agents. Events are stored and billed exactly once before acknowledgement, retained by plan, delivered to receivers with HMAC signatures, and readable over the API. Agents can sign up headlessly and pay for themselves over x402 (USDC on Base)."},
  "servers": [{"url": "https://webhooks.agnt.gg/hooks/v1"}],
  "components": {
    "securitySchemes": {"bearer": {"type": "http", "scheme": "bearer", "description": "Agent secret (hook_…) from POST /agents, a scoped key from POST /keys, or an AGNT owner login token."}},
    "schemas": {
      "Error": {"type": "object", "properties": {"error": {"type": "string"}, "reason": {"type": "string"}, "detail": {"type": "string"}}},
      "Endpoint": {"type": "object", "properties": {"id": {"type": "string"}, "slug": {"type": "string"}, "name": {"type": "string"}, "url": {"type": "string"}, "state": {"type": "string", "enum": ["provisioning", "awaiting_plan", "active", "paused", "retired"]}, "created_at": {"type": "integer"}}},
      "EventSummary": {"type": "object", "properties": {"id": {"type": "string"}, "source": {"type": "string", "enum": ["ingress", "emit"]}, "bytes": {"type": "integer"}, "content_type": {"type": "string"}, "received_at": {"type": "integer"}, "expires_at": {"type": "integer"}}},
      "Event": {"type": "object", "properties": {"id": {"type": "string"}, "endpointId": {"type": "string"}, "source": {"type": "string"}, "contentType": {"type": "string"}, "bytes": {"type": "integer"}, "receivedAt": {"type": "integer"}, "expiresAt": {"type": "integer"}, "body": {"type": "string", "description": "Raw posted body"}}}
    }
  },
  "paths": {
    "/agents": {"post": {"summary": "Headless agent signup", "requestBody": {"content": {"application/json": {"schema": {"type": "object", "required": ["name"], "properties": {"name": {"type": "string"}}}}}}, "responses": {"201": {"description": "Agent created; secret shown once", "content": {"application/json": {"schema": {"type": "object", "properties": {"agentId": {"type": "string"}, "secret": {"type": "string"}, "balance": {"type": "integer"}, "fund": {"type": "object", "properties": {"claimUrl": {"type": "string"}, "x402": {"type": "string"}}}}}}}}, "429": {"description": "Too many signups from this address"}}}},
    "/agents/{agentId}/claim": {"get": {"summary": "Funding and hosting status for an agent", "parameters": [{"name": "agentId", "in": "path", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "OK"}}}},
    "/capabilities": {"get": {"summary": "Live capability flags", "responses": {"200": {"description": "signup, ingress, emit, checkout, autonomousFunding, customerWebhooks"}}}},
    "/plans": {"get": {"summary": "Plan tiers and unit price", "responses": {"200": {"description": "OK"}}}},
    "/usage": {"get": {"security": [{"bearer": []}], "summary": "Balance and hosting status", "responses": {"200": {"description": "credit, reserved, available, frozen, hosting"}}}},
    "/endpoints": {
      "get": {"security": [{"bearer": []}], "summary": "List endpoints", "responses": {"200": {"description": "OK", "content": {"application/json": {"schema": {"type": "object", "properties": {"endpoints": {"type": "array", "items": {"$ref": "#/components/schemas/Endpoint"}}}}}}}}},
      "post": {"security": [{"bearer": []}], "summary": "Create an endpoint (public inbound URL)", "requestBody": {"content": {"application/json": {"schema": {"type": "object", "required": ["name"], "properties": {"name": {"type": "string", "pattern": "^[a-z0-9][a-z0-9-]{1,38}[a-z0-9]$"}}}}}}, "responses": {"201": {"description": "Created", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Endpoint"}}}}, "402": {"description": "hosting_required"}, "409": {"description": "endpoint_limit"}}}
    },
    "/endpoints/{id}/pause": {"post": {"security": [{"bearer": []}], "summary": "Pause the public URL", "parameters": [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "OK"}}}},
    "/endpoints/{id}/resume": {"post": {"security": [{"bearer": []}], "summary": "Resume the public URL", "parameters": [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "OK"}}}},
    "/endpoints/{id}": {"delete": {"security": [{"bearer": []}], "summary": "Retire an endpoint; its slug is never reused", "parameters": [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "OK"}}}},
    "/endpoints/{id}/events": {"get": {"security": [{"bearer": []}], "summary": "List stored events, oldest first, 100 per page", "parameters": [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "after", "in": "query", "schema": {"type": "integer"}, "description": "received_at cursor"}], "responses": {"200": {"description": "OK", "content": {"application/json": {"schema": {"type": "object", "properties": {"events": {"type": "array", "items": {"$ref": "#/components/schemas/EventSummary"}}}}}}}}}},
    "/endpoints/{id}/export": {"get": {"security": [{"bearer": []}], "summary": "Export events with bodies as NDJSON (owner)", "parameters": [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "since", "in": "query", "schema": {"type": "integer"}}], "responses": {"200": {"description": "application/x-ndjson"}}}},
    "/events/{id}": {"get": {"security": [{"bearer": []}], "summary": "Read one event with its body", "parameters": [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "OK", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Event"}}}}, "404": {"description": "event_not_found"}}}},
    "/events/{id}/replay": {"post": {"security": [{"bearer": []}], "summary": "Re-deliver an event to all active receivers (Pro and Business)", "parameters": [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "queued"}, "409": {"description": "replay_requires_pro"}}}},
    "/emit": {"post": {"security": [{"bearer": []}], "summary": "Publish an event from the agent to its receivers", "requestBody": {"content": {"application/json": {"schema": {"type": "object", "required": ["type"], "properties": {"type": {"type": "string", "pattern": "^[a-z0-9_.-]{1,64}$"}, "data": {}, "endpointId": {"type": "string"}}}}}}, "responses": {"202": {"description": "Accepted"}, "413": {"description": "payload_too_large"}}}},
    "/webhooks": {
      "get": {"security": [{"bearer": []}], "summary": "List receivers", "responses": {"200": {"description": "OK"}}},
      "post": {"security": [{"bearer": []}], "summary": "Register a receiver; returns its signing secret once", "requestBody": {"content": {"application/json": {"schema": {"type": "object", "required": ["url"], "properties": {"url": {"type": "string", "format": "uri"}}}}}}, "responses": {"201": {"description": "id, secret"}}}
    },
    "/webhooks/{id}": {"delete": {"security": [{"bearer": []}], "summary": "Revoke a receiver", "parameters": [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}], "responses": {"204": {"description": "Revoked"}}}},
    "/webhooks/{id}/resume": {"post": {"security": [{"bearer": []}], "summary": "Resume a paused receiver and re-queue exhausted deliveries", "parameters": [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "resumed"}}}},
    "/webhook-deliveries": {"get": {"security": [{"bearer": []}], "summary": "Delivery attempts", "responses": {"200": {"description": "OK"}}}},
    "/notifications": {"get": {"security": [{"bearer": []}], "summary": "Event log behind deliveries", "parameters": [{"name": "after", "in": "query", "schema": {"type": "integer"}}], "responses": {"200": {"description": "OK"}}}},
    "/keys": {"post": {"security": [{"bearer": []}], "summary": "Create a scoped agent key (owner)", "requestBody": {"content": {"application/json": {"schema": {"type": "object", "required": ["scopes"], "properties": {"endpointId": {"type": "string"}, "scopes": {"type": "array", "items": {"type": "string", "enum": ["hook:read", "hook:emit", "hook:manage"]}}}}}}}, "responses": {"201": {"description": "id, key (shown once)"}}}},
    "/keys/{keyId}": {"delete": {"security": [{"bearer": []}], "summary": "Revoke a key", "parameters": [{"name": "keyId", "in": "path", "required": true, "schema": {"type": "string"}}], "responses": {"204": {"description": "Revoked"}}}},
    "/hosting/purchase": {"post": {"security": [{"bearer": []}], "summary": "Activate or upgrade a plan from prepaid credit", "parameters": [{"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string"}}], "requestBody": {"content": {"application/json": {"schema": {"type": "object", "properties": {"plan": {"type": "string", "enum": ["starter", "pro", "business"]}}}}}}, "responses": {"200": {"description": "OK"}, "402": {"description": "insufficient_credit"}}}},
    "/hosting/preferences": {"put": {"security": [{"bearer": []}], "summary": "Renewal and overage preferences", "requestBody": {"content": {"application/json": {"schema": {"type": "object", "properties": {"autoRenew": {"type": "boolean"}, "allowOverage": {"type": "boolean"}}}}}}, "responses": {"200": {"description": "OK"}}}},
    "/funding/checkout": {"post": {"security": [{"bearer": []}], "summary": "Stripe Checkout for prepaid credit (owner)", "requestBody": {"content": {"application/json": {"schema": {"type": "object", "properties": {"amountCents": {"type": "integer", "enum": [1000, 2500, 5000]}}}}}}, "responses": {"200": {"description": "url"}}}},
    "/funding/x402": {"post": {"security": [{"bearer": []}], "summary": "Create an x402 funding order (USDC on Base)", "description": "Returns HTTP 402 with x402 v2 requirements in the body and a PAYMENT-REQUIRED header. Pay by POSTing PAYMENT-SIGNATURE to the order URL. @x402/fetch refuses payments over $1 by default; call setSpendControls first. The wallet needs USDC only; the facilitator pays gas.", "requestBody": {"content": {"application/json": {"schema": {"type": "object", "properties": {"amountCents": {"type": "integer", "enum": [1000, 2500, 5000]}}}}}}, "responses": {"402": {"description": "orderId, state, expiresAt, requirements"}, "503": {"description": "x402_unavailable"}}}},
    "/funding/x402/{orderId}": {
      "get": {"security": [{"bearer": []}], "summary": "Order status", "parameters": [{"name": "orderId", "in": "path", "required": true, "schema": {"type": "string"}}], "responses": {"402": {"description": "awaiting_payment"}, "200": {"description": "credited or expired"}}},
      "post": {"security": [{"bearer": []}], "summary": "Submit payment", "parameters": [{"name": "orderId", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "PAYMENT-SIGNATURE", "in": "header", "schema": {"type": "string"}}], "responses": {"200": {"description": "state: credited, transactionId, paymentIntent; PAYMENT-RESPONSE header"}, "400": {"description": "verification failed; nothing charged"}}}
    }
  }
}
