{
    "openapi": "3.0.3",
    "info": {
        "title": "Mailerjson API",
        "version": "1.0.0",
        "description": "Send transactional email with a single HTTP call.\n\nEvery email costs 1 credit. If an email is not sent because of a problem on our side or with the email provider, the credit is refunded automatically.\n\nRequests and responses are JSON. Errors always have the same shape, `{ \"error\": { \"code\": \"...\", \"message\": \"...\" } }`, so you can branch on `error.code`.\n\nThere is no idempotency key yet. If a request times out without any response, the email may or may not have been sent, so check before sending it again."
    },
    "servers": [
        { "url": "https://api.mailerjson.com", "description": "Production" }
    ],
    "security": [
        { "ApiKey": [] }
    ],
    "tags": [
        { "name": "Emails", "description": "Send an email and look it up afterwards." }
    ],
    "paths": {
        "/v1/send": {
            "post": {
                "operationId": "sendEmail",
                "tags": ["Emails"],
                "summary": "Send an email",
                "description": "Sends one email to one recipient and uses 1 credit.\n\nEverything is validated before anything is charged, so a request rejected for a bad field never costs a credit. A credit is also refunded when the email provider cannot accept the message.",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": { "$ref": "#/components/schemas/SendEmailRequest" },
                            "examples": {
                                "htmlAndText": {
                                    "summary": "HTML with a plain-text fallback",
                                    "value": {
                                        "from": "Acme <hello@mailerjson.com>",
                                        "to": "customer@example.com",
                                        "subject": "Welcome to Acme",
                                        "html": "<p>Thanks for signing up.</p>",
                                        "text": "Thanks for signing up.",
                                        "reply_to": "support@example.com"
                                    }
                                },
                                "textOnly": {
                                    "summary": "Plain text only",
                                    "value": {
                                        "from": "hello@mailerjson.com",
                                        "to": "customer@example.com",
                                        "subject": "Your code is 482913",
                                        "text": "Your verification code is 482913."
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The email was accepted for delivery and 1 credit was used.",
                        "content": {
                            "application/json": {
                                "schema": { "$ref": "#/components/schemas/SendEmailResponse" },
                                "example": {
                                    "id": "b0ab8e41-4701-4991-8610-5609e750149f",
                                    "message_id": "011001a124c47f3f-53ebfcc9-14ce-4010-bb48-5eb9af248c74-000000",
                                    "credits_remaining": 499
                                }
                            }
                        }
                    },
                    "400": { "$ref": "#/components/responses/InvalidJson" },
                    "401": { "$ref": "#/components/responses/InvalidApiKey" },
                    "402": { "$ref": "#/components/responses/InsufficientCredits" },
                    "403": { "$ref": "#/components/responses/Forbidden" },
                    "405": { "$ref": "#/components/responses/MethodNotAllowed" },
                    "413": { "$ref": "#/components/responses/PayloadTooLarge" },
                    "422": { "$ref": "#/components/responses/Unprocessable" },
                    "429": { "$ref": "#/components/responses/RateLimited" },
                    "500": { "$ref": "#/components/responses/InternalError" },
                    "502": { "$ref": "#/components/responses/ProviderUnavailable" }
                }
            }
        },
        "/v1/emails/{id}": {
            "get": {
                "operationId": "getEmail",
                "tags": ["Emails"],
                "summary": "Get an email",
                "description": "Returns an email that was sent with one of your workspace's keys. Emails from other workspaces are reported as not found.",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The `id` returned by `POST /v1/send`.",
                        "schema": { "type": "string" },
                        "example": "b0ab8e41-4701-4991-8610-5609e750149f"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The email.",
                        "content": {
                            "application/json": {
                                "schema": { "$ref": "#/components/schemas/Email" },
                                "example": {
                                    "id": "b0ab8e41-4701-4991-8610-5609e750149f",
                                    "to": "customer@example.com",
                                    "from": "Acme <hello@mailerjson.com>",
                                    "subject": "Welcome to Acme",
                                    "status": "sent",
                                    "message_id": "011001a124c47f3f-53ebfcc9-14ce-4010-bb48-5eb9af248c74-000000",
                                    "error": null,
                                    "created_at": 1791618219
                                }
                            }
                        }
                    },
                    "401": { "$ref": "#/components/responses/InvalidApiKey" },
                    "404": { "$ref": "#/components/responses/NotFound" },
                    "405": { "$ref": "#/components/responses/MethodNotAllowed" },
                    "500": { "$ref": "#/components/responses/InternalError" }
                }
            }
        }
    },
    "components": {
        "securitySchemes": {
            "ApiKey": {
                "type": "http",
                "scheme": "bearer",
                "bearerFormat": "mj_...",
                "description": "Your API key, sent as `Authorization: Bearer mj_...`. Create keys in the dashboard under Settings, API Keys. A key is shown once when you create it and cannot be shown again. Keep it on your server, never in a browser or mobile app."
            }
        },
        "schemas": {
            "SendEmailRequest": {
                "type": "object",
                "required": ["from", "to", "subject"],
                "anyOf": [
                    { "required": ["html"] },
                    { "required": ["text"] }
                ],
                "properties": {
                    "from": {
                        "type": "string",
                        "description": "The sender, as `address@domain` or `Display Name <address@domain>`. The display name must be plain ASCII, up to 100 characters, with no quotes, angle brackets or backslashes. The domain must be enabled for sending. For now that is `mailerjson.com`.",
                        "example": "Acme <hello@mailerjson.com>"
                    },
                    "to": {
                        "type": "string",
                        "format": "email",
                        "description": "One recipient address. Lists of recipients are not supported yet.",
                        "example": "customer@example.com"
                    },
                    "subject": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 200,
                        "description": "The subject line, 1 to 200 characters, on a single line.",
                        "example": "Welcome to Acme"
                    },
                    "html": {
                        "type": "string",
                        "maxLength": 262144,
                        "description": "The HTML body, up to 262,144 characters. Send `html`, `text`, or both."
                    },
                    "text": {
                        "type": "string",
                        "maxLength": 262144,
                        "description": "The plain-text body, up to 262,144 characters. Send `html`, `text`, or both."
                    },
                    "reply_to": {
                        "type": "string",
                        "format": "email",
                        "description": "Optional. Where replies should go."
                    }
                }
            },
            "SendEmailResponse": {
                "type": "object",
                "required": ["id", "message_id", "credits_remaining"],
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "Our id for this email. Use it with `GET /v1/emails/{id}`."
                    },
                    "message_id": {
                        "type": "string",
                        "description": "The email provider's id for the message. Useful when you need to ask about a delivery."
                    },
                    "credits_remaining": {
                        "type": "integer",
                        "description": "Your workspace's credit balance after this email."
                    }
                }
            },
            "Email": {
                "type": "object",
                "required": ["id", "to", "from", "subject", "status", "message_id", "error", "created_at"],
                "properties": {
                    "id": { "type": "string" },
                    "to": { "type": "string" },
                    "from": { "type": "string" },
                    "subject": { "type": "string" },
                    "status": {
                        "type": "string",
                        "enum": ["sent", "failed"],
                        "description": "`sent` means the provider accepted the message. `failed` means it did not, and no credit was used."
                    },
                    "message_id": {
                        "type": "string",
                        "nullable": true,
                        "description": "The email provider's id. Null when the email failed."
                    },
                    "error": {
                        "type": "string",
                        "nullable": true,
                        "description": "Why it failed. Null when the email was sent."
                    },
                    "created_at": {
                        "type": "integer",
                        "description": "When the email was created, as a Unix timestamp in seconds."
                    }
                }
            },
            "Error": {
                "type": "object",
                "required": ["error"],
                "properties": {
                    "error": {
                        "type": "object",
                        "required": ["code", "message"],
                        "properties": {
                            "code": {
                                "type": "string",
                                "description": "A stable, machine-readable code. Branch on this, not on the message.",
                                "enum": [
                                    "invalid_json",
                                    "invalid_api_key",
                                    "insufficient_credits",
                                    "account_disabled",
                                    "from_domain_not_allowed",
                                    "method_not_allowed",
                                    "payload_too_large",
                                    "validation_error",
                                    "message_rejected",
                                    "rate_limited",
                                    "not_found",
                                    "internal_error",
                                    "provider_unavailable"
                                ]
                            },
                            "message": {
                                "type": "string",
                                "description": "A human-readable explanation. The wording can change, so do not match on it."
                            }
                        }
                    }
                }
            }
        },
        "responses": {
            "InvalidJson": {
                "description": "The body is not a valid JSON object. Nothing was charged.",
                "content": {
                    "application/json": {
                        "schema": { "$ref": "#/components/schemas/Error" },
                        "example": { "error": { "code": "invalid_json", "message": "Request body must be valid JSON." } }
                    }
                }
            },
            "InvalidApiKey": {
                "description": "The API key is missing, wrong, or has been revoked.",
                "content": {
                    "application/json": {
                        "schema": { "$ref": "#/components/schemas/Error" },
                        "example": { "error": { "code": "invalid_api_key", "message": "Missing or invalid API key." } }
                    }
                }
            },
            "InsufficientCredits": {
                "description": "The workspace has no credits left. Add credits in the dashboard.",
                "content": {
                    "application/json": {
                        "schema": { "$ref": "#/components/schemas/Error" },
                        "example": { "error": { "code": "insufficient_credits", "message": "Not enough credits. Top up to keep sending." } }
                    }
                }
            },
            "Forbidden": {
                "description": "The request is understood but not allowed. Nothing was charged.",
                "content": {
                    "application/json": {
                        "schema": { "$ref": "#/components/schemas/Error" },
                        "examples": {
                            "accountDisabled": {
                                "summary": "The workspace is disabled",
                                "value": { "error": { "code": "account_disabled", "message": "This account is disabled." } }
                            },
                            "fromDomainNotAllowed": {
                                "summary": "The sender domain is not enabled",
                                "value": { "error": { "code": "from_domain_not_allowed", "message": "Sending from \"example.org\" is not allowed." } }
                            }
                        }
                    }
                }
            },
            "MethodNotAllowed": {
                "description": "The route exists but not for this HTTP method.",
                "content": {
                    "application/json": {
                        "schema": { "$ref": "#/components/schemas/Error" },
                        "example": { "error": { "code": "method_not_allowed", "message": "Use POST for this route." } }
                    }
                }
            },
            "PayloadTooLarge": {
                "description": "The request body is too large. Nothing was charged.",
                "content": {
                    "application/json": {
                        "schema": { "$ref": "#/components/schemas/Error" },
                        "example": { "error": { "code": "payload_too_large", "message": "Request body is too large." } }
                    }
                }
            },
            "Unprocessable": {
                "description": "The request was understood but cannot be sent. No credit was used.",
                "content": {
                    "application/json": {
                        "schema": { "$ref": "#/components/schemas/Error" },
                        "examples": {
                            "validationError": {
                                "summary": "A field is invalid",
                                "value": { "error": { "code": "validation_error", "message": "\"to\" must be a valid email address." } }
                            },
                            "messageRejected": {
                                "summary": "The email provider rejected the message",
                                "value": { "error": { "code": "message_rejected", "message": "The provider rejected this message." } }
                            }
                        }
                    }
                }
            },
            "RateLimited": {
                "description": "You are sending faster than the email provider allows. No credit was used. Wait for the number of seconds in `Retry-After`, then retry.",
                "headers": {
                    "Retry-After": {
                        "description": "Seconds to wait before retrying.",
                        "schema": { "type": "integer", "example": 1 }
                    }
                },
                "content": {
                    "application/json": {
                        "schema": { "$ref": "#/components/schemas/Error" },
                        "example": { "error": { "code": "rate_limited", "message": "Sending too fast. Retry in a moment. Your credit was refunded." } }
                    }
                }
            },
            "ProviderUnavailable": {
                "description": "The email provider is temporarily unavailable. The credit was refunded. Retry after a short delay.",
                "content": {
                    "application/json": {
                        "schema": { "$ref": "#/components/schemas/Error" },
                        "example": { "error": { "code": "provider_unavailable", "message": "The email provider is temporarily unavailable. Your credit was refunded, please retry." } }
                    }
                }
            },
            "NotFound": {
                "description": "No email with this id exists for your workspace.",
                "content": {
                    "application/json": {
                        "schema": { "$ref": "#/components/schemas/Error" },
                        "example": { "error": { "code": "not_found", "message": "Email not found." } }
                    }
                }
            },
            "InternalError": {
                "description": "An unexpected failure on our side. Retry later, and check your balance if a credit looks wrong.",
                "content": {
                    "application/json": {
                        "schema": { "$ref": "#/components/schemas/Error" },
                        "example": { "error": { "code": "internal_error", "message": "Something went wrong on our side." } }
                    }
                }
            }
        }
    }
}
