{"openapi":"3.0.3","info":{"title":"webhook-inbox","description":"Registry id: co.kymac.inbox/webhook-inbox.\nCapability keywords: webhook inbox, request bin, capture post.\nMachine-buyable ephemeral HTTPS inbox. Keys, prepaid TEST credits, mint, capture, and list are live.\nSole advertised bot entry is GET /llms.txt. Do not start here.\nPublic capture URL is not an install entry.\nPrefer Authorization: Bearer; X-API-Key is an alias only.\nDebit policy: burn 1 credit on successful POST /inbox only (reason=`inbox_mint`, request_id=inbox id). Capture and list do not debit. Fail closed: errors do not debit. Early revoke does not refund.\nFirst POST /keys grants 1 free credit. Quote GET /credits/quote?op=inbox. Checkout is intent-only (`credits_pending`) until POST /credits/confirm.\nLive Stripe is gated (unlock-live).\n","x-registry-id":"co.kymac.inbox/webhook-inbox","version":"0.4.1"},"servers":[{"url":"https://inbox.kymac.co","description":"Public live host."}],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"paths":{"/health":{"get":{"operationId":"getHealth","summary":"Health (billing + runner)","description":"Public readiness. Reports Stripe `billing` (`test` | `live` | `gated`) and `runner_ready`. Mint/capture/list are live; `runner_ready` stays false until a later cut treats mint as the runner. `ok` is true when the process is up. Live Stripe stays gated. No key. Not an install entry — start at GET /llms.txt.\n","security":[],"responses":{"200":{"description":"Process is up.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Health"},"example":{"ok":true,"status":"ok","service":"webhook-inbox","version":"0.4.1","billing":"test","runner_ready":false}}}}}}},"/incidents":{"get":{"operationId":"getIncidents","summary":"Public incident feed","description":"Public unauthenticated status feed bots can poll for outages or degradation (beyond GET /health). Not an install entry — start at GET /llms.txt. Healthy default is `status: none` and an empty `incidents` array. No invented incidents. No key.\n","security":[],"responses":{"200":{"description":"Stable incident JSON. Empty incidents when healthy.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Incidents"},"example":{"ok":true,"service":"webhook-inbox","status":"none","incidents":[]}}}}}}},"/mcp":{"get":{"operationId":"mcpSse","summary":"MCP Streamable HTTP (SSE)","description":"Optional GET for the MCP Streamable HTTP event stream.\nPrefer POST /mcp for initialize, tools/list, and tools/call.\nPublic path; gated tools still require a caller key.\nNot an install entry — start at GET /llms.txt.\n","security":[],"responses":{"200":{"description":"SSE stream when the client requested text/event-stream.","content":{"text/event-stream":{"schema":{"type":"string"}}}}},"tags":["webhook inbox","request bin","capture post"]},"post":{"operationId":"mcpStreamableHttp","summary":"MCP Streamable HTTP","description":"Model Context Protocol Streamable HTTP (JSON-RPC 2.0).\n`tools/list` includes `issue_key`, `verify_key`, `rotate_key`, `revoke_key`, `quote_credits`, `list_credit_packs`, `checkout_credits`, `confirm_credits`, `credit_balance`, `credit_events`, `mint_inbox`, `capture_inbox`, `list_inbox_events`, `revoke_inbox`, and optional `health`.\nBot install starts at GET /llms.txt (sole advertised entry).\nGated tools prefer `Authorization: Bearer whi_…` or env `WEBHOOK_INBOX_API_KEY`. `X-API-Key` is an alias only.\nInbox tools return the same 200 credit fields and fail JSON as HTTP.\nPublic path; auth is per-tool.\n","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpJsonRpcRequest"},"examples":{"toolsList":{"summary":"List MCP tools","value":{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}},"initialize":{"summary":"Initialize MCP session","value":{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"probe","version":"0"}}}}}}}},"responses":{"200":{"description":"JSON-RPC result as text/event-stream.","content":{"text/event-stream":{"schema":{"$ref":"#/components/schemas/McpJsonRpcResponse"}},"application/json":{"schema":{"$ref":"#/components/schemas/McpJsonRpcResponse"}}}},"406":{"description":"Client did not accept both application/json and text/event-stream.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpJsonRpcResponse"}}}}},"tags":["webhook inbox","request bin","capture post"]}},"/keys":{"post":{"operationId":"issueKey","summary":"Issue a caller key","description":"Mints a caller key. Secret is returned once. Prefer `Authorization: Bearer <key>`; `X-API-Key` is an alias only. Key `id` is the stable `caller_id` for credit ledger events. First issue grants 1 free credit (`credit.grant` reason=first_key) so GET /credits/quote?op=inbox can complete without prepaid checkout.\n","security":[],"responses":{"201":{"description":"Key issued. `key` is shown only here.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssuedKey"},"example":{"ok":true,"key":"whi_abcdefghijklmnopqrstuvwxyz012345","id":"k_0123456789abcdef","createdAt":"2026-09-17T10:00:00.000Z"}}}}},"tags":["webhook inbox","request bin","capture post"]}},"/keys/verify":{"get":{"operationId":"verifyKey","summary":"Verify a caller key","description":"Confirms the presented key is valid. Does not echo the secret.","responses":{"200":{"description":"Key is valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifiedKey"}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/keys/rotate":{"post":{"operationId":"rotateKey","summary":"Rotate a caller key","description":"Requires the current caller key. Same `id` / `caller_id` so credits stay attached. New `whi_…` is returned once. The previous secret then fails 401 `invalid_api_key`.","responses":{"201":{"description":"New secret issued. `key` is shown only here.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssuedKey"}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/keys/revoke":{"post":{"operationId":"revokeKey","summary":"Revoke a caller key","description":"Invalidates the presented secret. Subsequent calls with that secret fail 401 `invalid_api_key`.","responses":{"200":{"description":"Key revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevokedKey"}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/credits/quote":{"get":{"operationId":"quoteCredits","summary":"Quote an operation without debiting","description":"Dry-run cost for `op=inbox`. Returns whether the caller can mint (`would_succeed`) and the 1-credit `cost` without appending `credit.debit`. Requires a caller key. Unknown or missing `op` → 400. Successful POST /inbox burns that 1 credit (reason=`inbox_mint`).","parameters":[{"in":"query","name":"op","required":true,"schema":{"type":"string","enum":["inbox"]},"description":"Operation to quote. Only inbox is supported."}],"responses":{"200":{"description":"Quote for the operation. Does not debit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditQuote"},"example":{"ok":true,"caller_id":"k_0123456789abcdef","op":"inbox","cost":1,"balance":1,"would_succeed":true}}}},"400":{"description":"Missing or unknown op.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"}},"tags":["webhook inbox","request bin","capture post"]}},"/credits/balance":{"get":{"operationId":"getCreditBalance","summary":"Caller credit balance","description":"Derived balance for this `caller_id` (grant + purchase − debit).","responses":{"200":{"description":"Current balance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditBalance"}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/credits/events":{"get":{"operationId":"getCreditEvents","summary":"Append-only credit ledger","description":"Events for this `caller_id` only. Types: `credit.grant` (reason=first_key), `credit.purchase`, `credit.debit` (reason=inbox_mint on successful mint), optional `credit.balance_snapshot`.","responses":{"200":{"description":"Append-only events, oldest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditEventList"}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/credits/packs":{"get":{"operationId":"listCreditPacks","summary":"List prepaid credit packs","description":"Machine-buyable Stripe TEST packs. Public. Live Stripe is gated (unlock-live). Buy with POST /credits/checkout.","security":[],"responses":{"200":{"description":"TEST pack catalog.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditPackList"}}}}}}},"/credits/checkout":{"post":{"operationId":"checkoutCredits","summary":"Create a TEST PaymentIntent for a pack","description":"Stripe TEST PaymentIntent for `pack_id`, tied to this caller's `caller_id`. Intent only — does not grant or spend credits. `credits_pending` is the pack size after confirm; balance is unchanged until POST /credits/confirm (TEST card pm_card_visa). Fail-closed if live keys are configured.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditCheckoutRequest"},"example":{"pack_id":"pack_10"}}}},"responses":{"200":{"description":"TEST PaymentIntent created. Intent only — not granted or spendable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditCheckout"},"example":{"ok":true,"mode":"test","caller_id":"k_0123456789abcdef","pack_id":"pack_10","credits_pending":10,"amount_cents":100,"currency":"usd","stripe_payment_intent_id":"pi_test_123","client_secret":"pi_test_123_secret_abc","publishable_key":"pk_test_123"}}}},"400":{"description":"Bad pack_id or body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"code":"invalid_request","message":"pack_id is required","retryable":false,"error":"pack_id is required","next":"fix request"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"503":{"$ref":"#/components/responses/StripeUnavailable"}}}},"/credits/confirm":{"post":{"operationId":"confirmCredits","summary":"Confirm a TEST credit purchase","description":"Confirms the PaymentIntent with Stripe test payment method `pm_card_visa` (TEST only). On success, appends `credit.purchase` and `credit.balance_snapshot`. Idempotent on payment intent id.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditConfirmRequest"},"example":{"stripe_payment_intent_id":"pi_test_123"}}}},"responses":{"200":{"description":"Purchase recorded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditConfirm"}}}},"400":{"description":"Missing id, unpaid, or intent belongs to another caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"503":{"$ref":"#/components/responses/StripeUnavailable"}}}},"/inbox":{"post":{"operationId":"mintInbox","summary":"Mint an ephemeral inbox","description":"Creates `{ id, capture_url, expires_at }`. Debit policy: burns 1 credit on success only (ledger `credit.debit` reason=`inbox_mint`, `request_id`=inbox id). Fail closed: 401/402 and other errors do not debit and do not leave an inbox. Capture and list do not debit. TTL is 1 hour. `capture_url` is a public POST target (`/c/{id}`) and is not an install entry.","responses":{"201":{"description":"Inbox minted. One credit burned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MintedInbox"},"example":{"ok":true,"id":"inb_0123456789abcdef0123456789abcdef","capture_url":"https://inbox.kymac.co/c/inb_0123456789abcdef0123456789abcdef","expires_at":"2026-09-18T00:00:00.000Z","credits_remaining":0}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/InsufficientCredits"}},"tags":["webhook inbox","request bin","capture post"]}},"/c/{id}":{"post":{"operationId":"captureInbox","summary":"Capture a raw POST","description":"Public. No API key. Not an install entry. Stores the raw body and incoming headers for later GET /inbox/{id}/events. Does not debit. Rejects revoked (410 `inbox_revoked`) or expired (410 `inbox_expired`) inboxes. Body limit 1MB.","security":[],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"},"description":"Inbox id from POST /inbox."}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}},"application/octet-stream":{"schema":{"type":"string","format":"binary"}},"text/plain":{"schema":{"type":"string"}}}},"responses":{"200":{"description":"Captured.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CapturedEventAck"}}}},"400":{"description":"Inbox event limit reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown inbox.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"410":{"description":"Inbox expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Payload larger than 1MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"tags":["webhook inbox","request bin","capture post"]}},"/inbox/{id}/events":{"get":{"operationId":"listInboxEvents","summary":"List captured POSTs","description":"Authenticated owner only. Returns captured POSTs as JSON (headers + body). Does not debit. Other callers see 404. Listing still works after revoke so already-captured events can be read.","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Captured events, oldest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboxEventList"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"description":"Unknown inbox or not owned by this caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"tags":["webhook inbox","request bin","capture post"]}},"/inbox/{id}":{"delete":{"operationId":"revokeInbox","summary":"Revoke an inbox early","description":"Stops further captures. Does not refund the mint debit. Idempotent. Owner only.","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Inbox revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevokedInbox"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"description":"Unknown inbox or not owned by this caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"tags":["webhook inbox","request bin","capture post"]}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Preferred. Caller key from POST /keys (`Authorization: Bearer <key>`)."},"apiKeyHeader":{"type":"apiKey","in":"header","name":"X-API-Key","description":"Alias only. Same secret as Bearer. Prefer Authorization Bearer."}},"responses":{"Unauthorized":{"description":"Missing or invalid caller key.","headers":{"WWW-Authenticate":{"schema":{"type":"string","example":"Bearer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"missing":{"value":{"code":"missing_api_key","message":"missing API key","retryable":false,"error":"missing API key","next":"refresh key"}},"invalid":{"value":{"code":"invalid_api_key","message":"invalid API key","retryable":false,"error":"invalid API key","next":"refresh key"}}}}}},"StripeUnavailable":{"description":"Stripe TEST keys missing, or live keys rejected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"InsufficientCredits":{"description":"Caller cannot afford the 1-credit mint. No debit. No inbox created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InsufficientCredits"}}}}},"schemas":{"Health":{"type":"object","additionalProperties":false,"required":["ok","status","service","version","billing","runner_ready"],"properties":{"ok":{"type":"boolean","description":"True when the HTTP process is up."},"status":{"type":"string","enum":["ok","not_ready"]},"service":{"type":"string","enum":["webhook-inbox"]},"version":{"type":"string","example":"0.4.1"},"billing":{"type":"string","enum":["test","live","gated"],"description":"Stripe mode. `live` is reserved for unlock-live. Hosts report `test` when TEST secrets or BILLING=test are present, otherwise `gated`."},"runner_ready":{"type":"boolean","description":"Inbox capture runner. False on this cut; mint/capture/list are live without treating mint as the runner."}}},"Error":{"type":"object","additionalProperties":false,"required":["code","message","retryable","error","next"],"properties":{"code":{"type":"string","description":"Stable machine code (snake_case).","enum":["missing_api_key","invalid_api_key","invalid_request","stripe_not_configured","stripe_misconfigured","not_found","inbox_expired","inbox_revoked","inbox_full","payload_too_large","internal_error"]},"message":{"type":"string"},"retryable":{"type":"boolean"},"error":{"type":"string","description":"Alias of message."},"next":{"type":"string","enum":["buy credits","refresh key","retry","fix request"]}}},"IssuedKey":{"type":"object","additionalProperties":false,"required":["ok","key","id","createdAt"],"properties":{"ok":{"type":"boolean","enum":[true]},"key":{"type":"string","description":"Secret. Shown only at issue or rotate time. Prefix whi_."},"id":{"type":"string","description":"Public key id (k_ + hex)."},"createdAt":{"type":"string","format":"date-time"}}},"VerifiedKey":{"type":"object","additionalProperties":false,"required":["ok","id","createdAt"],"properties":{"ok":{"type":"boolean","enum":[true]},"id":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}},"RevokedKey":{"type":"object","additionalProperties":false,"required":["ok","id","revoked"],"properties":{"ok":{"type":"boolean","enum":[true]},"id":{"type":"string"},"revoked":{"type":"boolean","enum":[true]}}},"InsufficientCredits":{"type":"object","additionalProperties":false,"required":["code","message","retryable","error","next","caller_id","balance","required"],"properties":{"code":{"type":"string","enum":["insufficient_credits"]},"message":{"type":"string","enum":["insufficient credits"]},"retryable":{"type":"boolean","enum":[false]},"error":{"type":"string","enum":["insufficient credits"]},"next":{"type":"string","enum":["buy credits"]},"caller_id":{"type":"string"},"balance":{"type":"integer","minimum":0},"required":{"type":"integer","minimum":1,"example":1}}},"CreditPack":{"type":"object","additionalProperties":false,"required":["pack_id","credits","amount_cents","currency"],"properties":{"pack_id":{"type":"string"},"credits":{"type":"integer","minimum":1},"amount_cents":{"type":"integer","minimum":1},"currency":{"type":"string","enum":["usd"]}}},"CreditPackList":{"type":"object","additionalProperties":false,"required":["ok","mode","packs"],"properties":{"ok":{"type":"boolean","enum":[true]},"mode":{"type":"string","enum":["test"]},"packs":{"type":"array","items":{"$ref":"#/components/schemas/CreditPack"}}}},"CreditCheckoutRequest":{"type":"object","additionalProperties":false,"required":["pack_id"],"properties":{"pack_id":{"type":"string"}}},"CreditCheckout":{"type":"object","additionalProperties":false,"required":["ok","mode","caller_id","pack_id","credits_pending","amount_cents","currency","stripe_payment_intent_id","publishable_key"],"properties":{"ok":{"type":"boolean","enum":[true]},"mode":{"type":"string","enum":["test"]},"caller_id":{"type":"string"},"pack_id":{"type":"string"},"credits_pending":{"type":"integer","description":"Pack size after confirm succeeds. Not granted or spendable yet."},"amount_cents":{"type":"integer"},"currency":{"type":"string","enum":["usd"]},"stripe_payment_intent_id":{"type":"string"},"client_secret":{"type":"string","nullable":true},"publishable_key":{"type":"string","description":"pk_test_… only."}}},"CreditConfirmRequest":{"type":"object","additionalProperties":false,"required":["stripe_payment_intent_id"],"properties":{"stripe_payment_intent_id":{"type":"string"}}},"CreditPurchaseEvent":{"type":"object","additionalProperties":false,"required":["type","caller_id","pack_id","credits_added","amount_cents","currency","stripe_payment_intent_id","ts"],"properties":{"type":{"type":"string","enum":["credit.purchase"]},"caller_id":{"type":"string"},"pack_id":{"type":"string"},"credits_added":{"type":"integer","minimum":1},"amount_cents":{"type":"integer","minimum":1},"currency":{"type":"string","enum":["usd"]},"stripe_payment_intent_id":{"type":"string"},"ts":{"type":"string","format":"date-time"}}},"CreditGrantEvent":{"type":"object","additionalProperties":false,"required":["type","caller_id","credits_added","reason","ts"],"properties":{"type":{"type":"string","enum":["credit.grant"]},"caller_id":{"type":"string"},"credits_added":{"type":"integer","minimum":1},"reason":{"type":"string","enum":["first_key"]},"ts":{"type":"string","format":"date-time"}}},"CreditQuote":{"type":"object","additionalProperties":false,"required":["ok","caller_id","op","cost","balance","would_succeed"],"properties":{"ok":{"type":"boolean","enum":[true]},"caller_id":{"type":"string"},"op":{"type":"string","enum":["inbox"]},"cost":{"type":"integer","minimum":1,"example":1},"balance":{"type":"integer","minimum":0},"would_succeed":{"type":"boolean"}}},"CreditDebitEvent":{"type":"object","additionalProperties":false,"required":["type","caller_id","credits_burned","reason","request_id","ts"],"properties":{"type":{"type":"string","enum":["credit.debit"]},"caller_id":{"type":"string"},"credits_burned":{"type":"integer","minimum":1},"reason":{"type":"string","enum":["inbox_mint"]},"request_id":{"type":"string"},"ts":{"type":"string","format":"date-time"}}},"CreditBalanceSnapshotEvent":{"type":"object","additionalProperties":false,"required":["type","caller_id","balance","ts"],"properties":{"type":{"type":"string","enum":["credit.balance_snapshot"]},"caller_id":{"type":"string"},"balance":{"type":"integer","minimum":0},"ts":{"type":"string","format":"date-time"}}},"LedgerEvent":{"oneOf":[{"$ref":"#/components/schemas/CreditPurchaseEvent"},{"$ref":"#/components/schemas/CreditGrantEvent"},{"$ref":"#/components/schemas/CreditDebitEvent"},{"$ref":"#/components/schemas/CreditBalanceSnapshotEvent"}],"discriminator":{"propertyName":"type","mapping":{"credit.purchase":"#/components/schemas/CreditPurchaseEvent","credit.grant":"#/components/schemas/CreditGrantEvent","credit.debit":"#/components/schemas/CreditDebitEvent","credit.balance_snapshot":"#/components/schemas/CreditBalanceSnapshotEvent"}}},"CreditConfirm":{"type":"object","additionalProperties":false,"required":["ok","mode","event","snapshot","balance"],"properties":{"ok":{"type":"boolean","enum":[true]},"mode":{"type":"string","enum":["test"]},"event":{"$ref":"#/components/schemas/CreditPurchaseEvent"},"snapshot":{"$ref":"#/components/schemas/CreditBalanceSnapshotEvent"},"balance":{"type":"integer","minimum":0}}},"CreditBalance":{"type":"object","additionalProperties":false,"required":["ok","caller_id","balance","ts"],"properties":{"ok":{"type":"boolean","enum":[true]},"caller_id":{"type":"string"},"balance":{"type":"integer","minimum":0},"ts":{"type":"string","format":"date-time"}}},"MintedInbox":{"type":"object","additionalProperties":false,"required":["ok","id","capture_url","expires_at","credits_remaining"],"properties":{"ok":{"type":"boolean","enum":[true]},"id":{"type":"string","description":"Inbox id (inb_ + hex)."},"capture_url":{"type":"string","format":"uri","description":"Public POST URL. No API key."},"expires_at":{"type":"string","format":"date-time"},"credits_remaining":{"type":"integer","minimum":0,"description":"Balance after the 1-credit mint debit."}}},"CapturedEventAck":{"type":"object","additionalProperties":false,"required":["ok","id","inbox_id"],"properties":{"ok":{"type":"boolean","enum":[true]},"id":{"type":"string","description":"Event id (evt_ + hex)."},"inbox_id":{"type":"string"}}},"CapturedEvent":{"type":"object","additionalProperties":false,"required":["id","inbox_id","received_at","method","headers","content_type","encoding","body","byte_length"],"properties":{"id":{"type":"string"},"inbox_id":{"type":"string"},"received_at":{"type":"string","format":"date-time"},"method":{"type":"string","enum":["POST"]},"headers":{"type":"object","additionalProperties":{"type":"string"},"description":"Incoming request headers (lowercase names)."},"content_type":{"type":"string","nullable":true},"encoding":{"type":"string","enum":["utf8","base64"],"description":"utf8 when the raw body is valid UTF-8; otherwise body is base64."},"body":{"type":"string"},"byte_length":{"type":"integer","minimum":0}}},"InboxEventList":{"type":"object","additionalProperties":false,"required":["ok","inbox_id","expires_at","revoked","events"],"properties":{"ok":{"type":"boolean","enum":[true]},"inbox_id":{"type":"string"},"expires_at":{"type":"string","format":"date-time"},"revoked":{"type":"boolean"},"events":{"type":"array","items":{"$ref":"#/components/schemas/CapturedEvent"}}}},"RevokedInbox":{"type":"object","additionalProperties":false,"required":["ok","id","revoked"],"properties":{"ok":{"type":"boolean","enum":[true]},"id":{"type":"string"},"revoked":{"type":"boolean","enum":[true]}}},"CreditEventList":{"type":"object","additionalProperties":false,"required":["ok","caller_id","events"],"properties":{"ok":{"type":"boolean","enum":[true]},"caller_id":{"type":"string"},"events":{"type":"array","items":{"$ref":"#/components/schemas/LedgerEvent"}}}},"Incident":{"type":"object","additionalProperties":false,"required":["id","status","summary"],"properties":{"id":{"type":"string"},"status":{"type":"string","enum":["degraded","outage"]},"summary":{"type":"string"}}},"Incidents":{"type":"object","additionalProperties":false,"required":["ok","service","status","incidents"],"properties":{"ok":{"type":"boolean","enum":[true]},"service":{"type":"string","enum":["webhook-inbox"]},"status":{"type":"string","enum":["none","degraded","outage"],"description":"`none` when there are no active incidents. `degraded` and `outage` are reserved for operator-declared incidents only.\n"},"incidents":{"type":"array","description":"Active incidents. Empty when healthy. Never invented.","items":{"$ref":"#/components/schemas/Incident"}}}},"McpJsonRpcRequest":{"type":"object","required":["jsonrpc","method"],"properties":{"jsonrpc":{"type":"string","enum":["2.0"]},"id":{"oneOf":[{"type":"string"},{"type":"integer"},{"type":"null"}]},"method":{"type":"string"},"params":{"type":"object","additionalProperties":true}}},"McpJsonRpcResponse":{"type":"object","required":["jsonrpc"],"properties":{"jsonrpc":{"type":"string","enum":["2.0"]},"id":{"oneOf":[{"type":"string"},{"type":"integer"},{"type":"null"}]},"result":{"type":"object","additionalProperties":true},"error":{"type":"object","properties":{"code":{"type":"integer"},"message":{"type":"string"}}}}}}},"tags":[{"name":"webhook inbox","description":"Registry id co.kymac.inbox/webhook-inbox. Not an install entry — start at GET /llms.txt.\n"},{"name":"request bin","description":"Ephemeral HTTPS inbox that captures POSTs for later JSON list. Not an install entry — start at GET /llms.txt.\n"},{"name":"capture post","description":"Public POST to capture_url stores raw body and headers. Not an install entry — start at GET /llms.txt.\n"}]}