{"openapi":"3.1.0","info":{"title":"OVEYON API","version":"1.0.0","summary":"Transactional email: send by API, receive by signed webhook.","description":"Transactional email infrastructure with both directions over HTTP. API-key (Bearer) authentication with scopes; errors with a stable `error` and a localized `message`; 429 with Retry-After; sandbox with `X-Oveyon-Sandbox: 1`; idempotency with `Idempotency-Key`. Webhooks signed with HMAC-SHA256 (see `webhooks`).","contact":{"name":"Oveyon support","email":"support@oveyon.com","url":"https://oveyon.com/support"},"termsOfService":"https://oveyon.com/terms"},"externalDocs":{"description":"Human-readable reference","url":"https://api.oveyon.com/docs"},"servers":[{"url":"https://api.oveyon.com/v1"}],"tags":[{"name":"Meta"},{"name":"Sending"},{"name":"Messages"},{"name":"Utilities"},{"name":"Inbound"},{"name":"Suppressions"},{"name":"Domains"},{"name":"Webhooks"},{"name":"Allow/Block lists"},{"name":"IP rules"},{"name":"Templates"},{"name":"Send policies"},{"name":"NPS/CSAT surveys"}],"paths":{"/ping":{"get":{"operationId":"get_ping","tags":["Meta"],"summary":"Ping","description":"Shallow: 200 if the API answers. Public. For external health checks.","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"service":{"type":"string"},"version":{"type":"string"}}},"example":{"ok":true,"service":"oveyon","version":"v1"}}}}},"security":[]}},"/openapi.json":{"get":{"operationId":"get_openapi_json","tags":["Meta"],"summary":"This document","description":"The OpenAPI 3.1 of this API, generated from the code. Public.","responses":{"200":{"description":"OpenAPI 3.1","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[]}},"/send":{"post":{"operationId":"post_send","tags":["Sending"],"summary":"Send a message","description":"Queues a message for up to 5 recipients (to + cc + bcc). Each recipient is one quota unit. `Idempotency-Key` (header) or `idempotencyKey` (body) deduplicates safely; `X-Oveyon-Sandbox: 1` accepts and freezes without delivering. On a 500, only retry with an idempotencyKey.","parameters":[{"name":"Idempotency-Key","in":"header","schema":{"type":"string"}},{"name":"X-Oveyon-Sandbox","in":"header","schema":{"type":"string","enum":["1"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendRequest"},"example":{"from":"agent@yourdomain.com","to":"customer@example.com","subject":"Your order 8812 is on its way","text":"Hi — it shipped today."}}}},"responses":{"200":{"description":"Duplicate: the idempotencyKey was already used; returns the original id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendResponse"}}}},"202":{"description":"Accepted (`accepted`) or frozen in sandbox (`sandbox`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendResponse"},"example":{"id":"3f8a1c2e-9b4d-4e10-8a77-2b0c9d5e1f34","status":"accepted"}}}},"400":{"description":"bad_request, too_many_recipients, bad_recipient, too_many_attachments, bad_attachment, template_conflict, template_var_missing.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Stable code to branch on (never compare `message`: it is localized by the caller’s country)."},"message":{"type":"string"}},"additionalProperties":true}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"413":{"description":"attachments_too_large (> 15 MB).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Stable code to branch on (never compare `message`: it is localized by the caller’s country)."},"message":{"type":"string"}},"additionalProperties":true}}}},"422":{"description":"domain_not_verified, invalid_recipient_domain, recipient_suppressed, recipient_blocked, recipient_not_allowed, policy_refused, unsub_footer_multi_recipient, template_not_found and template render errors.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Stable code to branch on (never compare `message`: it is localized by the caller’s country)."},"message":{"type":"string"}},"additionalProperties":true}}}},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"send"}},"/messages":{"get":{"operationId":"get_messages","tags":["Messages"],"summary":"List sent messages","parameters":[{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/cursor"},{"name":"status","in":"query","schema":{"type":"string","enum":["accepted","queued","delivered","deferred","bounced","suppressed","failed","frozen"]}},{"name":"outcome","in":"query","schema":{"type":"string","enum":["devolvidas","bloqueadas","fila","held","entregues"]},"description":"Grouped outcome (the dashboard’s five cuts)."},{"name":"recipient","in":"query","schema":{"type":"string"},"description":"Exact address, in to/cc/bcc."},{"name":"domain","in":"query","schema":{"type":"string"},"description":"Numeric id or name."},{"name":"credential","in":"query","schema":{"type":"integer"}},{"$ref":"#/components/parameters/from"},{"$ref":"#/components/parameters/to"},{"name":"event","in":"query","schema":{"type":"string"},"description":"Filter by a timeline event (e.g. opened)."}],"responses":{"200":{"description":"Page","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageList"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"read:messages"}},"/messages/{uuid}":{"get":{"operationId":"get_messages_uuid","tags":["Messages"],"summary":"Message detail and timeline","parameters":[{"name":"uuid","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Message","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageDetail"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"read:messages"}},"/stats":{"get":{"operationId":"get_stats","tags":["Messages"],"summary":"Aggregate statistics","parameters":[{"name":"group_by","in":"query","schema":{"type":"string","enum":["day","domain","credential"],"default":"day"}},{"$ref":"#/components/parameters/from"},{"$ref":"#/components/parameters/to"},{"name":"breakdown","in":"query","schema":{"type":"string"},"description":"`provider`, `reason` and/or `credential`, comma-separated."}],"responses":{"200":{"description":"Series and rates","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Stats"}}}},"400":{"description":"bad_breakdown, bad_date","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Stable code to branch on (never compare `message`: it is localized by the caller’s country)."},"message":{"type":"string"}},"additionalProperties":true}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"read:stats"}},"/disposable":{"get":{"operationId":"get_disposable","tags":["Utilities"],"summary":"Is the domain disposable?","description":"Public (no key). Only the domain against our list, refreshed daily; does not check whether the mailbox exists. Per-IP cap: 60/h.","parameters":[{"name":"email","in":"query","schema":{"type":"string"}},{"name":"domain","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisposableCheck"},"example":{"domain":"mailinator.com","result":"disposable","disposable":true,"list":{"updatedAt":"2026-08-27T03:00:00Z","domains":118000}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"description":"List unavailable — `result: \"unknown\"`.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Stable code to branch on (never compare `message`: it is localized by the caller’s country)."},"message":{"type":"string"}},"additionalProperties":true}}}}},"security":[]}},"/inbound":{"get":{"operationId":"get_inbound","tags":["Inbound"],"summary":"List received emails","parameters":[{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/cursor"},{"name":"recipient","in":"query","schema":{"type":"string"}},{"name":"sender","in":"query","schema":{"type":"string"},"description":"Matches envelope and header."},{"name":"domain","in":"query","schema":{"type":"string"}},{"name":"dmarc","in":"query","schema":{"type":"string"}},{"name":"has_attachments","in":"query","schema":{"type":"boolean"}},{"name":"outcome","in":"query","schema":{"type":"string"}},{"$ref":"#/components/parameters/from"},{"$ref":"#/components/parameters/to"}],"responses":{"200":{"description":"Page","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboundList"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"read:inbound"}},"/inbound/{uid}":{"get":{"operationId":"get_inbound_uid","tags":["Inbound"],"summary":"Received email detail","parameters":[{"name":"uid","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Message with attachment manifest and links","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboundDetail"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"read:inbound"}},"/inbound/{uid}/content":{"get":{"operationId":"get_inbound_uid_content","tags":["Inbound"],"summary":"Parsed body (text/html)","parameters":[{"name":"uid","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Body, cut at 256 KB per field","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboundContent"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"read:inbound"}},"/inbound/{uid}/raw":{"get":{"operationId":"get_inbound_uid_raw","tags":["Inbound"],"summary":"The original .eml","parameters":[{"name":"uid","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"message/rfc822, byte for byte","content":{"message/rfc822":{"schema":{"type":"string","format":"binary"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"read:inbound"}},"/inbound/{uid}/attachments/{n}":{"get":{"operationId":"get_inbound_uid_attachments_n","tags":["Inbound"],"summary":"Attachment bytes","parameters":[{"name":"uid","in":"path","required":true,"schema":{"type":"string"}},{"name":"n","in":"path","required":true,"schema":{"type":"integer"},"description":"The manifest `ord`, not the file name."}],"responses":{"200":{"description":"The attachment","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"read:inbound"}},"/suppressions":{"get":{"operationId":"get_suppressions","tags":["Suppressions"],"summary":"List suppressions","parameters":[{"name":"email","in":"query","schema":{"type":"string"},"description":"Substring match."},{"name":"reason","in":"query","schema":{"type":"string","enum":["hard_bounce","complaint","manual","unsubscribe"]}},{"name":"limit","in":"query","schema":{"type":"integer","maximum":500,"default":100}},{"name":"offset","in":"query","schema":{"type":"integer"}}],"responses":{"200":{"description":"List","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuppressionList"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"read:suppressions"},"post":{"operationId":"post_suppressions","tags":["Suppressions"],"summary":"Suppress an address","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email"],"properties":{"email":{"type":"string","format":"email"},"reason":{"type":"string","enum":["manual","unsubscribe"]}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Suppression"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"write:suppressions"}},"/suppressions/{email}":{"delete":{"operationId":"delete_suppressions_email","tags":["Suppressions"],"summary":"Remove a suppression","description":"A complaint (`complaint`) can never be removed — not even here.","parameters":[{"name":"email","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Removed","content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"write:suppressions"}},"/domains":{"get":{"operationId":"get_domains","tags":["Domains"],"summary":"List sending domains","responses":{"200":{"description":"List","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"read:domains"},"post":{"operationId":"post_domains","tags":["Domains"],"summary":"Add a domain","description":"Returns the DNS records to publish (SPF, DKIM, DMARC). On the Free plan the domain goes through reputation screening; refusal = 403 domain_not_allowed_free, without a reason (on purpose).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["domain"],"properties":{"domain":{"type":"string"}}}}}},"responses":{"201":{"description":"Created, with the records","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Domain"}}}},"400":{"description":"bad_domain","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Stable code to branch on (never compare `message`: it is localized by the caller’s country)."},"message":{"type":"string"}},"additionalProperties":true}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"description":"domain_exists (already yours) or domain_taken (belongs to another account).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Stable code to branch on (never compare `message`: it is localized by the caller’s country)."},"message":{"type":"string"}},"additionalProperties":true}}}},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"write:domains"}},"/domains/{id}/verify":{"post":{"operationId":"post_domains_id_verify","tags":["Domains"],"summary":"Verify DNS live","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Result per check; `inconclusive` when the resolver did not answer (previous state preserved).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Domain"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"write:domains"}},"/webhooks":{"get":{"operationId":"get_webhooks","tags":["Webhooks"],"summary":"List delivery webhooks","responses":{"200":{"description":"List","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Webhook"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"manage:webhooks"},"post":{"operationId":"post_webhooks","tags":["Webhooks"],"summary":"Create a delivery webhook","description":"Events: delivered, bounced, opened, clicked, complained, blocked. The `secret` is shown once. Every POST carries x-oveyon-event, x-oveyon-timestamp and x-oveyon-signature (sha256=HMAC-SHA256(secret, timestamp + \".\" + body)). Internal/private destinations are refused.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url","events"],"properties":{"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"type":"string"}},"credential":{"type":"object","properties":{"type":{"type":"string","enum":["smtp","api"]},"id":{"type":"integer"}}}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookCreated"}}}},"400":{"description":"bad_request, bad_events, unsafe_url","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Stable code to branch on (never compare `message`: it is localized by the caller’s country)."},"message":{"type":"string"}},"additionalProperties":true}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"manage:webhooks"}},"/webhooks/{id}":{"patch":{"operationId":"patch_webhooks_id","tags":["Webhooks"],"summary":"Update a webhook","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"active":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Webhook"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"manage:webhooks"},"post":{"operationId":"post_webhooks_id","tags":["Webhooks"],"summary":"Update a webhook (alias of PATCH)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Webhook"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"manage:webhooks"},"delete":{"operationId":"delete_webhooks_id","tags":["Webhooks"],"summary":"Delete a webhook","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"type":"integer"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"manage:webhooks"}},"/policies":{"get":{"operationId":"get_policies","tags":["Allow/Block lists"],"summary":"List allow/block entries","parameters":[{"name":"limit","in":"query","schema":{"type":"integer"}},{"name":"offset","in":"query","schema":{"type":"integer"}}],"responses":{"200":{"description":"List (a paused entry is still listed and does not apply).","content":{"application/json":{"schema":{"type":"object","properties":{"policies":{"type":"array","items":{"$ref":"#/components/schemas/ListEntry"}},"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"read:policies"},"post":{"operationId":"post_policies","tags":["Allow/Block lists"],"summary":"Create an allow/block entry","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["scope","kind","pattern"],"properties":{"scope":{"type":"string","enum":["allow","block"]},"kind":{"type":"string"},"pattern":{"type":"string"},"domainId":{"type":"integer"},"credentialType":{"type":"string","enum":["smtp","apiKey"]},"credentialId":{"type":"integer"}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListEntry"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"description":"policy_exists","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Stable code to branch on (never compare `message`: it is localized by the caller’s country)."},"message":{"type":"string"}},"additionalProperties":true}}}},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"write:policies"}},"/policies/{id}":{"delete":{"operationId":"delete_policies_id","tags":["Allow/Block lists"],"summary":"Delete an entry","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Removed","content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"type":"integer"},"pattern":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"write:policies"}},"/credentials/ip-rules":{"get":{"operationId":"get_credentials_ip_rules","tags":["IP rules"],"summary":"List CIDRs per credential","responses":{"200":{"description":"Rules (with paused/pausedAt)","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"read:policies"},"post":{"operationId":"post_credentials_ip_rules","tags":["IP rules"],"summary":"Allow a CIDR for a credential","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["credentialType","credentialId","cidr"],"properties":{"credentialType":{"type":"string","enum":["smtp","apiKey"]},"credentialId":{"type":"integer"},"cidr":{"type":"string"}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IpRule"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"write:policies"}},"/credentials/ip-rules/{id}":{"delete":{"operationId":"delete_credentials_ip_rules_id","tags":["IP rules"],"summary":"Remove a CIDR","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Removed","content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"type":"integer"},"cidr":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"write:policies"}},"/credentials/ip-rules/pause":{"post":{"operationId":"post_credentials_ip_rules_pause","tags":["IP rules"],"summary":"Pause a credential’s IP fence","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["credentialType","credentialId"],"properties":{"credentialType":{"type":"string","enum":["smtp","apiKey"]},"credentialId":{"type":"integer"}}}}}},"responses":{"200":{"description":"Paused — authenticates from any IP; the ranges stay registered.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"write:policies"}},"/credentials/ip-rules/unpause":{"post":{"operationId":"post_credentials_ip_rules_unpause","tags":["IP rules"],"summary":"Re-enable the fence","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["credentialType","credentialId"],"properties":{"credentialType":{"type":"string","enum":["smtp","apiKey"]},"credentialId":{"type":"integer"}}}}}},"responses":{"200":{"description":"Re-enabled; may carry `warning.uncoveredRecentIps`.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"write:policies"}},"/templates":{"get":{"operationId":"get_templates","tags":["Templates"],"summary":"List templates","responses":{"200":{"description":"List","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"read:templates"},"post":{"operationId":"post_templates","tags":["Templates"],"summary":"Create a template (draft v1)","description":"Closed syntax: `{{var}}`, `{{{var}}}`, `{{#each}}`, `| \"default\"`. Helpers, partials and comments are refused (400 template_parse_error).","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Template"}}}},"400":{"description":"template_invalid, template_parse_error, template_source_too_large","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Stable code to branch on (never compare `message`: it is localized by the caller’s country)."},"message":{"type":"string"}},"additionalProperties":true}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"write:templates"}},"/templates/{ref}":{"get":{"operationId":"get_templates_ref","tags":["Templates"],"summary":"A template with all its versions","parameters":[{"name":"ref","in":"path","required":true,"schema":{"type":"string"},"description":"Numeric id or `name`."}],"responses":{"200":{"description":"Template","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Template"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"template_not_found","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Stable code to branch on (never compare `message`: it is localized by the caller’s country)."},"message":{"type":"string"}},"additionalProperties":true}}}},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"read:templates"},"put":{"operationId":"put_templates_ref","tags":["Templates"],"summary":"New version (draft)","parameters":[{"name":"ref","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateInput"}}}},"responses":{"200":{"description":"Draft saved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Template"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"template_not_found","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Stable code to branch on (never compare `message`: it is localized by the caller’s country)."},"message":{"type":"string"}},"additionalProperties":true}}}},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"write:templates"},"delete":{"operationId":"delete_templates_ref","tags":["Templates"],"summary":"Delete a template","parameters":[{"name":"ref","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"type":"integer"},"name":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"template_not_found","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Stable code to branch on (never compare `message`: it is localized by the caller’s country)."},"message":{"type":"string"}},"additionalProperties":true}}}},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"write:templates"}},"/templates/{ref}/publish":{"post":{"operationId":"post_templates_ref_publish","tags":["Templates"],"summary":"Publish a version","description":"No body: publishes the newest draft. `{\"version\": N}`: makes that version current (rollback included).","parameters":[{"name":"ref","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"version":{"type":"integer","minimum":1}}}}}},"responses":{"200":{"description":"Published","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Template"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"template_not_found","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Stable code to branch on (never compare `message`: it is localized by the caller’s country)."},"message":{"type":"string"}},"additionalProperties":true}}}},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"write:templates"}},"/send-policies":{"get":{"operationId":"get_send_policies","tags":["Send policies"],"summary":"List policies in evaluation order","responses":{"200":{"description":"All (cap 50), including paused","content":{"application/json":{"schema":{"type":"object","properties":{"policies":{"type":"array","items":{"$ref":"#/components/schemas/SendPolicy"}},"total":{"type":"integer"},"max":{"type":"integer"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"read:send-policies"},"post":{"operationId":"post_send_policies","tags":["Send policies"],"summary":"Create a policy (born paused, last in order)","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendPolicyInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendPolicy"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"write:send-policies"}},"/send-policies/decisions":{"get":{"operationId":"get_send_policies_decisions","tags":["Send policies"],"summary":"What the policies decided","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}},{"name":"before","in":"query","schema":{"type":"integer"},"description":"The `id` of the last row of the previous page (the response carries `nextBefore`)."}],"responses":{"200":{"description":"Decisions, newest first","content":{"application/json":{"schema":{"type":"object","properties":{"decisions":{"type":"array","items":{"$ref":"#/components/schemas/Decision"}},"nextBefore":{"type":["integer","null"]}},"additionalProperties":true}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"read:send-policies"}},"/send-policies/{id}":{"get":{"operationId":"get_send_policies_id","tags":["Send policies"],"summary":"One policy","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Policy","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendPolicy"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"read:send-policies"},"put":{"operationId":"put_send_policies_id","tags":["Send policies"],"summary":"Replace a whole policy","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendPolicyInput"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendPolicy"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"write:send-policies"},"delete":{"operationId":"delete_send_policies_id","tags":["Send policies"],"summary":"Delete a policy","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Removed","content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"type":"integer"},"name":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"write:send-policies"}},"/send-policies/{id}/pause":{"post":{"operationId":"post_send_policies_id_pause","tags":["Send policies"],"summary":"Pause","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Paused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendPolicy"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"write:send-policies"}},"/send-policies/{id}/unpause":{"post":{"operationId":"post_send_policies_id_unpause","tags":["Send policies"],"summary":"Activate","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Active","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendPolicy"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"write:send-policies"}},"/send-policies/reorder":{"post":{"operationId":"post_send_policies_reorder","tags":["Send policies"],"summary":"Reorder","description":"Foreign ids are ignored; missing ones go to the end in their previous order.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["order"],"properties":{"order":{"type":"array","items":{"type":"integer"}}}}}}},"responses":{"200":{"description":"New order","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"write:send-policies"}},"/surveys":{"get":{"operationId":"get_surveys","tags":["NPS/CSAT surveys"],"summary":"List surveys","responses":{"200":{"description":"List","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"read:surveys"},"post":{"operationId":"post_surveys","tags":["NPS/CSAT surveys"],"summary":"Create a survey","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SurveyInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Survey"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"write:surveys"}},"/surveys/{id}":{"get":{"operationId":"get_surveys_id","tags":["NPS/CSAT surveys"],"summary":"One survey with its rollup","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Survey + rollup (media, distribuicao, nps, range)","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"read:surveys"},"put":{"operationId":"put_surveys_id","tags":["NPS/CSAT surveys"],"summary":"Replace a survey (kind is ignored)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SurveyInput"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Survey"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"write:surveys"},"delete":{"operationId":"delete_surveys_id","tags":["NPS/CSAT surveys"],"summary":"Delete a survey and its responses","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Deleted; `responsesDeleted` says how many responses went with it.","content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"type":"integer"},"name":{"type":"string"},"responsesDeleted":{"type":"integer"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"write:surveys"}},"/surveys/{id}/responses":{"get":{"operationId":"get_surveys_id_responses","tags":["NPS/CSAT surveys"],"summary":"Responses (cursor)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/cursor"}],"responses":{"200":{"description":"Page; each item is the response’s current state (key by sendId).","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SurveyResponse"}},"next_cursor":{"type":["string","null"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"read:surveys"}},"/surveys/{id}/send":{"post":{"operationId":"post_surveys_id_send","tags":["NPS/CSAT surveys"],"summary":"Send to one recipient","description":"The score is the click in the email. Anti-fatigue: the same recipient is surveyed once per account window (429 recipient_recently_surveyed, with a Retry-After that may be weeks).","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["to"],"properties":{"to":{"type":"string","format":"email"},"meta":{"type":"object","additionalProperties":true,"description":"Your context (≤ 4 KB); comes back in the webhook and in the responses."},"idempotencyKey":{"type":"string"}}}}}},"responses":{"200":{"description":"Duplicate (idempotencyKey)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendResponse"}}}},"202":{"description":"Sent","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"bearer":[]}],"x-oveyon-scope":"send:surveys"}}},"webhooks":{"deliveryEvent":{"post":{"summary":"Delivery event (delivered, bounced, opened, clicked, complained, blocked)","parameters":[{"name":"x-oveyon-event","in":"header","required":true,"schema":{"type":"string"}},{"name":"x-oveyon-timestamp","in":"header","required":true,"schema":{"type":"integer"},"description":"Epoch seconds. Reject if |now − timestamp| > 300 s."},{"name":"x-oveyon-signature","in":"header","required":true,"schema":{"type":"string"},"description":"`sha256=` + HMAC-SHA256(secret, timestamp + \".\" + raw body)."}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"event":{"type":"string"},"id":{"type":"string"},"timestamp":{"type":"string","format":"date-time"}},"additionalProperties":true}}}},"responses":{"200":{"description":"Any 2xx within 10 s counts as delivered; 3xx/4xx/5xx/timeout go to retry (6 attempts)."}}}},"inbound.received":{"post":{"summary":"Email received (per recipient; stable eventId for deduplication)","parameters":[{"name":"x-oveyon-event","in":"header","required":true,"schema":{"type":"string"}},{"name":"x-oveyon-timestamp","in":"header","required":true,"schema":{"type":"integer"},"description":"Epoch seconds. Reject if |now − timestamp| > 300 s."},{"name":"x-oveyon-signature","in":"header","required":true,"schema":{"type":"string"},"description":"`sha256=` + HMAC-SHA256(secret, timestamp + \".\" + raw body)."}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"event":{"type":"string","const":"inbound.received"},"eventId":{"type":"string","format":"uuid"},"schemaVersion":{"type":"integer"},"timestamp":{"type":"string","format":"date-time"},"message":{"$ref":"#/components/schemas/InboundMessage"},"recipient":{"type":"object","properties":{"id":{"type":"string"},"to":{"type":"string"}}},"attachments":{"type":"array","items":{"type":"object","additionalProperties":true}},"truncation":{"type":"object","properties":{"degraded":{"type":"boolean"},"requestedMode":{"type":"string"},"mode":{"type":"string"},"reason":{"type":["string","null"]},"maxBytes":{"type":"integer"}},"additionalProperties":true}},"additionalProperties":true}}}},"responses":{"200":{"description":"Answer 2xx fast; do the heavy work afterwards."}}}},"url_verification":{"post":{"summary":"Challenge before an inbound webhook URL is saved","parameters":[{"name":"x-oveyon-event","in":"header","required":true,"schema":{"type":"string"}},{"name":"x-oveyon-timestamp","in":"header","required":true,"schema":{"type":"integer"},"description":"Epoch seconds. Reject if |now − timestamp| > 300 s."},{"name":"x-oveyon-signature","in":"header","required":true,"schema":{"type":"string"},"description":"`sha256=` + HMAC-SHA256(secret, timestamp + \".\" + raw body)."}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string","const":"url_verification"},"challenge":{"type":"string"},"url":{"type":"string"},"sentAt":{"type":"string","format":"date-time"}}}}}},"responses":{"200":{"description":"Echo the `challenge` value with a 2xx (an empty body does NOT pass). Timeout 10 s."}}}},"survey.response":{"post":{"summary":"Survey response (current state; may arrive more than once per response — key by sendId)","parameters":[{"name":"x-oveyon-event","in":"header","required":true,"schema":{"type":"string"}},{"name":"x-oveyon-timestamp","in":"header","required":true,"schema":{"type":"integer"},"description":"Epoch seconds. Reject if |now − timestamp| > 300 s."},{"name":"x-oveyon-signature","in":"header","required":true,"schema":{"type":"string"},"description":"`sha256=` + HMAC-SHA256(secret, timestamp + \".\" + raw body)."}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"event":{"type":"string","const":"survey.response"},"surveyId":{"type":"integer"},"surveyName":{"type":"string"},"kind":{"type":"string"},"sendId":{"type":"string"},"recipient":{"type":"string"},"score":{"type":"integer"},"comment":{"type":["string","null"]},"updated":{"type":"boolean"},"meta":{"type":"object","additionalProperties":true},"messageId":{"type":"string"},"timestamp":{"type":"string","format":"date-time"}},"additionalProperties":true}}}},"responses":{"200":{"description":"2xx."}}}}},"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"Account API key: `Authorization: Bearer <key>`. Each key carries scopes; the scope an operation requires is in `x-oveyon-scope`."}},"parameters":{"limit":{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},"cursor":{"name":"cursor","in":"query","schema":{"type":"string"},"description":"The `next_cursor` of the previous page. Cursors from different routes are not interchangeable (400 bad_cursor)."},"from":{"name":"from","in":"query","schema":{"type":"string"},"description":"Start of the range, ISO 8601 (YYYY-MM-DD or timestamp)."},"to":{"name":"to","in":"query","schema":{"type":"string"},"description":"End of the range, ISO 8601."}},"headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until you may retry."}},"responses":{"Unauthorized":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Stable code to branch on (never compare `message`: it is localized by the caller’s country)."},"message":{"type":"string"}},"additionalProperties":true},"example":{"error":"unauthorized"}}}},"Forbidden":{"description":"Insufficient scope (`insufficient_scope`, with `required` and `have`), API key switched off by its owner in the panel (`key_disabled` — the key is valid; turn it back on or use another one, do not rotate), sending disabled, account suspended (`account_suspended`) or unknown (`account_unknown`). 403 is not a limit: do not retry.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Stable code to branch on (never compare `message`: it is localized by the caller’s country)."},"message":{"type":"string"}},"additionalProperties":true},"example":{"error":"insufficient_scope","required":"send","have":["read:messages"]}}}},"NotFound":{"description":"Does not exist, belongs to another account, or the identifier is malformed — the response is identical in all three cases, on purpose.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Stable code to branch on (never compare `message`: it is localized by the caller’s country)."},"message":{"type":"string"}},"additionalProperties":true},"example":{"error":"not_found"}}}},"RateLimited":{"description":"Per-IP limit, account quota (`quota_exceeded` with `window`, `used`, `limit`), warmup cap (`warmup_cap_reached`) or saturation (`queue_full`). Honor `Retry-After` with exponential backoff and jitter.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Stable code to branch on (never compare `message`: it is localized by the caller’s country)."},"message":{"type":"string"}},"additionalProperties":true},"example":{"error":"rate_limited","retryAfter":60}}}},"BadRequest":{"description":"Invalid request — fix it before retrying.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Stable code to branch on (never compare `message`: it is localized by the caller’s country)."},"message":{"type":"string"}},"additionalProperties":true},"example":{"error":"bad_request"}}}}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Stable code to branch on (never compare `message`: it is localized by the caller’s country)."},"message":{"type":"string"}},"additionalProperties":true},"Attachment":{"type":"object","required":["filename","content"],"properties":{"filename":{"type":"string"},"content":{"type":"string","description":"Base64-encoded content."},"contentType":{"type":"string"}}},"SendRequest":{"type":"object","required":["from","to"],"properties":{"from":{"type":"string","description":"`a@b.com` or `Name <a@b.com>`; the domain must be verified in the account."},"to":{"oneOf":[{"type":"string","format":"email"},{"type":"array","items":{"type":"string","format":"email"}}],"description":"One address or a list. `\"Name <a@b.com>\"` is accepted too."},"cc":{"oneOf":[{"type":"string","format":"email"},{"type":"array","items":{"type":"string","format":"email"}}],"description":"One address or a list. `\"Name <a@b.com>\"` is accepted too."},"bcc":{"oneOf":[{"type":"string","format":"email"},{"type":"array","items":{"type":"string","format":"email"}}],"description":"One address or a list. `\"Name <a@b.com>\"` is accepted too."},"subject":{"type":"string","maxLength":500},"html":{"type":"string"},"text":{"type":"string","description":"At least one of `html`/`text` is required — unless `templateId` is used."},"templateId":{"oneOf":[{"type":"integer"},{"type":"string"}],"description":"Numeric id or `name` of a published template. Mutually exclusive with subject/html/text."},"data":{"type":"object","additionalProperties":true,"description":"Template variables."},"version":{"type":"integer","minimum":1,"description":"Pins a published template version."},"headers":{"type":"object","additionalProperties":{"type":"string"},"description":"Extra headers. List-Unsubscribe, X-Report-Abuse and X-Oveyon-* are ignored."},"idempotencyKey":{"type":"string","description":"The same key never produces two messages (alternative to the Idempotency-Key header)."},"attachments":{"type":"array","maxItems":20,"items":{"$ref":"#/components/schemas/Attachment"},"description":"Up to 20 attachments, ≤ 15 MB in total."},"sandbox":{"type":"boolean","description":"true accepts and freezes without delivering (or header X-Oveyon-Sandbox: 1)."}}},"SendResponse":{"type":"object","required":["id","status"],"properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["accepted","sandbox","duplicate"]},"recipients":{"type":"integer","description":"Present only when there is more than one distinct address."}}},"Message":{"type":"object","properties":{"id":{"type":"string"},"from":{"type":"string"},"to":{"type":"string"},"subject":{"type":"string"},"status":{"type":"string","enum":["accepted","queued","delivered","deferred","bounced","suppressed","failed","frozen"]},"statusDetail":{"type":["string","null"]},"route":{"type":"string"},"acceptedAt":{"type":"string","format":"date-time"},"deliveredAt":{"type":["string","null"],"format":"date-time"},"templateId":{"type":["integer","null"]},"templateVersion":{"type":["integer","null"]}},"additionalProperties":true},"MessageDetail":{"allOf":[{"$ref":"#/components/schemas/Message"},{"type":"object","properties":{"sizeBytes":{"type":"integer"},"deliveries":{"type":"array","items":{"type":"object","additionalProperties":true}},"events":{"type":"array","items":{"type":"object","additionalProperties":true}},"tracking":{"type":"object","additionalProperties":true}}}]},"MessageList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Message"}},"next_cursor":{"type":["string","null"]}}},"Stats":{"type":"object","properties":{"series":{"type":"array","items":{"type":"object","additionalProperties":true}},"rates":{"type":"object","additionalProperties":true},"breakdown":{"type":"object","additionalProperties":true}},"additionalProperties":true},"DisposableCheck":{"type":"object","properties":{"domain":{"type":"string"},"result":{"type":"string","enum":["disposable","not_listed","unknown"]},"disposable":{"type":["boolean","null"]},"list":{"type":"object","properties":{"updatedAt":{"type":"string"},"domains":{"type":"integer"},"source":{"type":"string"}}}}},"Authentication":{"type":"object","properties":{"spf":{"type":"string"},"dkim":{"type":"string"},"dmarc":{"type":"string"}}},"InboundMessage":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"receivedAt":{"type":"string","format":"date-time"},"from":{"type":"string"},"fromHeader":{"type":"string"},"fromName":{"type":["string","null"]},"subject":{"type":"string"},"domain":{"type":"string"},"recipients":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"to":{"type":"string"}},"additionalProperties":true}},"authentication":{"$ref":"#/components/schemas/Authentication"},"spamScore":{"type":["integer","null"],"minimum":0,"maximum":100},"sizeBytes":{"type":"integer"},"attachmentCount":{"type":"integer"},"expiresAt":{"type":["string","null"],"format":"date-time"},"outcome":{"type":"string","description":"`accepted` or `blocked` — branch on this, never on blockedReason."},"blockedReason":{"type":["string","null"]}},"additionalProperties":true},"InboundList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/InboundMessage"}},"next_cursor":{"type":["string","null"]}}},"InboundDetail":{"allOf":[{"$ref":"#/components/schemas/InboundMessage"},{"type":"object","properties":{"attachments":{"type":"array","items":{"type":"object","properties":{"ord":{"type":"integer"},"filename":{"type":"string"},"contentType":{"type":"string"},"sizeBytes":{"type":"integer"},"sha256":{"type":"string"},"url":{"type":"string"}}}},"links":{"type":"object","properties":{"self":{"type":"string"},"content":{"type":"string"},"raw":{"type":"string"}}}}}]},"InboundContent":{"type":"object","properties":{"id":{"type":"string"},"text":{"type":["string","null"]},"html":{"type":["string","null"],"description":"Third-party HTML — sanitize before rendering."},"truncated":{"type":"boolean"}}},"Suppression":{"type":"object","properties":{"email":{"type":"string"},"reason":{"type":"string","enum":["hard_bounce","complaint","manual","unsubscribe"]},"source":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}},"additionalProperties":true},"SuppressionList":{"type":"object","properties":{"suppressions":{"type":"array","items":{"$ref":"#/components/schemas/Suppression"}},"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"}}},"ListEntry":{"type":"object","properties":{"id":{"type":"integer"},"scope":{"type":"string","enum":["allow","block"]},"kind":{"type":"string"},"pattern":{"type":"string"},"domainId":{"type":["integer","null"]},"credentialType":{"type":["string","null"],"enum":["smtp","apiKey",null]},"credentialId":{"type":["integer","null"]},"paused":{"type":"boolean"},"pausedAt":{"type":["string","null"]}},"additionalProperties":true},"IpRule":{"type":"object","properties":{"id":{"type":"integer"},"credentialType":{"type":"string","enum":["smtp","apiKey"]},"credentialId":{"type":"integer"},"cidr":{"type":"string"},"paused":{"type":"boolean"},"pausedAt":{"type":["string","null"]}},"additionalProperties":true},"Condition":{"type":"object","required":["campo","op","valor"],"properties":{"campo":{"type":"string"},"op":{"type":"string"},"valor":{"type":"string"}}},"SendPolicy":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string","maxLength":120},"conditions":{"type":"array","minItems":1,"maxItems":5,"items":{"$ref":"#/components/schemas/Condition"}},"action":{"type":"string","enum":["recusar","reter","exigir_footer","forcar_transacional","seguir_fluxo","limitar_hora"]},"actionParams":{"type":"object","additionalProperties":true},"position":{"type":"integer"},"paused":{"type":"boolean"},"pausedAt":{"type":["string","null"]}},"additionalProperties":true},"SendPolicyInput":{"type":"object","required":["name","conditions","action"],"properties":{"name":{"type":"string","maxLength":120},"conditions":{"type":"array","minItems":1,"maxItems":5,"items":{"$ref":"#/components/schemas/Condition"}},"action":{"type":"string"},"actionParams":{"type":"object","additionalProperties":true}}},"Template":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"version":{"type":"integer"},"status":{"type":"string"},"vars":{"type":"array","items":{"type":"string"}}},"additionalProperties":true},"TemplateInput":{"type":"object","required":["name","subject"],"properties":{"name":{"type":"string","maxLength":120,"description":"Unique in the account; starts with a letter; letters, digits, . - _"},"subject":{"type":"string"},"html":{"type":"string"},"text":{"type":"string"}}},"Survey":{"type":"object","properties":{"id":{"type":"integer"},"kind":{"type":"string","enum":["nps","csat"]},"name":{"type":"string"},"subject":{"type":"string"},"fromEmail":{"type":"string"},"fromName":{"type":"string"},"question":{"type":"string"},"throttleDays":{"type":"integer","minimum":7,"maximum":3650},"brandColor":{"type":"string"},"logoUrl":{"type":"string"},"active":{"type":"boolean"}},"additionalProperties":true},"SurveyInput":{"type":"object","required":["kind","name","subject","fromEmail"],"properties":{"kind":{"type":"string","enum":["nps","csat"],"description":"Cannot change after creation."},"name":{"type":"string"},"subject":{"type":"string"},"fromEmail":{"type":"string","description":"A domain of your account."},"fromName":{"type":"string"},"question":{"type":"string"},"throttleDays":{"type":"integer","minimum":7,"maximum":3650,"default":90},"brandColor":{"type":"string","pattern":"^#[0-9a-fA-F]{6}$"},"logoUrl":{"type":"string","format":"uri"},"active":{"type":"boolean"}}},"SurveyResponse":{"type":"object","properties":{"sendId":{"type":"string"},"recipient":{"type":"string"},"score":{"type":"integer"},"comment":{"type":["string","null"]},"updated":{"type":"boolean"},"meta":{"type":"object","additionalProperties":true},"timestamp":{"type":"string","format":"date-time"}},"additionalProperties":true},"Webhook":{"type":"object","properties":{"id":{"type":"integer"},"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"type":"string","enum":["delivered","bounced","opened","clicked","complained","blocked"]}},"active":{"type":"boolean"},"credential":{"type":["object","null"],"properties":{"type":{"type":"string","enum":["smtp","api"]},"id":{"type":"integer"}}}},"additionalProperties":true},"WebhookCreated":{"allOf":[{"$ref":"#/components/schemas/Webhook"},{"type":"object","properties":{"secret":{"type":"string","description":"Shown ONCE. Signs x-oveyon-signature."},"signature":{"type":"object","additionalProperties":true}}}]},"Domain":{"type":"object","properties":{"id":{"type":"integer"},"domain":{"type":"string"},"records":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string"},"name":{"type":"string"},"value":{"type":"string"},"purpose":{"type":"string"}}}},"verification":{"type":"object","properties":{"spf":{"type":"boolean"},"dkim":{"type":"boolean"},"dmarc":{"type":"boolean"},"inconclusive":{"type":"array","items":{"type":"string"}}},"additionalProperties":true}},"additionalProperties":true},"Decision":{"type":"object","additionalProperties":true,"description":"One send-policy decision (newest first)."}}},"security":[{"bearer":[]}]}