{
    "openapi": "3.1.0",
    "info": {
        "title": "grabmail",
        "version": "1.0.0",
        "summary": "Disposable email addresses with a REST API. No account, no key, no payment.",
        "description": "grabmail hands out throwaway email addresses and lets you read what arrives at them over HTTP.\n\nThere is nothing to create: an address exists the moment mail reaches it. Pick any local part on one of the public domains (grabmail.io, mixozia.com, linqmail.com, uvorion.com), use it, then poll GET /api/v1/mailbox.\n\nNo account, no API key and no payment are required for the public domains. Bring your own domain by pointing its MX at smtp.grabmail.io; that one is private and is read with a bearer key.\n\nMessages are deleted 5 days after they arrive, and attachments are capped at 5 MB. Anyone who guesses a public address can read it, so never send anything confidential to one.",
        "contact": {
            "url": "https://grabmail.io/docs/api"
        },
        "license": {
            "name": "Free to use",
            "url": "https://grabmail.io/legal/terms"
        }
    },
    "servers": [
        {
            "url": "https://grabmail.io",
            "description": "Production"
        }
    ],
    "externalDocs": {
        "url": "https://grabmail.io/docs/api",
        "description": "Reference with examples"
    },
    "tags": [
        {
            "name": "Mailbox",
            "description": "Read and empty a disposable inbox."
        }
    ],
    "security": [
        [],
        {
            "bearerAuth": []
        }
    ],
    "components": {
        "securitySchemes": {
            "bearerAuth": {
                "type": "http",
                "scheme": "bearer",
                "description": "Only for a domain you connected yourself. The public domains need no credential at all."
            }
        },
        "schemas": {
            "MessageSummary": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "example": "7ZK3QW1M8T5VDR0YXC2NHB4JPE",
                        "description": "Opaque message id. Use it with /message and /attachment."
                    },
                    "from": {
                        "type": "string",
                        "format": "email",
                        "description": "Envelope sender."
                    },
                    "from_name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Display name, when the sender set one."
                    },
                    "subject": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "date": {
                        "type": "string",
                        "format": "date-time",
                        "description": "When it arrived, UTC."
                    },
                    "seen": {
                        "type": "boolean",
                        "description": "True once the message has been read through the API."
                    },
                    "attachments": {
                        "type": "integer",
                        "description": "How many attachments it carries."
                    },
                    "expires_at": {
                        "type": "string",
                        "format": "date-time",
                        "description": "When it will be deleted: 5 days after it arrived."
                    }
                },
                "required": [
                    "id",
                    "from",
                    "date",
                    "seen",
                    "attachments",
                    "expires_at"
                ]
            },
            "Message": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "example": "7ZK3QW1M8T5VDR0YXC2NHB4JPE",
                        "description": "Opaque message id. Use it with /message and /attachment."
                    },
                    "from": {
                        "type": "string",
                        "format": "email",
                        "description": "Envelope sender."
                    },
                    "from_name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Display name, when the sender set one."
                    },
                    "subject": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "date": {
                        "type": "string",
                        "format": "date-time",
                        "description": "When it arrived, UTC."
                    },
                    "seen": {
                        "type": "boolean",
                        "description": "True once the message has been read through the API."
                    },
                    "attachments": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "properties": {
                                "id": {
                                    "type": "string"
                                },
                                "filename": {
                                    "type": "string"
                                },
                                "mime": {
                                    "type": "string",
                                    "description": "What the sender claimed. Do not trust it."
                                },
                                "size": {
                                    "type": "integer"
                                },
                                "url": {
                                    "type": "string",
                                    "description": "Always served as a download, never inline."
                                }
                            }
                        }
                    },
                    "expires_at": {
                        "type": "string",
                        "format": "date-time",
                        "description": "When it will be deleted: 5 days after it arrived."
                    },
                    "to": {
                        "type": "string",
                        "format": "email"
                    },
                    "text": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Plain-text part, if the sender included one."
                    },
                    "html": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "HTML part. Never render it unsandboxed."
                    }
                }
            },
            "Error": {
                "type": "object",
                "properties": {
                    "error": {
                        "type": "string",
                        "example": "rate_limited"
                    },
                    "message": {
                        "type": "string"
                    }
                },
                "required": [
                    "error",
                    "message"
                ]
            }
        },
        "parameters": {
            "Mailbox": {
                "name": "mailbox",
                "in": "query",
                "required": true,
                "schema": {
                    "type": "string",
                    "format": "email"
                },
                "example": "a7f3k2@grabmail.io",
                "description": "The address the message was delivered to. Scopes the id, so an id alone is not enough."
            }
        },
        "responses": {
            "RateLimited": {
                "description": "Too many requests. One read per second per address, 1200 per 60s per client. Retry-After says how long to wait.",
                "headers": {
                    "Retry-After": {
                        "schema": {
                            "type": "integer"
                        },
                        "description": "Seconds."
                    }
                },
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/Error"
                        }
                    }
                }
            },
            "BadAddress": {
                "description": "The address is missing or malformed.",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/Error"
                        }
                    }
                }
            },
            "NotHosted": {
                "description": "That domain is not hosted here. Check the MX record, or use a public domain.",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/Error"
                        }
                    }
                }
            }
        }
    },
    "paths": {
        "/api/v1/mailbox": {
            "get": {
                "operationId": "listMessages",
                "tags": [
                    "Mailbox"
                ],
                "summary": "List the messages waiting at an address",
                "description": "Newest first. An empty mailbox is a 200 with count 0, never a 404, so a polling loop needs no special case.\n\nOne call returns at most 200 messages; `next` carries a cursor for the page after that, and is null once there is nothing older.",
                "parameters": [
                    {
                        "name": "address",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "format": "email"
                        },
                        "example": "a7f3k2@grabmail.io",
                        "description": "Any local part on a hosted domain. It does not need to exist first."
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 200,
                            "default": 50
                        },
                        "description": "How many to return in this call. Caps the response, not the mailbox."
                    },
                    {
                        "name": "before",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Cursor: pass back the `next` value from the previous page."
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The mailbox was read.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "address": {
                                            "type": "string",
                                            "format": "email"
                                        },
                                        "count": {
                                            "type": "integer",
                                            "description": "How many are in THIS response."
                                        },
                                        "next": {
                                            "type": [
                                                "string",
                                                "null"
                                            ],
                                            "description": "Cursor for the next page, or null."
                                        },
                                        "messages": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/MessageSummary"
                                            }
                                        }
                                    },
                                    "required": [
                                        "address",
                                        "count",
                                        "messages"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/BadAddress"
                    },
                    "401": {
                        "description": "That domain is private. Send its key as a bearer token."
                    },
                    "404": {
                        "$ref": "#/components/responses/NotHosted"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v1/message/{id}": {
            "get": {
                "operationId": "readMessage",
                "tags": [
                    "Mailbox"
                ],
                "summary": "Read one message in full",
                "description": "Body, headers and attachment list. This is where a confirmation code will be.",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "$ref": "#/components/parameters/Mailbox"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The message.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Message"
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/BadAddress"
                    },
                    "404": {
                        "description": "No such message in that mailbox, or it has expired."
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "delete": {
                "operationId": "deleteMessage",
                "tags": [
                    "Mailbox"
                ],
                "summary": "Delete a message now",
                "description": "Idempotent: deleting twice still answers 200.",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "$ref": "#/components/parameters/Mailbox"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Deleted, or already gone."
                    },
                    "400": {
                        "$ref": "#/components/responses/BadAddress"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v1/attachment/{id}": {
            "get": {
                "operationId": "downloadAttachment",
                "tags": [
                    "Mailbox"
                ],
                "summary": "Download an attachment",
                "description": "Always served as application/octet-stream with Content-Disposition: attachment, whatever the sender declared. Never rendered inline.",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "$ref": "#/components/parameters/Mailbox"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The file.",
                        "content": {
                            "application/octet-stream": {
                                "schema": {
                                    "type": "string",
                                    "format": "binary"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No such attachment in that mailbox."
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        }
    },
    "x-mcp": {
        "endpoint": "https://grabmail.io/mcp",
        "transport": "streamable-http",
        "description": "The same service as MCP tools, for AI agents: create_inbox, wait_for_message, list_messages, read_message, delete_message, list_domains."
    },
    "x-public-domains": [
        "grabmail.io",
        "mixozia.com",
        "linqmail.com",
        "uvorion.com"
    ],
    "x-retention-days": 5,
    "x-requires-auth": false
}