{
  "openapi": "3.1.0",
  "info": {
    "title": "MailMarco API",
    "version": "1.0.0",
    "summary": "Transactional email, domains, webhooks and deliverability.",
    "description": "The MailMarco `/v1` HTTP API. Runtime routes authenticate with an API key (`Authorization: Bearer mf_live_…`); management routes such as domains and API-key administration authenticate with a dashboard session access token.",
    "contact": {
      "name": "MailMarco",
      "url": "https://docs.mailmarco.com"
    }
  },
  "servers": [
    {
      "url": "https://api.mailmarco.com",
      "description": "Production"
    }
  ],
  "x-mailmarco-coverage": {
    "covered": [
      "emails",
      "domains",
      "templates",
      "suppressions",
      "bounces",
      "complaints",
      "webhooks",
      "api-keys"
    ],
    "notCovered": [
      "marketing",
      "inbound",
      "reputation",
      "billing",
      "admin"
    ]
  },
  "tags": [
    {
      "name": "Emails",
      "description": "Send and inspect messages."
    },
    {
      "name": "Domains",
      "description": "Sending domains, DNS records and verification."
    },
    {
      "name": "Templates",
      "description": "Versioned, publishable templates."
    },
    {
      "name": "Deliverability",
      "description": "Suppressions, bounces and complaints."
    },
    {
      "name": "Webhooks",
      "description": "Event subscriptions and delivery history."
    },
    {
      "name": "API keys",
      "description": "Key lifecycle (session-authenticated)."
    }
  ],
  "security": [
    {
      "apiKey": []
    }
  ],
  "paths": {
    "/v1/emails": {
      "post": {
        "tags": [
          "Emails"
        ],
        "operationId": "sendEmail",
        "summary": "Send an email",
        "description": "Accepts the message, persists it and enqueues it for delivery. Returns 202 — acceptance is not delivery; subscribe to webhooks for the outcome.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Replaying the same key for the same organization returns the original message with `deduped: true` instead of sending again."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendEmail"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SendResult"
                }
              }
            }
          },
          "400": {
            "description": "Validation failed, or a domain rule rejected the request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Plan send limit reached (`error: plan_limit_exceeded`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Organization sending is paused (`error: org_suspended`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Warm-up daily cap reached (`error: warmup_cap_reached`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/emails/batch": {
      "post": {
        "tags": [
          "Emails"
        ],
        "operationId": "sendEmailBatch",
        "summary": "Send up to 500 emails in one request",
        "description": "Each item is processed independently: one failure is reported in that item's `error` and does not abort the rest.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "emails"
                ],
                "properties": {
                  "emails": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 500,
                    "items": {
                      "$ref": "#/components/schemas/SendEmail"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Per-item results, aligned to the request order by `index`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "results"
                  ],
                  "properties": {
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "index"
                        ],
                        "properties": {
                          "index": {
                            "type": "integer"
                          },
                          "id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "status": {
                            "type": "string"
                          },
                          "deduped": {
                            "type": "boolean"
                          },
                          "error": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation failed, or a domain rule rejected the request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/emails/{id}": {
      "get": {
        "tags": [
          "Emails"
        ],
        "operationId": "getEmail",
        "summary": "Retrieve a message with its recipients and events",
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "The message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmailDetail"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No message with that id in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/emails/{id}/cancel": {
      "post": {
        "tags": [
          "Emails"
        ],
        "operationId": "cancelEmail",
        "summary": "Cancel a scheduled message",
        "description": "Only a message still in `scheduled` can be cancelled. Answers 201 (the NestJS default for POST).",
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "201": {
            "description": "Cancelled.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "status": {
                      "type": "string",
                      "const": "cancelled"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "The message is not in `scheduled` state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/domains": {
      "get": {
        "tags": [
          "Domains"
        ],
        "operationId": "listDomains",
        "summary": "List sending domains",
        "security": [
          {
            "session": []
          }
        ],
        "responses": {
          "200": {
            "description": "Domains, without their DNS records.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Domain"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Domains"
        ],
        "operationId": "createDomain",
        "summary": "Add a sending domain",
        "description": "Mints a DKIM keypair and returns the full set of DNS records to publish.",
        "security": [
          {
            "session": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "domain"
                ],
                "properties": {
                  "domain": {
                    "type": "string",
                    "description": "Lower-cased and trimmed; must contain at least one dot.",
                    "examples": [
                      "mail.example.com"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The domain with its generated records.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DomainWithRecords"
                }
              }
            }
          },
          "400": {
            "description": "Validation failed, or a domain rule rejected the request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "The domain already exists.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/domains/{id}": {
      "get": {
        "tags": [
          "Domains"
        ],
        "operationId": "getDomain",
        "summary": "Retrieve a domain with its DNS records",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "The domain.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DomainWithRecords"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such domain.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/domains/{id}/dns-records": {
      "get": {
        "tags": [
          "Domains"
        ],
        "operationId": "listDomainDnsRecords",
        "summary": "List the DNS records for a domain",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "Records with their last check result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/DnsRecord"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/domains/{id}/verify": {
      "post": {
        "tags": [
          "Domains"
        ],
        "operationId": "verifyDomain",
        "summary": "Re-check the published DNS and update the domain status",
        "description": "Rate limited to 10 calls per organization per hour.",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "201": {
            "description": "The domain with freshly checked records.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DomainWithRecords"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such domain.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Verification rate limit exceeded; see `retryAfterSeconds`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/domains/{id}/suspend": {
      "post": {
        "tags": [
          "Domains"
        ],
        "operationId": "suspendDomain",
        "summary": "Suspend a domain",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "201": {
            "description": "The suspended domain.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Domain"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such domain.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/templates": {
      "post": {
        "tags": [
          "Templates"
        ],
        "operationId": "createTemplate",
        "summary": "Create a template",
        "security": [
          {
            "apiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The template."
          },
          "400": {
            "description": "Validation failed, or a domain rule rejected the request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/templates/{id}/versions": {
      "post": {
        "tags": [
          "Templates"
        ],
        "operationId": "addTemplateVersion",
        "summary": "Add a version",
        "description": "At least one of `html`, `text` or `reactSource` is required.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "subject"
                ],
                "properties": {
                  "subject": {
                    "type": "string",
                    "minLength": 1
                  },
                  "html": {
                    "type": "string"
                  },
                  "text": {
                    "type": "string"
                  },
                  "reactSource": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The version."
          },
          "400": {
            "description": "Validation failed, or a domain rule rejected the request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/templates/{id}/publish": {
      "post": {
        "tags": [
          "Templates"
        ],
        "operationId": "publishTemplate",
        "summary": "Publish a version",
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "version"
                ],
                "properties": {
                  "version": {
                    "type": "integer",
                    "minimum": 1
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The published template."
          },
          "400": {
            "description": "Validation failed, or a domain rule rejected the request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/suppressions": {
      "get": {
        "tags": [
          "Deliverability"
        ],
        "operationId": "listSuppressions",
        "summary": "List suppressed addresses",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Suppressions.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Suppression"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Deliverability"
        ],
        "operationId": "addSuppression",
        "summary": "Suppress an address",
        "security": [
          {
            "apiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "address"
                ],
                "properties": {
                  "address": {
                    "type": "string",
                    "minLength": 1
                  },
                  "scope": {
                    "type": "string",
                    "enum": [
                      "global",
                      "tenant",
                      "domain",
                      "recipient"
                    ],
                    "default": "tenant"
                  },
                  "reason": {
                    "type": "string",
                    "enum": [
                      "bounce",
                      "complaint",
                      "invalid",
                      "manual"
                    ],
                    "default": "manual"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The suppression.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Suppression"
                }
              }
            }
          },
          "400": {
            "description": "Validation failed, or a domain rule rejected the request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/suppressions/{id}": {
      "delete": {
        "tags": [
          "Deliverability"
        ],
        "operationId": "deleteSuppression",
        "summary": "Remove a suppression",
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "Removed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "deleted": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/bounces": {
      "get": {
        "tags": [
          "Deliverability"
        ],
        "operationId": "listBounces",
        "summary": "List bounces",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Bounces."
          },
          "401": {
            "description": "Missing or invalid credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/complaints": {
      "get": {
        "tags": [
          "Deliverability"
        ],
        "operationId": "listComplaints",
        "summary": "List complaints",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Complaints."
          },
          "401": {
            "description": "Missing or invalid credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhooks": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "listWebhooks",
        "summary": "List endpoints",
        "description": "Secrets are masked as `whsec_***`; the plaintext is only ever returned at create and rotate.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Endpoints.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WebhookEndpoint"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "createWebhook",
        "summary": "Create an endpoint",
        "security": [
          {
            "apiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url",
                  "eventTypes"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "eventTypes": {
                    "type": "array",
                    "minItems": 1,
                    "items": {
                      "$ref": "#/components/schemas/WebhookEventType"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The endpoint, including the one-time plaintext `secret`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpoint"
                }
              }
            }
          },
          "400": {
            "description": "Validation failed, or a domain rule rejected the request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhooks/{id}": {
      "delete": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "deleteWebhook",
        "summary": "Delete an endpoint and its delivery history",
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "deleted": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhooks/{id}/test": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "testWebhook",
        "summary": "Send a sample email.delivered event to one endpoint",
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "201": {
            "description": "The resulting delivery row."
          },
          "401": {
            "description": "Missing or invalid credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhooks/{id}/rotate-secret": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "rotateWebhookSecret",
        "summary": "Rotate the signing secret",
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "201": {
            "description": "The endpoint with the new plaintext `secret`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpoint"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhooks/{id}/replay/{deliveryId}": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "replayWebhookDelivery",
        "summary": "Re-deliver a past event as a new delivery",
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "deliveryId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "The new delivery row."
          },
          "401": {
            "description": "Missing or invalid credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such delivery or endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhook-events": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "listWebhookDeliveries",
        "summary": "Recent delivery attempts (newest first, up to 100)",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Deliveries.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WebhookDelivery"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/api-keys": {
      "get": {
        "tags": [
          "API keys"
        ],
        "operationId": "listApiKeys",
        "summary": "List keys (metadata only)",
        "security": [
          {
            "session": []
          }
        ],
        "responses": {
          "200": {
            "description": "Keys."
          },
          "401": {
            "description": "Missing or invalid credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "API keys"
        ],
        "operationId": "createApiKey",
        "summary": "Create a key",
        "description": "The plaintext `token` is returned exactly once.",
        "security": [
          {
            "session": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  },
                  "scopes": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "default": [
                      "emails:send"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The key plus its one-time plaintext token.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyCreated"
                }
              }
            }
          },
          "400": {
            "description": "Validation failed, or a domain rule rejected the request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/api-keys/{id}": {
      "delete": {
        "tags": [
          "API keys"
        ],
        "operationId": "revokeApiKey",
        "summary": "Revoke a key",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "Revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "revoked": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "parameters": {
      "PathId": {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    },
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "mf_live_<prefix>.<secret>",
        "description": "An organization API key. Send as `Authorization: Bearer mf_live_…`."
      },
      "session": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "A dashboard session access token from `POST /v1/auth/login`."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "statusCode",
          "error",
          "message"
        ],
        "properties": {
          "statusCode": {
            "type": "integer"
          },
          "error": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "details": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "path": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                }
              }
            }
          },
          "constraint": {
            "type": "string"
          }
        }
      },
      "Attachment": {
        "type": "object",
        "required": [
          "filename",
          "contentType",
          "content"
        ],
        "properties": {
          "filename": {
            "type": "string",
            "minLength": 1
          },
          "contentType": {
            "type": "string",
            "minLength": 1
          },
          "content": {
            "type": "string",
            "contentEncoding": "base64",
            "description": "Base64 bytes. At most 10 MiB decoded per attachment."
          },
          "inline": {
            "type": "boolean"
          },
          "contentId": {
            "type": "string"
          }
        }
      },
      "SendEmail": {
        "type": "object",
        "required": [
          "from",
          "to"
        ],
        "description": "`subject` is required unless `template` is supplied. Free-text header values must not contain CR or LF.",
        "properties": {
          "from": {
            "type": "string",
            "format": "email"
          },
          "to": {
            "oneOf": [
              {
                "type": "string",
                "format": "email"
              },
              {
                "type": "array",
                "minItems": 1,
                "items": {
                  "type": "string",
                  "format": "email"
                }
              }
            ]
          },
          "cc": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "email"
            }
          },
          "bcc": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "email"
            }
          },
          "subject": {
            "type": "string",
            "minLength": 1
          },
          "html": {
            "type": "string"
          },
          "text": {
            "type": "string"
          },
          "replyTo": {
            "type": "string",
            "format": "email"
          },
          "template": {
            "type": "object",
            "required": [
              "id"
            ],
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "variables": {
                "type": "object",
                "additionalProperties": true,
                "default": {}
              }
            }
          },
          "attachments": {
            "type": "array",
            "maxItems": 20,
            "items": {
              "$ref": "#/components/schemas/Attachment"
            },
            "description": "At most 25 MiB decoded across all attachments."
          },
          "headers": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "propertyNames": {
              "pattern": "^[A-Za-z0-9-]+$"
            }
          },
          "tags": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true
          },
          "sandbox": {
            "type": "boolean"
          },
          "scheduledAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "SendResult": {
        "type": "object",
        "required": [
          "id",
          "status"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "scheduled"
            ]
          },
          "deduped": {
            "type": "boolean",
            "description": "Present and true when an Idempotency-Key replayed an existing message."
          }
        }
      },
      "EmailStatus": {
        "type": "string",
        "enum": [
          "queued",
          "scheduled",
          "sent",
          "delivered",
          "delivery_delayed",
          "bounced",
          "complained",
          "opened",
          "clicked",
          "failed",
          "cancelled"
        ]
      },
      "EmailDetail": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "$ref": "#/components/schemas/EmailStatus"
          },
          "from": {
            "type": "string"
          },
          "subject": {
            "type": "string"
          },
          "sandbox": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "recipients": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "type": {
                  "type": "string",
                  "enum": [
                    "to",
                    "cc",
                    "bcc"
                  ]
                },
                "address": {
                  "type": "string",
                  "format": "email"
                },
                "status": {
                  "$ref": "#/components/schemas/EmailStatus"
                }
              }
            }
          },
          "events": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "type": {
                  "type": "string"
                },
                "occurredAt": {
                  "type": "string",
                  "format": "date-time"
                },
                "providerResponse": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            }
          }
        }
      },
      "Domain": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "domain": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "verifying",
              "verified",
              "failed",
              "suspended"
            ]
          },
          "region": {
            "type": "string"
          },
          "verifiedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "DnsRecord": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "type": {
            "type": "string",
            "enum": [
              "MX",
              "SPF",
              "DKIM",
              "DMARC",
              "RETURN_PATH",
              "TRACKING"
            ]
          },
          "host": {
            "type": "string"
          },
          "value": {
            "type": "string"
          },
          "ttl": {
            "type": "integer"
          },
          "verified": {
            "type": "boolean"
          },
          "checkedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "DomainWithRecords": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Domain"
          },
          {
            "type": "object",
            "properties": {
              "records": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/DnsRecord"
                }
              }
            }
          }
        ]
      },
      "Suppression": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "address": {
            "type": "string"
          },
          "scope": {
            "type": "string",
            "enum": [
              "global",
              "tenant",
              "domain",
              "recipient"
            ]
          },
          "reason": {
            "type": "string",
            "enum": [
              "bounce",
              "complaint",
              "invalid",
              "manual"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebhookEventType": {
        "type": "string",
        "enum": [
          "email.queued",
          "email.scheduled",
          "email.sent",
          "email.delivered",
          "email.delivery_delayed",
          "email.bounced",
          "email.complained",
          "email.opened",
          "email.clicked",
          "email.failed",
          "email.received",
          "domain.created",
          "domain.verified",
          "domain.failed"
        ]
      },
      "WebhookEndpoint": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "enabled": {
            "type": "boolean"
          },
          "eventTypes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookEventType"
            }
          },
          "secret": {
            "type": "string",
            "description": "Plaintext at create/rotate only; `whsec_***` everywhere else."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebhookDelivery": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "endpointId": {
            "type": "string",
            "format": "uuid"
          },
          "eventId": {
            "type": "string"
          },
          "eventType": {
            "$ref": "#/components/schemas/WebhookEventType"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "delivered",
              "failed",
              "dead",
              "blocked"
            ]
          },
          "attempts": {
            "type": "integer"
          },
          "responseCode": {
            "type": [
              "integer",
              "null"
            ]
          },
          "nextRetryAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "deliveredAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "ApiKeyCreated": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "prefix": {
            "type": "string",
            "description": "16 hex characters."
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "token": {
            "type": "string",
            "description": "One-time plaintext, `mf_live_<prefix>.<secret>`."
          },
          "lastUsedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "revokedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      }
    }
  }
}