{"openapi":"3.1.1","info":{"title":"Openhook native API","version":"0.1.0","description":"Webhook inboxes for agents. For MCP use the Streamable HTTP endpoint /mcp. Each inbox has its own private management token. Stable inbox operations use /api/v1; /api paths remain supported aliases. Breaking changes require a new major version. Deprecation and Sunset headers will announce a removal at least 90 days in advance. No removal is scheduled.","license":{"name":"MIT","identifier":"MIT"}},"servers":[{"url":"https://openhook.dev"}],"paths":{"/api/call":{"post":{"operationId":"callInbox","summary":"Create, inspect, configure, or delete a webhook inbox","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebCall"}}}},"responses":{"200":{"description":"Successful response. call/wait wrap the result in data; export returns requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Success"}}},"headers":{"RateLimit-Policy":{"description":"Per-IP rolling request budget: 120 requests in 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"Remaining quota and seconds until the next slot is available.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Compatibility limit header.","schema":{"type":"string"}},"RateLimit-Remaining":{"description":"Compatibility remaining quota.","schema":{"type":"string"}},"RateLimit-Reset":{"description":"Seconds until the next slot is available.","schema":{"type":"string"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Invalid private token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Cross-origin request rejected","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Inbox expired or not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"413":{"description":"Request body exceeds limit","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate or inbox limit reached; honor Retry-After when present","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"Retry-After":{"description":"Seconds to wait for an HTTP rate limit; capacity errors may need cleanup or renewal instead.","schema":{"type":"integer"}}}},"405":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"description":"Send action=create to obtain data.token and data.url. All other actions need the private token. Use get with request_id for full content, list with page for previews, send with payload for a marked test event, configure with config for response settings, rotate to replace the private token, activity with since/limit for durable history, and delete to remove the inbox. Never put a private token in a public URL. Tokens are in the JSON body, not an Authorization header."}},"/api/wait":{"post":{"operationId":"waitForEvent","summary":"Wait with a cursor for an event (up to 30 seconds)","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WaitCall"}}}},"responses":{"200":{"description":"Successful response. call/wait wrap the result in data; export returns requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Success"}}},"headers":{"RateLimit-Policy":{"description":"Per-IP rolling request budget: 120 requests in 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"Remaining quota and seconds until the next slot is available.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Compatibility limit header.","schema":{"type":"string"}},"RateLimit-Remaining":{"description":"Compatibility remaining quota.","schema":{"type":"string"}},"RateLimit-Reset":{"description":"Seconds until the next slot is available.","schema":{"type":"string"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Invalid private token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Cross-origin request rejected","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Inbox expired or not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"413":{"description":"Request body exceeds limit","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate or inbox limit reached; honor Retry-After when present","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"Retry-After":{"description":"Seconds to wait for an HTTP rate limit; capacity errors may need cleanup or renewal instead.","schema":{"type":"integer"}}}},"405":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"description":"Use since=0 initially, then data.next_since after successful processing. Returns data.request (event or null), data.next_since, and data.timeout. This is an outbound long poll; it does not wake a stopped agent session."}},"/api/export":{"post":{"operationId":"exportEvents","summary":"Stream all retained events with original body bytes","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportCall"}}}},"responses":{"200":{"description":"Successful response. call/wait wrap the result in data; export returns requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventExport"}}},"headers":{"RateLimit-Policy":{"description":"Per-IP rolling request budget: 120 requests in 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"Remaining quota and seconds until the next slot is available.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Compatibility limit header.","schema":{"type":"string"}},"RateLimit-Remaining":{"description":"Compatibility remaining quota.","schema":{"type":"string"}},"RateLimit-Reset":{"description":"Seconds until the next slot is available.","schema":{"type":"string"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Invalid private token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Cross-origin request rejected","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Inbox expired or not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"413":{"description":"Request body exceeds limit","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate or inbox limit reached; honor Retry-After when present","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"Retry-After":{"description":"Seconds to wait for an HTTP rate limit; capacity errors may need cleanup or renewal instead.","schema":{"type":"integer"}}}},"405":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/tools":{"get":{"operationId":"listMcpTools","summary":"Live MCP names and JSON input schemas","responses":{"200":{"description":"MCP tool catalog","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolCatalog"}}},"headers":{"RateLimit-Policy":{"description":"Per-IP rolling request budget: 120 requests in 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"Remaining quota and seconds until the next slot is available.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Compatibility limit header.","schema":{"type":"string"}},"RateLimit-Remaining":{"description":"Compatibility remaining quota.","schema":{"type":"string"}},"RateLimit-Reset":{"description":"Seconds until the next slot is available.","schema":{"type":"string"}}}},"400":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"405":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"413":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"Retry-After":{"description":"Seconds to wait for an HTTP rate limit; capacity errors may need cleanup or renewal instead.","schema":{"type":"integer"}}}},"500":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/health":{"get":{"operationId":"health","summary":"Storage health and configured transport flags","responses":{"200":{"description":"Storage is reachable; not proof of public transport delivery","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Health"}}}},"400":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"405":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"413":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/h/{identifier}":{"get":{"summary":"Receive an event at the public URL returned when creating an inbox","parameters":[{"name":"identifier","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"description":"Capture accepts incoming bodies, not private read access. Keep the private token out of this URL. Optional signature verification and configured HTTP response apply.","responses":{"200":{"description":"Default is text/plain. JSON is returned only if the inbox owner configures a JSON response body and content type; status and body are owner-controlled. HEAD returns no body.","content":{"text/plain":{"schema":{"type":"string"}},"application/json":{"schema":{},"example":{"received":true}}}},"401":{"description":"Signature verification failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Inbox missing or expired","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"413":{"description":"Body too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit reached","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"400":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"405":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"operationId":"captureGet"},"head":{"summary":"Receive an event at the public URL returned when creating an inbox","parameters":[{"name":"identifier","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"description":"Capture accepts incoming bodies, not private read access. Keep the private token out of this URL. Optional signature verification and configured HTTP response apply.","responses":{"200":{"description":"Default is text/plain. JSON is returned only if the inbox owner configures a JSON response body and content type; status and body are owner-controlled. HEAD returns no body.","content":{"text/plain":{"schema":{"type":"string"}},"application/json":{"schema":{},"example":{"received":true}}}},"401":{"description":"Signature verification failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Inbox missing or expired","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"413":{"description":"Body too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit reached","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"400":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"405":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"operationId":"captureHead"},"post":{"summary":"Receive an event at the public URL returned when creating an inbox","parameters":[{"name":"identifier","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Optional source event ID. Repeated deliveries with the same ID in this inbox return the retained original event; deduplication ends when that event is deleted or expires.","schema":{"type":"string"}}],"description":"Capture accepts incoming bodies, not private read access. Keep the private token out of this URL. Optional signature verification and configured HTTP response apply.","responses":{"200":{"description":"Default is text/plain. JSON is returned only if the inbox owner configures a JSON response body and content type; status and body are owner-controlled. HEAD returns no body.","content":{"text/plain":{"schema":{"type":"string"}},"application/json":{"schema":{},"example":{"received":true}}}},"401":{"description":"Signature verification failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Inbox missing or expired","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"413":{"description":"Body too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit reached","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"400":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"405":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"operationId":"capturePost"},"put":{"summary":"Receive an event at the public URL returned when creating an inbox","parameters":[{"name":"identifier","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Optional source event ID. Repeated deliveries with the same ID in this inbox return the retained original event; deduplication ends when that event is deleted or expires.","schema":{"type":"string"}}],"description":"Capture accepts incoming bodies, not private read access. Keep the private token out of this URL. Optional signature verification and configured HTTP response apply.","responses":{"200":{"description":"Default is text/plain. JSON is returned only if the inbox owner configures a JSON response body and content type; status and body are owner-controlled. HEAD returns no body.","content":{"text/plain":{"schema":{"type":"string"}},"application/json":{"schema":{},"example":{"received":true}}}},"401":{"description":"Signature verification failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Inbox missing or expired","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"413":{"description":"Body too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit reached","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"400":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"405":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"operationId":"capturePut"},"patch":{"summary":"Receive an event at the public URL returned when creating an inbox","parameters":[{"name":"identifier","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Optional source event ID. Repeated deliveries with the same ID in this inbox return the retained original event; deduplication ends when that event is deleted or expires.","schema":{"type":"string"}}],"description":"Capture accepts incoming bodies, not private read access. Keep the private token out of this URL. Optional signature verification and configured HTTP response apply.","responses":{"200":{"description":"Default is text/plain. JSON is returned only if the inbox owner configures a JSON response body and content type; status and body are owner-controlled. HEAD returns no body.","content":{"text/plain":{"schema":{"type":"string"}},"application/json":{"schema":{},"example":{"received":true}}}},"401":{"description":"Signature verification failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Inbox missing or expired","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"413":{"description":"Body too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit reached","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"400":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"405":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"operationId":"capturePatch"},"delete":{"summary":"Receive an event at the public URL returned when creating an inbox","parameters":[{"name":"identifier","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"description":"Capture accepts incoming bodies, not private read access. Keep the private token out of this URL. Optional signature verification and configured HTTP response apply.","responses":{"200":{"description":"Default is text/plain. JSON is returned only if the inbox owner configures a JSON response body and content type; status and body are owner-controlled. HEAD returns no body.","content":{"text/plain":{"schema":{"type":"string"}},"application/json":{"schema":{},"example":{"received":true}}}},"401":{"description":"Signature verification failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Inbox missing or expired","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"413":{"description":"Body too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit reached","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"400":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"405":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"operationId":"captureDelete"},"options":{"summary":"Receive an event at the public URL returned when creating an inbox","parameters":[{"name":"identifier","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"description":"Capture accepts incoming bodies, not private read access. Keep the private token out of this URL. Optional signature verification and configured HTTP response apply.","responses":{"200":{"description":"Default is text/plain. JSON is returned only if the inbox owner configures a JSON response body and content type; status and body are owner-controlled. HEAD returns no body.","content":{"text/plain":{"schema":{"type":"string"}},"application/json":{"schema":{},"example":{"received":true}}}},"401":{"description":"Signature verification failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Inbox missing or expired","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"413":{"description":"Body too large","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit reached","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"400":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"405":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"operationId":"captureOptions"}},"/api/v1/call":{"post":{"operationId":"callInboxV1","summary":"Create, inspect, configure, or delete a webhook inbox","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebCall"}}}},"responses":{"200":{"description":"Successful response. call/wait wrap the result in data; export returns requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Success"}}},"headers":{"RateLimit-Policy":{"description":"Per-IP rolling request budget: 120 requests in 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"Remaining quota and seconds until the next slot is available.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Compatibility limit header.","schema":{"type":"string"}},"RateLimit-Remaining":{"description":"Compatibility remaining quota.","schema":{"type":"string"}},"RateLimit-Reset":{"description":"Seconds until the next slot is available.","schema":{"type":"string"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Invalid private token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Cross-origin request rejected","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Inbox expired or not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"413":{"description":"Request body exceeds limit","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate or inbox limit reached; honor Retry-After when present","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"Retry-After":{"description":"Seconds to wait for an HTTP rate limit; capacity errors may need cleanup or renewal instead.","schema":{"type":"integer"}}}},"405":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"description":"Send action=create to obtain data.token and data.url. All other actions need the private token. Use get with request_id for full content, list with page for previews, send with payload for a marked test event, configure with config for response settings, rotate to replace the private token, activity with since/limit for durable history, and delete to remove the inbox. Never put a private token in a public URL. Tokens are in the JSON body, not an Authorization header."}},"/api/v1/wait":{"post":{"operationId":"waitForEventV1","summary":"Wait with a cursor for an event (up to 30 seconds)","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WaitCall"}}}},"responses":{"200":{"description":"Successful response. call/wait wrap the result in data; export returns requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Success"}}},"headers":{"RateLimit-Policy":{"description":"Per-IP rolling request budget: 120 requests in 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"Remaining quota and seconds until the next slot is available.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Compatibility limit header.","schema":{"type":"string"}},"RateLimit-Remaining":{"description":"Compatibility remaining quota.","schema":{"type":"string"}},"RateLimit-Reset":{"description":"Seconds until the next slot is available.","schema":{"type":"string"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Invalid private token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Cross-origin request rejected","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Inbox expired or not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"413":{"description":"Request body exceeds limit","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate or inbox limit reached; honor Retry-After when present","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"Retry-After":{"description":"Seconds to wait for an HTTP rate limit; capacity errors may need cleanup or renewal instead.","schema":{"type":"integer"}}}},"405":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"description":"Use since=0 initially, then data.next_since after successful processing. Returns data.request (event or null), data.next_since, and data.timeout. This is an outbound long poll; it does not wake a stopped agent session."}},"/api/v1/export":{"post":{"operationId":"exportEventsV1","summary":"Stream all retained events with original body bytes","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportCall"}}}},"responses":{"200":{"description":"Successful response. call/wait wrap the result in data; export returns requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventExport"}}},"headers":{"RateLimit-Policy":{"description":"Per-IP rolling request budget: 120 requests in 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"Remaining quota and seconds until the next slot is available.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Compatibility limit header.","schema":{"type":"string"}},"RateLimit-Remaining":{"description":"Compatibility remaining quota.","schema":{"type":"string"}},"RateLimit-Reset":{"description":"Seconds until the next slot is available.","schema":{"type":"string"}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Invalid private token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Cross-origin request rejected","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Inbox expired or not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"413":{"description":"Request body exceeds limit","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate or inbox limit reached; honor Retry-After when present","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"Retry-After":{"description":"Seconds to wait for an HTTP rate limit; capacity errors may need cleanup or renewal instead.","schema":{"type":"integer"}}}},"405":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/tools":{"get":{"operationId":"listMcpToolsV1","summary":"Live MCP names and JSON input schemas","responses":{"200":{"description":"MCP tool catalog","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolCatalog"}}},"headers":{"RateLimit-Policy":{"description":"Per-IP rolling request budget: 120 requests in 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"Remaining quota and seconds until the next slot is available.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Compatibility limit header.","schema":{"type":"string"}},"RateLimit-Remaining":{"description":"Compatibility remaining quota.","schema":{"type":"string"}},"RateLimit-Reset":{"description":"Seconds until the next slot is available.","schema":{"type":"string"}}}},"400":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"405":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"413":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"Retry-After":{"description":"Seconds to wait for an HTTP rate limit; capacity errors may need cleanup or renewal instead.","schema":{"type":"integer"}}}},"500":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Request could not be completed; read resolution before retrying.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}}},"components":{"schemas":{"WebCall":{"properties":{"action":{"enum":["create","info","list","get","send","configure","export","links","delete","rotate","activity"],"title":"Action","type":"string"},"token":{"default":"","title":"Token","type":"string"},"request_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Request Id"},"page":{"default":1,"maximum":1000,"minimum":1,"title":"Page","type":"integer"},"since":{"default":0,"minimum":0,"title":"Since","type":"integer"},"limit":{"default":100,"maximum":1000,"minimum":1,"title":"Limit","type":"integer"},"payload":{"additionalProperties":true,"title":"Payload","type":"object"},"config":{"additionalProperties":true,"title":"Config","type":"object"}},"required":["action"],"title":"WebCall","type":"object"},"WaitCall":{"properties":{"token":{"title":"Token","type":"string"},"since":{"default":0,"minimum":0,"title":"Since","type":"integer"},"timeout_seconds":{"default":25,"exclusiveMinimum":0,"maximum":30,"title":"Timeout Seconds","type":"number"}},"required":["token"],"title":"WaitCall","type":"object"},"ExportCall":{"type":"object","required":["token"],"properties":{"token":{"type":"string"}}},"Problem":{"type":"object","required":["type","title","status","code","detail","resolution","success","message"],"properties":{"type":{"type":"string","format":"uri-reference"},"title":{"type":"string"},"status":{"type":"integer"},"code":{"type":"string"},"detail":{"type":"string"},"resolution":{"type":"string"},"success":{"const":false},"message":{"type":"string"}}},"Success":{"type":"object","required":["success","data"],"properties":{"success":{"const":true},"data":{"type":"object","additionalProperties":true}}},"EventExport":{"type":"object","required":["requests"],"properties":{"requests":{"type":"array","items":{"type":"object"}}}},"ToolCatalog":{"type":"object","required":["tools"],"properties":{"tools":{"type":"array","items":{"type":"object"}}}},"Health":{"type":"object","required":["status","product","version","storage","email","dns"],"properties":{"status":{"type":"string"},"product":{"type":"string"},"version":{"type":"string"},"storage":{"type":"string"},"email":{"type":"boolean"},"dns":{"type":"boolean"}}}}},"externalDocs":{"url":"https://openhook.dev/agents.md"}}