{
  "openapi": "3.1.0",
  "info": {
    "title": "OTPBox API",
    "version": "1",
    "description": "Disposable e-mail inboxes for AI agents. Every capability is also an MCP tool at /mcp (see /docs). Authenticate with an OTPBox API key (created in the web UI, `Authorization: Bearer obx_...`) or an OAuth access token from this server's authorization server (`obxa_...`). Each operation lists the OAuth scope it needs; API keys carry every scope.",
    "license": {
      "name": "Proprietary"
    }
  },
  "servers": [
    {
      "url": "https://otpbox.rc.center"
    }
  ],
  "tags": [
    {
      "name": "inboxes"
    },
    {
      "name": "messages"
    },
    {
      "name": "account"
    }
  ],
  "paths": {
    "/v1/domains": {
      "get": {
        "operationId": "listDomains",
        "summary": "Domains you can create inboxes on",
        "tags": [
          "account"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "oauth": [
              "inboxes:read"
            ]
          }
        ],
        "x-oauth-scope": "inboxes:read",
        "responses": {
          "200": {
            "description": "Domains",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "domains": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/usage": {
      "get": {
        "operationId": "getUsage",
        "summary": "Plan quotas and usage",
        "tags": [
          "account"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "oauth": [
              "inboxes:read"
            ]
          }
        ],
        "x-oauth-scope": "inboxes:read",
        "responses": {
          "200": {
            "description": "Usage",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Usage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/inboxes": {
      "get": {
        "operationId": "listInboxes",
        "summary": "List active inboxes",
        "tags": [
          "inboxes"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "oauth": [
              "inboxes:read"
            ]
          }
        ],
        "x-oauth-scope": "inboxes:read",
        "responses": {
          "200": {
            "description": "Inboxes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "inboxes": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Inbox"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "post": {
        "operationId": "createInbox",
        "summary": "Create an inbox",
        "tags": [
          "inboxes"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "oauth": [
              "inboxes:write"
            ]
          }
        ],
        "x-oauth-scope": "inboxes:write",
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Inbox"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "Inbox limit of the plan reached",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "description": "The address is <prefix>.<random>@<account>.<domain>; every account receives on its own subdomain.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "domain": {
                    "type": "string",
                    "examples": [
                      "otpbox.org"
                    ]
                  },
                  "prefix": {
                    "type": "string",
                    "pattern": "^[a-z0-9]([a-z0-9-]{0,22}[a-z0-9])?$",
                    "examples": [
                      "signup"
                    ]
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes/{id}": {
      "get": {
        "operationId": "getInbox",
        "summary": "Get an inbox",
        "tags": [
          "inboxes"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "oauth": [
              "inboxes:read"
            ]
          }
        ],
        "x-oauth-scope": "inboxes:read",
        "responses": {
          "200": {
            "description": "Inbox",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Inbox"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Inbox id"
          }
        ]
      },
      "delete": {
        "operationId": "deleteInbox",
        "summary": "Delete an inbox and its messages",
        "tags": [
          "inboxes"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "oauth": [
              "inboxes:write"
            ]
          }
        ],
        "x-oauth-scope": "inboxes:write",
        "responses": {
          "200": {
            "description": "Deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Inbox id"
          }
        ]
      }
    },
    "/v1/inboxes/{id}/webhook": {
      "put": {
        "operationId": "setInboxWebhook",
        "summary": "Set the inbox webhook",
        "tags": [
          "inboxes"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "oauth": [
              "inboxes:write"
            ]
          }
        ],
        "x-oauth-scope": "inboxes:write",
        "responses": {
          "200": {
            "description": "Webhook set; the secret is shown once",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "url": {
                      "type": "string"
                    },
                    "secret": {
                      "type": "string"
                    },
                    "signature_header": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "description": "OTPBox POSTs a JSON event for every new message, signed with `OTPBox-Signature: t=<unix>,v1=<hex HMAC-SHA256(secret, t + \".\" + body)>`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Inbox id"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri"
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "clearInboxWebhook",
        "summary": "Remove the inbox webhook",
        "tags": [
          "inboxes"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "oauth": [
              "inboxes:write"
            ]
          }
        ],
        "x-oauth-scope": "inboxes:write",
        "responses": {
          "200": {
            "description": "Removed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Inbox id"
          }
        ]
      }
    },
    "/v1/inboxes/{id}/messages": {
      "get": {
        "operationId": "listMessages",
        "summary": "List messages, newest first",
        "tags": [
          "messages"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "oauth": [
              "messages:read"
            ]
          }
        ],
        "x-oauth-scope": "messages:read",
        "responses": {
          "200": {
            "description": "Messages",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "messages": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/MessageSummary"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Inbox id"
          },
          {
            "name": "since",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 200
            }
          }
        ]
      }
    },
    "/v1/inboxes/{id}/wait": {
      "get": {
        "operationId": "waitMessage",
        "summary": "Wait for a message (long poll)",
        "tags": [
          "messages"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "oauth": [
              "messages:read"
            ]
          }
        ],
        "x-oauth-scope": "messages:read",
        "responses": {
          "200": {
            "description": "found=true with the newest match, or found=false on timeout",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WaitResult"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Inbox id"
          },
          {
            "name": "timeout",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 120
            },
            "description": "Seconds (default 30)"
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "From contains (case-insensitive)"
          },
          {
            "name": "subject",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Subject contains (case-insensitive)"
          },
          {
            "name": "regex",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "RE2 matched against subject and text"
          },
          {
            "name": "since",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Default: the last 10 minutes"
          },
          {
            "name": "html",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            },
            "description": "Include the sanitized HTML"
          }
        ]
      }
    },
    "/v1/messages/{id}": {
      "get": {
        "operationId": "getMessage",
        "summary": "Get a message",
        "tags": [
          "messages"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "oauth": [
              "messages:read"
            ]
          }
        ],
        "x-oauth-scope": "messages:read",
        "responses": {
          "200": {
            "description": "Message",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageDetail"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Message id"
          },
          {
            "name": "html",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            }
          }
        ]
      },
      "delete": {
        "operationId": "deleteMessage",
        "summary": "Delete a message",
        "tags": [
          "messages"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "oauth": [
              "messages:write"
            ]
          }
        ],
        "x-oauth-scope": "messages:write",
        "responses": {
          "200": {
            "description": "Deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Message id"
          }
        ]
      }
    },
    "/v1/messages/{id}/attachments/{index}": {
      "get": {
        "operationId": "getAttachment",
        "summary": "Download an attachment",
        "tags": [
          "messages"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "oauth": [
              "messages:read"
            ]
          }
        ],
        "x-oauth-scope": "messages:read",
        "responses": {
          "200": {
            "description": "The attachment, always as a download",
            "content": {
              "application/octet-stream": {
                "schema": {
                  "type": "string",
                  "contentMediaType": "application/octet-stream"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Message id"
          },
          {
            "name": "index",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 0
            }
          }
        ]
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "OTPBox API key (obx_...) or OAuth access token (obxa_...)"
      },
      "oauth": {
        "type": "oauth2",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://otpbox.rc.center/oauth/authorize",
            "tokenUrl": "https://otpbox.rc.center/oauth/token",
            "refreshUrl": "https://otpbox.rc.center/oauth/token",
            "scopes": {
              "inboxes:read": "see inboxes and usage",
              "inboxes:write": "create and delete inboxes, set webhooks",
              "messages:read": "read messages, codes, links and attachments",
              "messages:write": "delete messages"
            }
          }
        }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Missing or invalid bearer token (WWW-Authenticate names the resource metadata)",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Forbidden": {
        "description": "plan_required, insufficient_scope, suspended or flagged",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "Unknown id (or another account's)",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "examples": [
              "plan_required"
            ]
          },
          "message": {
            "type": "string"
          }
        }
      },
      "Deleted": {
        "type": "object",
        "properties": {
          "deleted": {
            "type": "boolean"
          }
        }
      },
      "Inbox": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "address": {
            "type": "string",
            "examples": [
              "signup.k3m9qa@d6pzky9tv25q.otpbox.org"
            ]
          },
          "domain": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "webhook_url": {
            "type": "string"
          }
        }
      },
      "Counter": {
        "type": "object",
        "properties": {
          "used": {
            "type": "integer"
          },
          "limit": {
            "type": "integer",
            "description": "-1 is unlimited"
          },
          "remaining": {
            "type": "integer"
          },
          "percent": {
            "type": "number"
          }
        }
      },
      "Usage": {
        "type": "object",
        "properties": {
          "plan": {
            "type": "string"
          },
          "plan_status": {
            "type": "string"
          },
          "access": {
            "type": "boolean"
          },
          "receiving": {
            "type": "boolean"
          },
          "reason": {
            "type": "string"
          },
          "inboxes": {
            "$ref": "#/components/schemas/Counter"
          },
          "messages_this_month": {
            "$ref": "#/components/schemas/Counter"
          },
          "messages_last_minute": {
            "$ref": "#/components/schemas/Counter"
          },
          "stored_bytes": {
            "$ref": "#/components/schemas/Counter"
          },
          "max_message_bytes": {
            "type": "integer"
          },
          "retention_days": {
            "type": "integer"
          },
          "clamav": {
            "type": "boolean"
          },
          "month": {
            "type": "string"
          }
        }
      },
      "MessageSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "inbox_id": {
            "type": "string"
          },
          "received_at": {
            "type": "string",
            "format": "date-time"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "state": {
            "type": "string",
            "enum": [
              "stored",
              "ready",
              "failed"
            ]
          },
          "size": {
            "type": "integer"
          },
          "from": {
            "type": "string"
          },
          "subject": {
            "type": "string"
          },
          "codes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "one-time codes, best first"
          },
          "verify_link": {
            "type": "string"
          },
          "has_attachments": {
            "type": "boolean"
          },
          "flagged": {
            "type": "boolean"
          }
        }
      },
      "MessageDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/MessageSummary"
          },
          {
            "type": "object",
            "properties": {
              "to": {
                "type": "array",
                "items": {
                  "type": "object"
                }
              },
              "text": {
                "type": "string"
              },
              "html": {
                "type": "string",
                "description": "sanitized; only with html=1"
              },
              "code_candidates": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "value": {
                      "type": "string"
                    },
                    "context": {
                      "type": "string"
                    },
                    "score": {
                      "type": "integer"
                    }
                  }
                }
              },
              "links": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "url": {
                      "type": "string"
                    },
                    "text": {
                      "type": "string"
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "verify",
                        "unsubscribe",
                        "other"
                      ]
                    }
                  }
                }
              },
              "attachments": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "index": {
                      "type": "integer"
                    },
                    "filename": {
                      "type": "string"
                    },
                    "content_type": {
                      "type": "string"
                    },
                    "size": {
                      "type": "integer"
                    },
                    "flagged": {
                      "type": "boolean"
                    },
                    "risky": {
                      "type": "boolean",
                      "description": "The file can run code when opened (program, script, installer, macros, a zip holding one, a double extension, or a declared type that does not match the name). Independent of the virus scan; downloads are still allowed."
                    },
                    "risk_reason": {
                      "type": "string",
                      "enum": [
                        "executable",
                        "double_extension",
                        "disguised_executable",
                        "macros",
                        "may_contain_macros",
                        "archive_contains_executable",
                        "type_mismatch"
                      ]
                    },
                    "risk_detail": {
                      "type": "string",
                      "description": "Context for the reason: the zip entry or the declared content type. Text from the message, untrusted."
                    }
                  }
                }
              },
              "auth": {
                "type": "object",
                "properties": {
                  "spf": {
                    "type": "string"
                  },
                  "dmarc": {
                    "type": "string"
                  },
                  "dkim": {
                    "type": "array",
                    "items": {
                      "type": "object"
                    }
                  }
                }
              },
              "envelope": {
                "type": "object"
              }
            }
          }
        ]
      },
      "WaitResult": {
        "type": "object",
        "properties": {
          "found": {
            "type": "boolean"
          },
          "codes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "verify_link": {
            "type": "string"
          },
          "message": {
            "$ref": "#/components/schemas/MessageDetail"
          }
        }
      }
    }
  }
}
