{
  "openapi": "3.1.0",
  "info": {
    "title": "InboxDome API",
    "version": "1.0.0",
    "description": "Disposable inboxes for email testing: create inboxes, receive mail, wait for OTPs, download attachments, and get signed webhooks.",
    "termsOfService": "https://inboxdome.com/legal/api-terms"
  },
  "servers": [{ "url": "https://inboxdome.com" }],
  "security": [{ "apiKey": [] }],
  "components": {
    "securitySchemes": {
      "apiKey": { "type": "http", "scheme": "bearer", "description": "API key (idk_live_...)" }
    },
    "schemas": {
      "Inbox": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "example": "inb_x3k2..." },
          "emailAddress": { "type": "string", "example": "qa.7f2k@mail.inboxdome.com" },
          "createdAt": { "type": "string", "format": "date-time" },
          "expiresAt": { "type": "string", "format": "date-time" },
          "messageCount": { "type": "integer" }
        }
      },
      "MessageSummary": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "from": { "type": "object", "properties": { "name": { "type": ["string", "null"] }, "address": { "type": ["string", "null"] } } },
          "subject": { "type": ["string", "null"] },
          "preview": { "type": ["string", "null"] },
          "receivedAt": { "type": "string", "format": "date-time" },
          "hasAttachments": { "type": "boolean" },
          "hasOtp": { "type": "boolean" }
        }
      },
      "Assertion": {
        "type": "object",
        "required": ["type"],
        "properties": {
          "type": { "type": "string", "enum": ["otpPresent", "containsText", "linkResponds", "auth"] },
          "text": { "type": "string", "description": "containsText: required substring (subject or body)" },
          "urlContains": { "type": "string", "description": "linkResponds: only try links containing this" },
          "check": { "type": "string", "enum": ["spf", "dkim", "dmarc"], "description": "auth: mechanism to check" },
          "expect": { "type": "string", "description": "auth: expected result (default \"pass\")" }
        }
      },
      "AssertionRun": {
        "type": "object",
        "properties": {
          "passed": { "type": "boolean" },
          "arrived": { "type": "boolean" },
          "arrivalSeconds": { "type": ["number", "null"] },
          "results": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": { "type": { "type": "string" }, "passed": { "type": "boolean" }, "detail": { "type": "string" } }
            }
          },
          "message": { "type": ["object", "null"], "properties": { "id": { "type": "string" }, "subject": { "type": ["string", "null"] }, "receivedAt": { "type": "string" } } }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": { "type": { "type": "string" }, "code": { "type": "string" }, "message": { "type": "string" } }
          }
        }
      }
    }
  },
  "paths": {
    "/v1/accounts": {
      "post": {
        "summary": "Register an account (returns your API key once)",
        "security": [],
        "requestBody": {
          "content": { "application/json": { "schema": { "type": "object", "required": ["email"], "properties": { "email": { "type": "string" }, "name": { "type": "string" } } } } }
        },
        "responses": { "201": { "description": "Account created; apiKey shown once." }, "409": { "description": "Email already registered." } }
      }
    },
    "/v1/account": { "get": { "summary": "Account info, plan limits, today's usage", "responses": { "200": { "description": "OK" } } } },
    "/v1/usage": { "get": { "summary": "Daily request/inbox usage", "parameters": [{ "name": "days", "in": "query", "schema": { "type": "integer", "maximum": 90 } }], "responses": { "200": { "description": "OK" } } } },
    "/v1/keys/rotate": { "post": { "summary": "Rotate the API key (old key stops working)", "responses": { "200": { "description": "New key, shown once." } } } },
    "/v1/keys": {
      "post": {
        "summary": "Create a named team key (environment live/test, role admin/member). Admin only.",
        "requestBody": { "content": { "application/json": { "schema": { "type": "object", "required": ["name"], "properties": { "name": { "type": "string" }, "environment": { "type": "string", "enum": ["live", "test"] }, "role": { "type": "string", "enum": ["admin", "member"] } } } } } },
        "responses": { "201": { "description": "Key created; apiKey shown once." }, "403": { "description": "Member keys cannot manage keys." } }
      },
      "get": { "summary": "List active keys", "responses": { "200": { "description": "OK" } } }
    },
    "/v1/keys/{id}": {
      "delete": { "summary": "Revoke a key immediately. Admin only.", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }], "responses": { "204": { "description": "Revoked" } } }
    },
    "/v1/domains": {
      "get": { "summary": "List selectable receiving domains (public + your active custom domains)", "responses": { "200": { "description": "OK" } } },
      "post": {
        "summary": "Register a bring-your-own domain (returns TXT verification record). Admin only.",
        "requestBody": { "content": { "application/json": { "schema": { "type": "object", "required": ["domain"], "properties": { "domain": { "type": "string" } } } } } },
        "responses": { "201": { "description": "Registered; add the returned TXT record, then verify." }, "409": { "description": "Domain already registered." } }
      }
    },
    "/v1/domains/custom": {
      "get": { "summary": "List your custom domains with verification state", "responses": { "200": { "description": "OK" } } }
    },
    "/v1/domains/{domain}/verify": {
      "post": { "summary": "Check the ownership TXT record via DNS", "parameters": [{ "name": "domain", "in": "path", "required": true, "schema": { "type": "string" } }], "responses": { "200": { "description": "Verified — activation follows onboarding." }, "422": { "description": "TXT record not found yet." } } }
    },
    "/v1/inboxes/{id}/assert": {
      "post": {
        "summary": "Wait for an email and run assertions (OTP, content, links respond, SPF/DKIM/DMARC)",
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }],
        "requestBody": { "content": { "application/json": { "schema": { "type": "object", "required": ["assertions"], "properties": { "assertions": { "type": "array", "items": { "$ref": "#/components/schemas/Assertion" } }, "timeoutSeconds": { "type": "integer", "maximum": 50, "default": 30 }, "since": { "type": "string", "format": "date-time" } } } } } },
        "responses": { "200": { "description": "Assertion report (check `passed`)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AssertionRun" } } } } }
      }
    },
    "/v1/scenarios": {
      "post": {
        "summary": "Save a reusable named assertion set",
        "requestBody": { "content": { "application/json": { "schema": { "type": "object", "required": ["name", "assertions"], "properties": { "name": { "type": "string" }, "assertions": { "type": "array", "items": { "$ref": "#/components/schemas/Assertion" } }, "timeoutSeconds": { "type": "integer", "maximum": 50 } } } } } },
        "responses": { "201": { "description": "Created" } }
      },
      "get": { "summary": "List scenarios", "responses": { "200": { "description": "OK" } } }
    },
    "/v1/scenarios/{id}": {
      "delete": { "summary": "Delete a scenario", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }], "responses": { "204": { "description": "Deleted" } } }
    },
    "/v1/scenarios/{id}/run": {
      "post": {
        "summary": "Run a scenario against an inbox",
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }],
        "requestBody": { "content": { "application/json": { "schema": { "type": "object", "required": ["inboxId"], "properties": { "inboxId": { "type": "string" }, "since": { "type": "string", "format": "date-time" } } } } } },
        "responses": { "200": { "description": "Assertion report", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AssertionRun" } } } } }
      }
    },
    "/v1/inboxes": {
      "post": {
        "summary": "Create an inbox",
        "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "domain": { "type": "string", "description": "domain name or \"smart\"" }, "localPart": { "type": "string" }, "ttlSeconds": { "type": "integer", "description": "600–604800 (default 86400)" } } } } } },
        "responses": { "201": { "description": "Created", "content": { "application/json": { "schema": { "type": "object", "properties": { "inbox": { "$ref": "#/components/schemas/Inbox" } } } } } }, "429": { "description": "Daily plan limit reached" } }
      },
      "get": { "summary": "List your active inboxes", "responses": { "200": { "description": "OK" } } }
    },
    "/v1/inboxes/{id}": {
      "get": { "summary": "Get an inbox", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }], "responses": { "200": { "description": "OK" }, "404": { "description": "Not found / not yours" } } },
      "delete": { "summary": "Delete an inbox and all content", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }], "responses": { "204": { "description": "Deleted" } } }
    },
    "/v1/inboxes/{id}/messages": {
      "get": {
        "summary": "List messages (newest first, cursor pagination)",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } },
          { "name": "cursor", "in": "query", "schema": { "type": "string" } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "maximum": 100 } }
        ],
        "responses": { "200": { "description": "OK" } }
      }
    },
    "/v1/inboxes/{id}/messages/{messageId}": {
      "get": { "summary": "Full message: text, sanitized HTML, OTP, links, attachments", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "messageId", "in": "path", "required": true, "schema": { "type": "string" } }], "responses": { "200": { "description": "OK" } } }
    },
    "/v1/inboxes/{id}/messages/{messageId}/attachments/{attachmentId}": {
      "get": { "summary": "Download an allowed attachment", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "messageId", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "attachmentId", "in": "path", "required": true, "schema": { "type": "string" } }], "responses": { "200": { "description": "Binary body" }, "403": { "description": "Blocked/quarantined attachment" } } }
    },
    "/v1/inboxes/{id}/wait": {
      "get": {
        "summary": "Long-poll until a message (or OTP) arrives",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } },
          { "name": "for", "in": "query", "schema": { "type": "string", "enum": ["message", "otp"] } },
          { "name": "timeoutSeconds", "in": "query", "schema": { "type": "integer", "maximum": 50, "default": 30 } },
          { "name": "since", "in": "query", "schema": { "type": "string", "format": "date-time" } }
        ],
        "responses": { "200": { "description": "Message arrived (otp field set when detected)" }, "408": { "description": "Nothing arrived in time" } }
      }
    },
    "/v1/webhooks": {
      "post": { "summary": "Add a webhook (message.received). Secret returned once.", "requestBody": { "content": { "application/json": { "schema": { "type": "object", "required": ["url"], "properties": { "url": { "type": "string", "description": "https:// only" } } } } } }, "responses": { "201": { "description": "Created" } } },
      "get": { "summary": "List webhooks", "responses": { "200": { "description": "OK" } } }
    },
    "/v1/webhooks/{id}": {
      "delete": { "summary": "Remove a webhook", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }], "responses": { "204": { "description": "Deleted" } } }
    },
    "/v1/webhooks/deliveries": {
      "get": { "summary": "Recent webhook delivery log", "responses": { "200": { "description": "OK" } } }
    }
  }
}
