{"openapi":"3.1.0","jsonSchemaDialect":"https://json-schema.org/draft/2020-12/schema","info":{"title":"Relay API","version":"1.0.0","description":"Scoped REST API for programmable inbound email inboxes. Create inboxes, read messages, extract authentication artifacts, receive SSE events, and manage signed webhooks.","termsOfService":"https://www.relaymcp.net/terms","contact":{"url":"https://www.relaymcp.net"},"license":{"name":"Proprietary"}},"servers":[{"url":"https://www.relaymcp.net/api/v1","description":"Relay production API"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Domains","description":"Available mail domains."},{"name":"Inboxes","description":"Create and inspect inboxes."},{"name":"Messages","description":"List, read, and inspect received messages."},{"name":"Events","description":"Server-sent event stream."},{"name":"Webhooks","description":"Signed webhook endpoints and delivery history."}],"paths":{"/domains":{"get":{"tags":["Domains"],"operationId":"listDomains","summary":"List available Free mail domains","security":[{"bearerAuth":["inboxes:read"]}],"responses":{"200":{"description":"Available domains.","content":{"application/json":{"schema":{"type":"object","required":["domains"],"properties":{"domains":{"type":"array","items":{"$ref":"#/components/schemas/Domain"}}}},"examples":{"success":{"value":{"domains":[{"id":"domain_123","name":"mail.example.net","tier":"free"}]}}}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key does not have the required scope or access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The requested resource conflicts with an existing resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/inboxes":{"get":{"tags":["Inboxes"],"operationId":"listInboxes","summary":"List the authenticated account's inboxes","security":[{"bearerAuth":["inboxes:read"]}],"parameters":[{"name":"cursor","in":"query","description":"Cursor returned by the previous page.","required":false,"schema":{"type":"string","maxLength":64}}],"responses":{"200":{"description":"Cursor-paginated inboxes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboxPage"}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key does not have the required scope or access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The requested resource conflicts with an existing resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["Inboxes"],"operationId":"createInbox","summary":"Create an inbox","security":[{"bearerAuth":["inboxes:write"]}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateInboxRequest"},"examples":{"named":{"value":{"name":"build-checks","domain":"mail.example.net"}},"random":{"value":{}}}}}},"responses":{"201":{"description":"Created inbox.","content":{"application/json":{"schema":{"type":"object","required":["inbox"],"properties":{"inbox":{"$ref":"#/components/schemas/Inbox"}}}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key does not have the required scope or access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The requested resource conflicts with an existing resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"No active mail domain is available.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/inboxes/{inboxId}":{"get":{"tags":["Inboxes"],"operationId":"getInbox","summary":"Get inbox metadata","security":[{"bearerAuth":["inboxes:read"]}],"parameters":[{"name":"inboxId","in":"path","required":true,"description":"Inbox ID.","schema":{"type":"string","minLength":1,"maxLength":64}}],"responses":{"200":{"description":"Inbox metadata.","content":{"application/json":{"schema":{"type":"object","required":["inbox"],"properties":{"inbox":{"$ref":"#/components/schemas/Inbox"}}}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key does not have the required scope or access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The requested resource conflicts with an existing resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/inboxes/{inboxId}/messages":{"get":{"tags":["Messages"],"operationId":"listMessages","summary":"List message previews","security":[{"bearerAuth":["messages:read"]}],"parameters":[{"name":"inboxId","in":"path","required":true,"description":"Inbox ID.","schema":{"type":"string","minLength":1,"maxLength":64}},{"name":"limit","in":"query","description":"Number of messages to return.","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":30}},{"name":"cursor","in":"query","description":"Cursor returned by the previous page.","required":false,"schema":{"type":"string","maxLength":200}}],"responses":{"200":{"description":"Message preview page.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessagePage"}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key does not have the required scope or access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The requested resource conflicts with an existing resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/inboxes/{inboxId}/messages/{messageId}":{"get":{"tags":["Messages"],"operationId":"readMessage","summary":"Read a full message","security":[{"bearerAuth":["messages:read"]}],"parameters":[{"name":"inboxId","in":"path","required":true,"description":"Inbox ID.","schema":{"type":"string","minLength":1,"maxLength":64}},{"name":"messageId","in":"path","required":true,"description":"Message ID.","schema":{"type":"string","minLength":1,"maxLength":64}}],"responses":{"200":{"description":"Full message with sanitized HTML and attachment metadata.","content":{"application/json":{"schema":{"type":"object","required":["message"],"properties":{"message":{"$ref":"#/components/schemas/Message"}}}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key does not have the required scope or access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The requested resource conflicts with an existing resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/inboxes/{inboxId}/messages/{messageId}/otp":{"get":{"tags":["Messages"],"operationId":"extractOtp","summary":"Extract a one-time password","security":[{"bearerAuth":["messages:read"]}],"parameters":[{"name":"inboxId","in":"path","required":true,"description":"Inbox ID.","schema":{"type":"string","minLength":1,"maxLength":64}},{"name":"messageId","in":"path","required":true,"description":"Message ID.","schema":{"type":"string","minLength":1,"maxLength":64}}],"responses":{"200":{"description":"OTP extraction result.","content":{"application/json":{"schema":{"type":"object","required":["otp"],"properties":{"otp":{"$ref":"#/components/schemas/OtpResult"}}},"examples":{"found":{"value":{"otp":{"found":true,"ambiguous":false,"code":"482916","confidence":"high"}}}}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key does not have the required scope or access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The requested resource conflicts with an existing resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/inboxes/{inboxId}/messages/{messageId}/auth":{"get":{"tags":["Messages"],"operationId":"extractAuthArtifacts","summary":"Extract OTP and authentication links","security":[{"bearerAuth":["messages:read"]}],"parameters":[{"name":"inboxId","in":"path","required":true,"description":"Inbox ID.","schema":{"type":"string","minLength":1,"maxLength":64}},{"name":"messageId","in":"path","required":true,"description":"Message ID.","schema":{"type":"string","minLength":1,"maxLength":64}}],"responses":{"200":{"description":"Authentication artifact extraction result.","content":{"application/json":{"schema":{"type":"object","required":["auth"],"properties":{"auth":{"$ref":"#/components/schemas/AuthArtifacts"}}}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key does not have the required scope or access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The requested resource conflicts with an existing resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/inboxes/{inboxId}/attachments/{attachmentId}":{"get":{"tags":["Messages"],"operationId":"downloadAttachment","summary":"Download an attachment","security":[{"bearerAuth":["messages:read"]}],"parameters":[{"name":"inboxId","in":"path","required":true,"description":"Inbox ID.","schema":{"type":"string","minLength":1,"maxLength":64}},{"name":"attachmentId","in":"path","required":true,"description":"Attachment ID.","schema":{"type":"string","minLength":1,"maxLength":64}}],"responses":{"200":{"description":"Binary attachment.","headers":{"Content-Disposition":{"schema":{"type":"string"}}},"content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key does not have the required scope or access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The requested resource conflicts with an existing resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/events":{"get":{"tags":["Events"],"operationId":"streamEvents","summary":"Stream account events over SSE","description":"Connections last up to ten minutes and poll at five-second intervals while the client consumes events. Keys and scopes are revalidated per poll. At most three streams per account are allowed in each server process. Resume after disconnection using the last numeric event ID.","security":[{"bearerAuth":["events:read"]}],"parameters":[{"name":"after","in":"query","description":"Last event ID already received.","required":false,"schema":{"type":"integer","minimum":0,"default":0}},{"name":"limit","in":"query","description":"Upper bound per poll; responses may contain fewer events to respect server byte and batch limits.","required":false,"schema":{"type":"integer","minimum":1,"maximum":500,"default":100}}],"responses":{"200":{"description":"text/event-stream containing typed events and heartbeat events.","content":{"text/event-stream":{"schema":{"type":"string","examples":["id: 42\nevent: inbox.message.received\ndata: {\\\"inbox_id\\\":\\\"inbox_123\\\"}\n\n"]}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key does not have the required scope or access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The requested resource conflicts with an existing resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/webhooks":{"get":{"tags":["Webhooks"],"operationId":"listWebhooks","summary":"List webhook endpoints","security":[{"bearerAuth":["webhooks:read"]}],"responses":{"200":{"description":"Webhook endpoints. The signing secret is never returned after creation.","content":{"application/json":{"schema":{"type":"object","required":["webhooks"],"properties":{"webhooks":{"type":"array","items":{"$ref":"#/components/schemas/Webhook"}}}}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key does not have the required scope or access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The requested resource conflicts with an existing resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["Webhooks"],"operationId":"createWebhook","summary":"Create a signed webhook endpoint","security":[{"bearerAuth":["webhooks:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebhookRequest"},"examples":{"default":{"value":{"url":"https://hooks.example.com/relay","events":["inbox.message.received"]}}}}}},"responses":{"201":{"description":"Created webhook. Save the one-time secret.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedWebhook"}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key does not have the required scope or access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The requested resource conflicts with an existing resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/webhooks/{webhookId}":{"get":{"tags":["Webhooks"],"operationId":"listWebhookDeliveries","summary":"List webhook delivery history","security":[{"bearerAuth":["webhooks:read"]}],"parameters":[{"name":"webhookId","in":"path","required":true,"description":"Webhook ID.","schema":{"type":"string","minLength":1,"maxLength":64}}],"responses":{"200":{"description":"Recent deliveries.","content":{"application/json":{"schema":{"type":"object","required":["deliveries"],"properties":{"deliveries":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDelivery"}}}}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key does not have the required scope or access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The requested resource conflicts with an existing resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Webhooks"],"operationId":"deleteWebhook","summary":"Delete a webhook endpoint","security":[{"bearerAuth":["webhooks:write"]}],"parameters":[{"name":"webhookId","in":"path","required":true,"description":"Webhook ID.","schema":{"type":"string","minLength":1,"maxLength":64}}],"responses":{"200":{"description":"Webhook deleted.","content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"const":true}}}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key does not have the required scope or access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The requested resource conflicts with an existing resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"rl_live_...","description":"Create a key in Relay Account settings. Keys are shown once and never stored in plaintext."}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"string"},"code":{"type":"string","description":"Stable machine-readable code when available."}},"additionalProperties":false},"Domain":{"type":"object","required":["id","name","tier"],"properties":{"id":{"type":"string"},"name":{"type":"string","format":"hostname"},"tier":{"type":"string","const":"free"}},"additionalProperties":false},"Inbox":{"type":"object","required":["id","address","owned"],"properties":{"id":{"type":"string"},"address":{"type":"string","format":"email"},"owned":{"type":"boolean"}},"additionalProperties":false},"CreateInboxRequest":{"type":"object","properties":{"name":{"type":"string","minLength":4,"maxLength":32,"pattern":"^[a-z][a-z0-9._-]{3,31}$"},"domain":{"type":"string","format":"hostname","maxLength":253}},"additionalProperties":false},"InboxPage":{"type":"object","required":["inboxes","nextCursor"],"properties":{"inboxes":{"type":"array","items":{"$ref":"#/components/schemas/Inbox"}},"nextCursor":{"type":["string","null"]}}},"MessagePreview":{"type":"object","required":["id","subject","created","time"],"properties":{"id":{"type":"string"},"sender":{"type":["string","null"]},"sender_address":{"type":["string","null"]},"subject":{"type":["string","null"]},"preview":{"type":["string","null"]},"created":{"type":"integer","format":"int64"},"time":{"type":"string","format":"date-time"},"size_bytes":{"type":"integer"},"source":{"type":["string","null"]},"attachment_count":{"type":"integer"}}},"Message":{"allOf":[{"$ref":"#/components/schemas/MessagePreview"},{"type":"object","properties":{"recipient":{"type":["string","null"]},"body":{"type":["string","null"]},"html":{"type":["string","null"]},"message_id":{"type":["string","null"]},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/Attachment"}}}}]},"MessagePage":{"type":"object","required":["messages","nextCursor"],"properties":{"messages":{"type":"array","items":{"$ref":"#/components/schemas/MessagePreview"}},"nextCursor":{"type":["string","null"]}}},"Attachment":{"type":"object","required":["id","filename","content_type","size_bytes","sha256"],"properties":{"id":{"type":"string"},"filename":{"type":"string"},"content_type":{"type":"string"},"size_bytes":{"type":"integer"},"sha256":{"type":"string"}}},"OtpResult":{"type":"object","required":["found","ambiguous","code","confidence"],"properties":{"found":{"type":"boolean"},"ambiguous":{"type":"boolean"},"code":{"type":["string","null"]},"confidence":{"type":"string","enum":["none","low","medium","high"]}}},"AuthArtifacts":{"type":"object","required":["otp","links"],"properties":{"otp":{"$ref":"#/components/schemas/OtpResult"},"links":{"type":"array","items":{"type":"string","format":"uri"}},"magicLink":{"type":["string","null"],"description":"Primary HTTPS action link when one can be chosen without guessing. Null when there is no single safe link. Clients must not open it automatically."}}},"CreateWebhookRequest":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri","pattern":"^https://","maxLength":2048},"events":{"type":"array","items":{"type":"string"},"minItems":1}},"additionalProperties":false},"Webhook":{"type":"object","required":["id","url","events","active","created","updated"],"properties":{"id":{"type":"string"},"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"type":"string"}},"active":{"type":"boolean"},"created":{"type":"integer","format":"int64"},"updated":{"type":"integer","format":"int64"}}},"CreatedWebhook":{"allOf":[{"$ref":"#/components/schemas/Webhook"},{"type":"object","required":["secret"],"properties":{"secret":{"type":"string","description":"One-time signing secret. Store it securely."}}}]},"WebhookDelivery":{"type":"object","properties":{"id":{"type":"string"},"endpoint_id":{"type":"string"},"event_id":{"type":"integer"},"attempt":{"type":"integer"},"state":{"type":"string"},"next_attempt":{"type":["integer","null"]},"response_status":{"type":["integer","null"]},"last_error":{"type":["string","null"]},"created":{"type":"integer"},"delivered":{"type":["integer","null"]}}}}},"externalDocs":{"description":"Relay developer documentation","url":"https://www.relaymcp.net/docs"}}