{
  "openapi": "3.1.0",
  "info": {
    "title": "YourMail API",
    "version": "1.0.0",
    "summary": "Transactional email API, sending from London (eu-west-2).",
    "description": "Send transactional email over HTTP and read back what happened to it.\n\nAuthenticate with `Authorization: Bearer <api key>`. Keys carry a scope: a `full` key reaches every endpoint, a `send` key may call only `POST /v1/emails` and `POST /v1/emails/batch` and receives 403 elsewhere.\n\nEvery error body carries a `docs_url` linking to the reference entry for its `type`. Read it off the response rather than rebuilding it, so a self-hosted deployment links to its own documentation.\n\nSending from a domain requires verifying it first; a verified domain sends from any local part on it, with no mailbox behind the address. Test mode is entered by sending from the shared sandbox sender \u2014 see /llms.txt.",
    "contact": {
      "name": "YourMail support",
      "url": "https://yourmail.dev/docs"
    },
    "license": {
      "name": "Proprietary",
      "identifier": "LicenseRef-Proprietary"
    }
  },
  "servers": [
    {
      "url": "https://api.yourmail.dev",
      "description": "Production"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Emails",
      "description": "Sending and retrieving messages"
    },
    {
      "name": "Suppressions",
      "description": "Addresses that must not be contacted. Hard bounces and complaints are added automatically."
    }
  ],
  "paths": {
    "/v1/emails": {
      "post": {
        "tags": [
          "Emails"
        ],
        "operationId": "sendEmail",
        "summary": "Send an email",
        "description": "Queues one message and returns its id immediately. Delivery happens asynchronously; subscribe to webhooks or poll the retrieve endpoint for the outcome.\n\nSupply `idempotency_key` to make retries safe \u2014 a repeated key returns the id of the original message rather than sending twice.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendEmailRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Queued",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SentEmail"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/AuthenticationError"
          },
          "403": {
            "$ref": "#/components/responses/DomainError"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "422": {
            "$ref": "#/components/responses/SuppressedRecipient"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "get": {
        "tags": [
          "Emails"
        ],
        "operationId": "listEmails",
        "summary": "List sent emails, newest first",
        "description": "Cursor-paginated. Pass the previous response's `nextCursor` to fetch the next page; `nextCursor` is null on the last one.",
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque cursor from a previous response.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Only return emails in this status. `queued` also covers messages mid-dispatch \u2014 the internal `sending` state is reported as `queued` on every public surface. Note that combining `search` with `status` narrows DIFFERENTLY: with a search term the query runs on the search index, where `status` is matched exactly, so `?search=x&status=queued` omits the mid-dispatch rows that `?status=queued` alone returns. This cannot be closed without a schema change, so it is stated rather than papered over.",
            "schema": {
              "$ref": "#/components/schemas/EmailStatusValue"
            }
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "description": "Full-text term matched against recipients, sender, subject and tag values. Results come back in relevance order rather than newest-first. Note that combining `search` with `status` narrows DIFFERENTLY: with a search term the query runs on the search index, where `status` is matched exactly, so `?search=x&status=queued` omits the mid-dispatch rows that `?status=queued` alone returns. This cannot be closed without a schema change, so it is stated rather than papered over. Maximum 512 characters and 16 whitespace-separated terms (the search engine's own cap); longer is a 400.",
            "schema": {
              "type": "string",
              "maxLength": 512
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of emails",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "hasMore",
                    "nextCursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/EmailListItem"
                      }
                    },
                    "hasMore": {
                      "type": "boolean"
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/AuthenticationError"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "500": {
            "description": "`internal_error` \u2014 this page of results could not be assembled completely. Rare, and specific to a tenant whose rows are large enough that the page had to be split repeatedly. A smaller `limit` does NOT help (it is ignored once the range is being narrowed); retry, or narrow with `status`/`search`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/emails/batch": {
      "post": {
        "tags": [
          "Emails"
        ],
        "operationId": "sendBatch",
        "summary": "Send up to 100 emails in one request",
        "description": "Each entry is validated and queued independently. The response is always HTTP 200 \u2014 inspect `summary.failed` to detect a partial failure, and the matching `data` entry for the reason.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "minItems": 1,
                "maxItems": 100,
                "items": {
                  "$ref": "#/components/schemas/SendEmailRequest"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Per-item results. Some entries may be errors.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "summary"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "oneOf": [
                          {
                            "$ref": "#/components/schemas/SentEmail"
                          },
                          {
                            "type": "object",
                            "required": [
                              "error"
                            ],
                            "properties": {
                              "error": {
                                "$ref": "#/components/schemas/ApiError"
                              }
                            }
                          }
                        ]
                      }
                    },
                    "summary": {
                      "type": "object",
                      "required": [
                        "total",
                        "succeeded",
                        "failed"
                      ],
                      "properties": {
                        "total": {
                          "type": "integer"
                        },
                        "succeeded": {
                          "type": "integer"
                        },
                        "failed": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/AuthenticationError"
          },
          "403": {
            "$ref": "#/components/responses/DomainError"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "422": {
            "$ref": "#/components/responses/SuppressedRecipient"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/emails/{id}": {
      "get": {
        "tags": [
          "Emails"
        ],
        "operationId": "getEmail",
        "summary": "Retrieve one email and its delivery timeline",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The id returned when the message was queued.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The message",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmailStatus"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/AuthenticationError"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "delete": {
        "tags": [
          "Emails"
        ],
        "operationId": "cancelEmail",
        "summary": "Cancel a scheduled send that has not dispatched",
        "description": "Only a message still in `scheduled` can be cancelled; once it has dispatched the send pipeline owns it and this returns 409. Requires a `full`-scope key.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The id returned when the message was scheduled.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Cancelled",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "id",
                    "canceled"
                  ],
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "canceled": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/AuthenticationError"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "The message has already dispatched and can no longer be cancelled.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/usage": {
      "get": {
        "operationId": "getUsage",
        "summary": "Current plan and consumption for this month and today",
        "description": "Plan tier plus month-to-date and today's send counts against their limits, and domain/webhook allowances. `limit: null` means unlimited on this plan. Requires a full-scope key: a send-only key exists to be handed to something that only sends, and account-level billing posture is not that. Read this before a large run rather than discovering the monthly cap as a 429 partway through one.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Current plan and consumption.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "plan": {
                      "type": "string",
                      "description": "The tenant's current tier."
                    },
                    "month": {
                      "type": "object",
                      "properties": {
                        "count": {
                          "type": "integer"
                        },
                        "limit": {
                          "type": [
                            "integer",
                            "null"
                          ],
                          "description": "null means unlimited on this plan."
                        }
                      },
                      "required": [
                        "count",
                        "limit"
                      ]
                    },
                    "day": {
                      "type": "object",
                      "description": "Today's sends against the ceiling actually ENFORCED - the new-account ramp stage or a review throttle where either applies, otherwise the plan's own daily cap. While ramped or throttled both figures count recipients rather than messages; the two always share a unit, so limit - count is real headroom either way.",
                      "properties": {
                        "count": {
                          "type": "integer"
                        },
                        "limit": {
                          "type": [
                            "integer",
                            "null"
                          ],
                          "description": "The enforced daily ceiling, which on a new or throttled account is below the plan's advertised cap. null means unlimited on this plan."
                        }
                      },
                      "required": [
                        "count",
                        "limit"
                      ]
                    },
                    "domains": {
                      "type": "object",
                      "properties": {
                        "count": {
                          "type": "integer"
                        },
                        "limit": {
                          "type": [
                            "integer",
                            "null"
                          ],
                          "description": "null means unlimited on this plan."
                        },
                        "suspended": {
                          "type": "integer",
                          "description": "How many a plan downgrade parked. Non-zero means some cannot be used."
                        }
                      },
                      "required": [
                        "count",
                        "limit",
                        "suspended"
                      ]
                    },
                    "webhooks": {
                      "type": "object",
                      "properties": {
                        "count": {
                          "type": "integer"
                        },
                        "limit": {
                          "type": [
                            "integer",
                            "null"
                          ],
                          "description": "null means unlimited on this plan."
                        },
                        "suspended": {
                          "type": "integer",
                          "description": "How many a plan downgrade parked. Non-zero means some cannot be used."
                        }
                      },
                      "required": [
                        "count",
                        "limit",
                        "suspended"
                      ]
                    }
                  },
                  "required": [
                    "plan",
                    "month",
                    "day",
                    "domains",
                    "webhooks"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/AuthenticationError"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/v1/domains": {
      "get": {
        "operationId": "listDomains",
        "summary": "List this account's sending domains",
        "description": "Requires a full-scope key: a send-only key must not be able to mint another key, repoint a webhook, or delete the domain it sends from, or the scope distinction would be decorative.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "The account's domains.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "pending",
                              "verified",
                              "failed"
                            ]
                          },
                          "verifiedAt": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "createdAt": {
                            "type": "integer"
                          },
                          "dnsCheckedAt": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "dnsHost": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "dnsRecords": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "type": {
                                  "type": "string"
                                },
                                "name": {
                                  "type": "string"
                                },
                                "value": {
                                  "type": "string"
                                },
                                "found": {
                                  "type": [
                                    "boolean",
                                    "null"
                                  ]
                                },
                                "observed": {
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                }
                              },
                              "required": [
                                "type",
                                "name",
                                "value",
                                "found",
                                "observed"
                              ]
                            }
                          },
                          "recommendedRecords": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "type": {
                                  "type": "string"
                                },
                                "name": {
                                  "type": "string"
                                },
                                "value": {
                                  "type": "string"
                                },
                                "found": {
                                  "type": [
                                    "boolean",
                                    "null"
                                  ]
                                },
                                "observed": {
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                }
                              },
                              "required": [
                                "type",
                                "name",
                                "value",
                                "found",
                                "observed"
                              ]
                            }
                          },
                          "failureReason": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "dnsRegressedAt": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Set when the daily health check found a verified domain no longer verified at SES. Advisory: the domain still sends."
                          },
                          "suspendedAt": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Set when a plan downgrade parked this domain. It keeps its records but cannot send."
                          },
                          "trackEngagement": {
                            "type": "boolean",
                            "description": "False when SES open/click tracking is switched off for this domain. Absent on a stored row means true."
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "status",
                          "verifiedAt",
                          "createdAt",
                          "dnsCheckedAt",
                          "dnsHost",
                          "dnsRecords",
                          "recommendedRecords",
                          "failureReason",
                          "dnsRegressedAt",
                          "suspendedAt",
                          "trackEngagement"
                        ]
                      }
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/AuthenticationError"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      },
      "post": {
        "operationId": "createDomain",
        "summary": "Add a sending domain and get its DNS records",
        "description": "Adds the domain and returns the DNS records to publish. Requires a full-scope key: a send-only key must not be able to mint another key, repoint a webhook, or delete the domain it sends from, or the scope distinction would be decorative.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "The domain to send from, e.g. mail.acme.com."
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The created domain, with the records to publish.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "pending",
                        "verified",
                        "failed"
                      ]
                    },
                    "verifiedAt": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "createdAt": {
                      "type": "integer"
                    },
                    "dnsCheckedAt": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "dnsHost": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "dnsRecords": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "type": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "value": {
                            "type": "string"
                          },
                          "found": {
                            "type": [
                              "boolean",
                              "null"
                            ]
                          },
                          "observed": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "type",
                          "name",
                          "value",
                          "found",
                          "observed"
                        ]
                      }
                    },
                    "recommendedRecords": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "type": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "value": {
                            "type": "string"
                          },
                          "found": {
                            "type": [
                              "boolean",
                              "null"
                            ]
                          },
                          "observed": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "type",
                          "name",
                          "value",
                          "found",
                          "observed"
                        ]
                      }
                    },
                    "failureReason": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "dnsRegressedAt": {
                      "type": [
                        "integer",
                        "null"
                      ],
                      "description": "Set when the daily health check found a verified domain no longer verified at SES. Advisory: the domain still sends."
                    },
                    "suspendedAt": {
                      "type": [
                        "integer",
                        "null"
                      ],
                      "description": "Set when a plan downgrade parked this domain. It keeps its records but cannot send."
                    },
                    "trackEngagement": {
                      "type": "boolean",
                      "description": "False when SES open/click tracking is switched off for this domain. Absent on a stored row means true."
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "status",
                    "verifiedAt",
                    "createdAt",
                    "dnsCheckedAt",
                    "dnsHost",
                    "dnsRecords",
                    "recommendedRecords",
                    "failureReason",
                    "dnsRegressedAt",
                    "suspendedAt",
                    "trackEngagement"
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/AuthenticationError"
          },
          "403": {
            "description": "This endpoint needs a `full`-scope key; a `send`-scoped key receives `403 authentication_error`. Also `domain_error` when the name is reserved by the platform, is tombstoned by an abuse suspension, or the plan's domain allowance is already used.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "`domain_error` \u2014 the domain is already on this account, or is held by another account. A `failed` row is recycled rather than conflicting, so re-posting a failed domain succeeds.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "502": {
            "description": "`domain_error` \u2014 SES refused to create the identity. Transient, and the one failure here worth retrying: the reserved row is deleted before this is raised, so a retry starts clean.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/domains/{id}": {
      "get": {
        "operationId": "getDomain",
        "summary": "Retrieve one domain, with its verification status and DNS records",
        "description": "Poll this while a domain verifies. Requires a full-scope key: a send-only key must not be able to mint another key, repoint a webhook, or delete the domain it sends from, or the scope distinction would be decorative.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The domain.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "pending",
                        "verified",
                        "failed"
                      ]
                    },
                    "verifiedAt": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "createdAt": {
                      "type": "integer"
                    },
                    "dnsCheckedAt": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "dnsHost": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "dnsRecords": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "type": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "value": {
                            "type": "string"
                          },
                          "found": {
                            "type": [
                              "boolean",
                              "null"
                            ]
                          },
                          "observed": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "type",
                          "name",
                          "value",
                          "found",
                          "observed"
                        ]
                      }
                    },
                    "recommendedRecords": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "type": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "value": {
                            "type": "string"
                          },
                          "found": {
                            "type": [
                              "boolean",
                              "null"
                            ]
                          },
                          "observed": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "type",
                          "name",
                          "value",
                          "found",
                          "observed"
                        ]
                      }
                    },
                    "failureReason": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "dnsRegressedAt": {
                      "type": [
                        "integer",
                        "null"
                      ],
                      "description": "Set when the daily health check found a verified domain no longer verified at SES. Advisory: the domain still sends."
                    },
                    "suspendedAt": {
                      "type": [
                        "integer",
                        "null"
                      ],
                      "description": "Set when a plan downgrade parked this domain. It keeps its records but cannot send."
                    },
                    "trackEngagement": {
                      "type": "boolean",
                      "description": "False when SES open/click tracking is switched off for this domain. Absent on a stored row means true."
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "status",
                    "verifiedAt",
                    "createdAt",
                    "dnsCheckedAt",
                    "dnsHost",
                    "dnsRecords",
                    "recommendedRecords",
                    "failureReason",
                    "dnsRegressedAt",
                    "suspendedAt",
                    "trackEngagement"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/AuthenticationError"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "delete": {
        "operationId": "deleteDomain",
        "summary": "Remove a sending domain",
        "description": "Removes the domain and its SES identity. Sending from it stops immediately. Requires a full-scope key: a send-only key must not be able to mint another key, repoint a webhook, or delete the domain it sends from, or the scope distinction would be decorative.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Removed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "deleted": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "id",
                    "deleted"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/AuthenticationError"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/domains/{id}/verify": {
      "post": {
        "operationId": "verifyDomain",
        "summary": "Re-check a domain's DNS records and verification status now",
        "description": "Asks SES to re-check this domain immediately and re-reads its DNS records, then returns the refreshed row \u2014 the same shape as GET /v1/domains/{id}. Without it a script could add a domain and publish its records but had no way to ask whether they had taken, short of waiting for the background poll. Safe to call repeatedly: it never moves a domain backwards, and a failed one is terminal and skipped entirely, so a retry loop reads 'already done' as success. A verified domain is still re-checked rather than skipped \u2014 that is how a repaired DNS record gets confirmed \u2014 but only dnsCheckedAt and the advisory dnsRegressedAt move; status never does. A DNS resolver failure is not an error: the SES verdict still applies and dnsCheckedAt simply stays where it was. Rate-shaped rather than rate-limited: a call within roughly 10 seconds of the last completed check answers 200 from the stored row without going out to SES again, so a tight loop is harmless but buys nothing \u2014 poll every 10-30s, since DNS propagation is minutes. dnsCheckedAt tells you which answers were freshly fetched. Requires a full-scope key.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The domain, as it stands after the re-check.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "pending",
                        "verified",
                        "failed"
                      ]
                    },
                    "verifiedAt": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "createdAt": {
                      "type": "integer"
                    },
                    "dnsCheckedAt": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "dnsHost": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "dnsRecords": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "type": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "value": {
                            "type": "string"
                          },
                          "found": {
                            "type": [
                              "boolean",
                              "null"
                            ]
                          },
                          "observed": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "type",
                          "name",
                          "value",
                          "found",
                          "observed"
                        ]
                      }
                    },
                    "recommendedRecords": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "type": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "value": {
                            "type": "string"
                          },
                          "found": {
                            "type": [
                              "boolean",
                              "null"
                            ]
                          },
                          "observed": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "type",
                          "name",
                          "value",
                          "found",
                          "observed"
                        ]
                      }
                    },
                    "failureReason": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "dnsRegressedAt": {
                      "type": [
                        "integer",
                        "null"
                      ],
                      "description": "Set when the daily health check found a verified domain no longer verified at SES. Advisory: the domain still sends."
                    },
                    "suspendedAt": {
                      "type": [
                        "integer",
                        "null"
                      ],
                      "description": "Set when a plan downgrade parked this domain. It keeps its records but cannot send."
                    },
                    "trackEngagement": {
                      "type": "boolean",
                      "description": "False when SES open/click tracking is switched off for this domain. Absent on a stored row means true."
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "status",
                    "verifiedAt",
                    "createdAt",
                    "dnsCheckedAt",
                    "dnsHost",
                    "dnsRecords",
                    "recommendedRecords",
                    "failureReason",
                    "dnsRegressedAt",
                    "suspendedAt",
                    "trackEngagement"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/AuthenticationError"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "502": {
            "description": "`domain_error` \u2014 Amazon SES could not be reached to re-check the domain. Transient, and the failure this endpoint is most likely to see, because it is documented as safe to poll and each call issues a live GetEmailIdentity: retry with backoff. Nothing has changed \u2014 the poll throws before any status write. A DNS resolver failure is deliberately NOT an error and does not appear here: the SES verdict still applies and dnsCheckedAt stays put.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/api-keys": {
      "get": {
        "operationId": "listApiKeys",
        "summary": "List this account's API keys",
        "description": "Secrets are never returned \u2014 only a key's metadata, including `last4` for matching a row against a secret you already hold. Live keys only: a revoked key leaves the list rather than reappearing with a timestamp, so its absence is the confirmation of a revocation. Requires a full-scope key: a send-only key must not be able to mint another key, repoint a webhook, or delete the domain it sends from, or the scope distinction would be decorative.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "The account's keys.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "last4": {
                            "type": "string",
                            "description": "The key's final four characters, for matching a row against a secret you already hold."
                          },
                          "scope": {
                            "type": "string",
                            "enum": [
                              "full",
                              "send"
                            ]
                          },
                          "createdAt": {
                            "type": "integer"
                          },
                          "lastUsedAt": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "last4",
                          "scope",
                          "createdAt",
                          "lastUsedAt"
                        ]
                      }
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/AuthenticationError"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      },
      "post": {
        "operationId": "createApiKey",
        "summary": "Mint an API key \u2014 the only time its secret is returned",
        "description": "The plaintext key is returned once and never stored; there is no way to retrieve it later. Requires a full-scope key: a send-only key must not be able to mint another key, repoint a webhook, or delete the domain it sends from, or the scope distinction would be decorative.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "scope": {
                    "type": "string",
                    "enum": [
                      "full",
                      "send"
                    ],
                    "description": "Absent means full, matching existing keys."
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The plaintext key. This is the only time it is returned.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "key": {
                      "type": "string",
                      "description": "The plaintext secret itself, e.g. \"yourmail_\u2026\" \u2014 a string, not an object. Shown once and stored only as a hash."
                    }
                  },
                  "required": [
                    "key"
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/AuthenticationError"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/api-keys/{id}": {
      "delete": {
        "operationId": "revokeApiKey",
        "summary": "Revoke an API key",
        "description": "The key stops authenticating immediately. Revoking is not deletion: the row stays so the request log keeps naming which key made past calls. Requires a full-scope key: a send-only key must not be able to mint another key, repoint a webhook, or delete the domain it sends from, or the scope distinction would be decorative.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "revoked": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "id",
                    "revoked"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/AuthenticationError"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/webhooks": {
      "get": {
        "operationId": "listWebhooks",
        "summary": "List this account's webhook endpoints",
        "description": "Signing secrets are not returned. Requires a full-scope key: a send-only key must not be able to mint another key, repoint a webhook, or delete the domain it sends from, or the scope distinction would be decorative.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "The account's endpoints.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "url": {
                            "type": "string"
                          },
                          "events": {
                            "type": "array",
                            "items": {
                              "$ref": "#/components/schemas/WebhookEventSubscription"
                            }
                          },
                          "enabled": {
                            "type": "boolean"
                          },
                          "description": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "consecutiveFailures": {
                            "type": "integer"
                          },
                          "lastAttemptAt": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "lastResponseStatus": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "lastError": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "suspendedByPlan": {
                            "type": "boolean"
                          },
                          "autoDisabledAt": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Set when YourMail switched the endpoint off after repeated failed deliveries; cleared on re-enable."
                          }
                        },
                        "required": [
                          "id",
                          "url",
                          "events",
                          "enabled",
                          "description",
                          "consecutiveFailures",
                          "lastAttemptAt",
                          "lastResponseStatus",
                          "lastError",
                          "suspendedByPlan",
                          "autoDisabledAt"
                        ]
                      }
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/AuthenticationError"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      },
      "post": {
        "operationId": "createWebhook",
        "summary": "Register a webhook endpoint",
        "description": "The signing secret is returned once, here, and never again. Requires a full-scope key: a send-only key must not be able to mint another key, repoint a webhook, or delete the domain it sends from, or the scope distinction would be decorative.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "description": "https only; private and link-local hosts are rejected."
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/WebhookEventSubscription"
                    },
                    "description": "Event types to receive, or [\"*\"] for all.",
                    "minItems": 1
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 500
                  }
                },
                "required": [
                  "url",
                  "events"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The created endpoint, including its signing secret.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "The created endpoint \u2014 the full row, plus the signing secret.",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "url": {
                      "type": "string"
                    },
                    "events": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WebhookEventSubscription"
                      }
                    },
                    "enabled": {
                      "type": "boolean"
                    },
                    "description": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "consecutiveFailures": {
                      "type": "integer"
                    },
                    "lastAttemptAt": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "lastResponseStatus": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "lastError": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "suspendedByPlan": {
                      "type": "boolean"
                    },
                    "autoDisabledAt": {
                      "type": [
                        "integer",
                        "null"
                      ],
                      "description": "Set when YourMail switched the endpoint off after repeated failed deliveries; cleared on re-enable."
                    },
                    "secret": {
                      "type": "string",
                      "description": "HMAC-SHA256 signing secret. Shown once."
                    }
                  },
                  "required": [
                    "id",
                    "url",
                    "events",
                    "enabled",
                    "description",
                    "consecutiveFailures",
                    "lastAttemptAt",
                    "lastResponseStatus",
                    "lastError",
                    "suspendedByPlan",
                    "autoDisabledAt",
                    "secret"
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/AuthenticationError"
          },
          "403": {
            "description": "This endpoint needs a `full`-scope key; a `send`-scoped key receives `403 authentication_error`. Also `validation_error` when the plan does not include webhook endpoints, or its endpoint allowance is already used \u2014 a refusal about the plan, not the key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/webhooks/{id}": {
      "patch": {
        "operationId": "updateWebhook",
        "summary": "Update a webhook's URL, events or enabled state",
        "description": "Partial update \u2014 omitted fields are left alone. Requires a full-scope key: a send-only key must not be able to mint another key, repoint a webhook, or delete the domain it sends from, or the scope distinction would be decorative.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string"
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/WebhookEventSubscription"
                    },
                    "minItems": 1
                  },
                  "enabled": {
                    "type": "boolean"
                  },
                  "description": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 500
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "url": {
                      "type": "string"
                    },
                    "events": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WebhookEventSubscription"
                      }
                    },
                    "enabled": {
                      "type": "boolean"
                    },
                    "description": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "consecutiveFailures": {
                      "type": "integer"
                    },
                    "lastAttemptAt": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "lastResponseStatus": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "lastError": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "suspendedByPlan": {
                      "type": "boolean"
                    },
                    "autoDisabledAt": {
                      "type": [
                        "integer",
                        "null"
                      ],
                      "description": "Set when YourMail switched the endpoint off after repeated failed deliveries; cleared on re-enable."
                    }
                  },
                  "required": [
                    "id",
                    "url",
                    "events",
                    "enabled",
                    "description",
                    "consecutiveFailures",
                    "lastAttemptAt",
                    "lastResponseStatus",
                    "lastError",
                    "suspendedByPlan",
                    "autoDisabledAt"
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/AuthenticationError"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "delete": {
        "operationId": "deleteWebhook",
        "summary": "Remove a webhook endpoint",
        "description": "Deliveries stop immediately. Past attempts stay in the delivery log until it is pruned. Requires a full-scope key: a send-only key must not be able to mint another key, repoint a webhook, or delete the domain it sends from, or the scope distinction would be decorative.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Removed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "deleted": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "id",
                    "deleted"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/AuthenticationError"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/suppressions": {
      "get": {
        "tags": [
          "Suppressions"
        ],
        "operationId": "listSuppressions",
        "summary": "List suppressed recipient addresses",
        "responses": {
          "200": {
            "description": "The suppression list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "hasMore",
                    "nextCursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Suppression"
                      }
                    },
                    "hasMore": {
                      "type": "boolean",
                      "description": "Whether another page exists. This \u2014 not an empty `data` \u2014 is the only authority on whether to keep paging."
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Pass as `cursor` to fetch the next page. `null` on the last page."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/AuthenticationError"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        },
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque cursor from a previous response.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          }
        ]
      },
      "post": {
        "tags": [
          "Suppressions"
        ],
        "operationId": "createSuppression",
        "summary": "Suppress an address manually",
        "description": "Idempotent. A manual suppression blocks all mail to the address, transactional included. Accepts either a single `email` or an `emails` array of up to 100. The array form is the migration path off another provider: without it, moving a suppression list meant one call per address, so day one on YourMail was spent mailing addresses that already hard-bounced elsewhere \u2014 on a SES reputation shared with every other tenant. Addresses already suppressed are skipped, not errors, so a re-run is safe.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "object",
                    "required": [
                      "email"
                    ],
                    "properties": {
                      "email": {
                        "type": "string",
                        "format": "email"
                      }
                    },
                    "title": "One address"
                  },
                  {
                    "title": "A list of addresses",
                    "type": "object",
                    "properties": {
                      "emails": {
                        "type": "array",
                        "items": {
                          "type": "string",
                          "format": "email"
                        },
                        "minItems": 1,
                        "maxItems": 100,
                        "description": "Up to 100 addresses. Longer lists are sent in batches by the caller."
                      }
                    },
                    "required": [
                      "emails"
                    ]
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Added. The single-address form returns the row; the array form returns every row it stored plus `added`, the number of addresses accepted (the request is all-or-nothing, so one invalid address fails the whole call with a 400).",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": [
                        "address",
                        "reason"
                      ],
                      "properties": {
                        "address": {
                          "type": "string",
                          "format": "email"
                        },
                        "reason": {
                          "type": "string",
                          "const": "manual"
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": [
                        "data",
                        "added"
                      ],
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "required": [
                              "address",
                              "reason"
                            ],
                            "properties": {
                              "address": {
                                "type": "string",
                                "format": "email"
                              },
                              "reason": {
                                "type": "string",
                                "const": "manual"
                              }
                            }
                          }
                        },
                        "added": {
                          "type": "integer"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/AuthenticationError"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/suppressions/{address}": {
      "delete": {
        "tags": [
          "Suppressions"
        ],
        "operationId": "deleteSuppression",
        "summary": "Remove an address from the suppression list",
        "description": "Idempotent \u2014 `removed` is false if the address was not suppressed. Requires a `full`-scope key.",
        "parameters": [
          {
            "name": "address",
            "in": "path",
            "required": true,
            "description": "URL-encoded email address.",
            "schema": {
              "type": "string",
              "format": "email"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Removal result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "address",
                    "removed"
                  ],
                  "properties": {
                    "address": {
                      "type": "string",
                      "format": "email"
                    },
                    "removed": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/AuthenticationError"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "An API key from the dashboard, sent as `Authorization: Bearer yourmail_\u2026`. Shown once at creation and stored only as a hash, so it cannot be recovered \u2014 mint a new one instead."
      }
    },
    "schemas": {
      "EmailAddress": {
        "type": "string",
        "description": "`user@example.com`, or `Display Name <user@example.com>`. Ownership of a `from` domain is always checked against the address, never the display name.",
        "examples": [
          "hello@mail.acme.com",
          "Acme Support <hello@mail.acme.com>"
        ]
      },
      "Tag": {
        "type": "object",
        "required": [
          "name",
          "value"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "value": {
            "type": "string"
          }
        }
      },
      "Attachment": {
        "type": "object",
        "required": [
          "filename",
          "content"
        ],
        "properties": {
          "filename": {
            "type": "string"
          },
          "content": {
            "type": "string",
            "contentEncoding": "base64"
          },
          "content_type": {
            "type": "string"
          }
        }
      },
      "SendEmailRequest": {
        "type": "object",
        "required": [
          "from",
          "to",
          "subject"
        ],
        "description": "One of `html` or `text` must be present. Recipients are capped at 50 per message across to/cc/bcc.",
        "properties": {
          "from": {
            "$ref": "#/components/schemas/EmailAddress"
          },
          "to": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/EmailAddress"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/EmailAddress"
                }
              }
            ]
          },
          "cc": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/EmailAddress"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/EmailAddress"
                }
              }
            ]
          },
          "bcc": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/EmailAddress"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/EmailAddress"
                }
              }
            ]
          },
          "reply_to": {
            "$ref": "#/components/schemas/EmailAddress"
          },
          "subject": {
            "type": "string"
          },
          "html": {
            "type": "string"
          },
          "text": {
            "type": "string"
          },
          "attachments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Attachment"
            }
          },
          "tags": {
            "type": "array",
            "maxItems": 10,
            "items": {
              "$ref": "#/components/schemas/Tag"
            }
          },
          "headers": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Custom SMTP headers. Address and MIME headers (From, To, Content-Type, DKIM-Signature, Return-Path \u2026) are reserved and rejected."
          },
          "idempotency_key": {
            "type": "string",
            "description": "Repeating a key returns the original message's id instead of sending again."
          },
          "bulk": {
            "type": "boolean",
            "description": "Marks a non-transactional message. A compliant one-click List-Unsubscribe header is injected unless you supply your own, and `unsubscribe` suppressions are enforced. Requires exactly one `to` recipient and no cc/bcc."
          },
          "scheduledAt": {
            "type": "string",
            "format": "date-time",
            "description": "Hold the message until this time (ISO 8601, or Unix milliseconds). Up to 30 days ahead. A time at or before now sends immediately rather than erroring; a numeric value below 1e12 is rejected as Unix seconds, which read as milliseconds would land in 1970 and dispatch at once. The message reads `scheduled` until it dispatches, and can be cancelled with DELETE /v1/emails/{id} until then. Quota is charged when it dispatches, so a cancelled send costs nothing \u2014 but there is a cap on how many you may have outstanding, equal to your plan's monthly allowance. `scheduled_at` is accepted as an alias."
          }
        }
      },
      "SentEmail": {
        "type": "object",
        "required": [
          "id"
        ],
        "properties": {
          "id": {
            "type": "string"
          }
        }
      },
      "EmailStatusValue": {
        "type": "string",
        "enum": [
          "scheduled",
          "queued",
          "sent",
          "delivered",
          "bounced",
          "complained",
          "failed",
          "canceled"
        ],
        "description": "`scheduled` is a send waiting for its `scheduledAt`; `canceled` is one that was cancelled before it dispatched. Both are distinct from `failed`, which means we tried and could not deliver."
      },
      "WebhookEventType": {
        "type": "string",
        "description": "A webhook event type. The eight `email.*` events carry an `emailId`; `quota.exceeded` is account-level and carries a `data` payload instead.",
        "enum": [
          "email.sent",
          "email.delivered",
          "email.opened",
          "email.clicked",
          "email.bounced",
          "email.complained",
          "email.delivery_delayed",
          "email.failed",
          "quota.exceeded"
        ]
      },
      "WebhookEventSubscription": {
        "description": "A webhook subscription entry: either a specific event type, or `\"*\"` for every event, including ones added later.",
        "anyOf": [
          {
            "$ref": "#/components/schemas/WebhookEventType"
          },
          {
            "type": "string",
            "const": "*",
            "description": "Subscribe to every event type."
          }
        ]
      },
      "EmailListItem": {
        "type": "object",
        "required": [
          "id",
          "to",
          "from",
          "subject",
          "status",
          "tags",
          "createdAt",
          "sentAt",
          "scheduledAt",
          "openedAt",
          "clickedAt"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "to": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "from": {
            "type": "string"
          },
          "subject": {
            "type": "string"
          },
          "status": {
            "$ref": "#/components/schemas/EmailStatusValue"
          },
          "tags": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Tag"
            }
          },
          "createdAt": {
            "type": "integer",
            "description": "Unix milliseconds."
          },
          "sentAt": {
            "type": [
              "integer",
              "null"
            ]
          },
          "scheduledAt": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Unix ms the send is scheduled to fire at. Null for a message sent immediately."
          },
          "openedAt": {
            "type": [
              "integer",
              "null"
            ],
            "description": "First open, Unix ms."
          },
          "clickedAt": {
            "type": [
              "integer",
              "null"
            ],
            "description": "First click, Unix ms."
          }
        }
      },
      "DeliveryEvent": {
        "type": "object",
        "required": [
          "type",
          "occurredAt",
          "meta"
        ],
        "properties": {
          "type": {
            "type": "string",
            "description": "send, delivered, bounce, complaint, open, click, delivery_delay \u2026"
          },
          "occurredAt": {
            "type": "integer",
            "description": "Unix milliseconds."
          },
          "meta": {
            "type": [
              "object",
              "null"
            ],
            "description": "Diagnostic detail, present on bounce, complaint and engagement events.",
            "properties": {
              "bounceType": {
                "type": "string",
                "enum": [
                  "Permanent",
                  "Transient",
                  "Undetermined"
                ]
              },
              "bounceSubType": {
                "type": "string"
              },
              "diagnosticCode": {
                "type": "string"
              },
              "complaintFeedbackType": {
                "type": "string"
              },
              "link": {
                "type": "string",
                "description": "The URL clicked, on a click event."
              },
              "userAgent": {
                "type": "string"
              }
            }
          }
        }
      },
      "EmailStatus": {
        "type": "object",
        "required": [
          "id",
          "status",
          "from",
          "to",
          "cc",
          "bcc",
          "replyTo",
          "subject",
          "html",
          "text",
          "tags",
          "sesMessageId",
          "error",
          "createdAt",
          "sentAt",
          "scheduledAt",
          "openedAt",
          "clickedAt",
          "events"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "status": {
            "$ref": "#/components/schemas/EmailStatusValue"
          },
          "from": {
            "type": "string"
          },
          "to": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "cc": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "bcc": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "replyTo": {
            "type": [
              "string",
              "null"
            ]
          },
          "subject": {
            "type": "string"
          },
          "html": {
            "type": [
              "string",
              "null"
            ],
            "description": "The body as sent. Null once the account's retention window has stripped it."
          },
          "text": {
            "type": [
              "string",
              "null"
            ]
          },
          "tags": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Tag"
            }
          },
          "sesMessageId": {
            "type": [
              "string",
              "null"
            ]
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "createdAt": {
            "type": "integer"
          },
          "sentAt": {
            "type": [
              "integer",
              "null"
            ]
          },
          "scheduledAt": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Unix ms a scheduled send dispatches at; null for an immediate send."
          },
          "openedAt": {
            "type": [
              "integer",
              "null"
            ]
          },
          "clickedAt": {
            "type": [
              "integer",
              "null"
            ]
          },
          "events": {
            "type": "array",
            "description": "Oldest first, capped at the 100 most recent.",
            "items": {
              "$ref": "#/components/schemas/DeliveryEvent"
            }
          }
        }
      },
      "Suppression": {
        "type": "object",
        "required": [
          "address",
          "reason",
          "createdAt"
        ],
        "properties": {
          "address": {
            "type": "string",
            "format": "email"
          },
          "reason": {
            "type": "string",
            "enum": [
              "hard_bounce",
              "complaint",
              "manual",
              "unsubscribe"
            ],
            "description": "`unsubscribe` blocks bulk mail only \u2014 transactional messages to the address still send. The others block everything."
          },
          "createdAt": {
            "type": "integer",
            "description": "Unix milliseconds."
          }
        }
      },
      "ApiErrorType": {
        "type": "string",
        "description": "The machine-readable error vocabulary. Branch on this, not on the message.",
        "enum": [
          "validation_error",
          "authentication_error",
          "domain_error",
          "quota_exceeded",
          "rate_limited",
          "deliverability_blocked",
          "account_pending_review",
          "sandbox_recipient",
          "suppressed_recipient",
          "not_found",
          "internal_error"
        ]
      },
      "ApiError": {
        "type": "object",
        "required": [
          "type",
          "message"
        ],
        "properties": {
          "type": {
            "$ref": "#/components/schemas/ApiErrorType"
          },
          "message": {
            "type": "string"
          },
          "docs_url": {
            "type": "string",
            "format": "uri",
            "description": "Reference entry for this error type. Read it from the response rather than rebuilding it, so a self-hosted deployment links to its own docs."
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "$ref": "#/components/schemas/ApiError"
          }
        }
      }
    },
    "responses": {
      "ValidationError": {
        "description": "The request was malformed \u2014 a missing field, a bad address, a reserved header.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "AuthenticationError": {
        "description": "Missing, malformed, revoked or out-of-scope API key.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "DomainError": {
        "description": "The `from` domain is not verified for this account, or is suspended by the current plan.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "SuppressedRecipient": {
        "description": "One or more recipients are on the suppression list. The message names each address and why it is blocked.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "RateLimited": {
        "description": "A rate limit or send quota was reached. Two distinct types, and neither is simply 'retryable'.\n\n`quota_exceeded` is a ceiling you have reached: the plan's monthly or daily allowance (including its grace band \u2014 sending continues past the plan limit to 110% of it, and a `quota.exceeded` webhook fires when you cross), the new-account ramp, the review throttle, or the outstanding-scheduled-sends cap. It carries NO `Retry-After` header. Surface it; retrying never clears it.\n\n`rate_limited` is not the caller's fault \u2014 the per-request rate limit, the sandbox daily cap, the account-wide SES daily cap, or brief contention between requests you sent in parallel \u2014 and always carries `Retry-After` in seconds. Retry it only if that value fits inside your backoff ceiling: the two daily caps answer with the seconds until UTC midnight.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "NotFound": {
        "description": "No such resource for this account.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "Forbidden": {
        "description": "This endpoint needs a `full`-scope key; a `send`-scoped key receives `403 authentication_error`.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "PayloadTooLarge": {
        "description": "The request is within the JSON schema but exceeds a size limit: too many attachments, an attachment over the per-file cap, the combined attachment cap, or the combined custom-header cap. The `type` is `validation_error`, like every other refusal of the body itself \u2014 the status is what distinguishes 'too big' from 'malformed', and a client that branches only on `type` should read the message. Retrying the same payload never succeeds; send fewer or smaller parts.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      }
    }
  }
}
