{
    "openapi": "3.1.0",
    "info": {
        "title": "Email Delivery Platform API",
        "version": "v1",
        "description": "Sending, deliverability and tracking API. Reseller endpoints add sub-accounts, credits and the embedded designer."
    },
    "servers": [
        {
            "url": "http://127.0.0.1:8226/api/v1"
        }
    ],
    "components": {
        "securitySchemes": {
            "bearerAuth": {
                "type": "http",
                "scheme": "bearer",
                "description": "Tenant or master API key."
            },
            "embedToken": {
                "type": "apiKey",
                "in": "header",
                "name": "X-Embed-Token",
                "description": "Signed, merchant-scoped embedded-designer token."
            }
        },
        "parameters": {
            "SubAccount": {
                "name": "X-Sub-Account",
                "in": "header",
                "required": false,
                "schema": {
                    "type": "string"
                },
                "description": "Reseller: act as a specific merchant."
            },
            "IdempotencyKey": {
                "name": "Idempotency-Key",
                "in": "header",
                "required": false,
                "schema": {
                    "type": "string"
                },
                "description": "Retry-safe key for send/fund \u2014 a retry is never double-charged."
            }
        }
    },
    "security": [
        {
            "bearerAuth": []
        }
    ],
    "paths": {
        "/messages/send": {
            "post": {
                "summary": "Send a single transactional email",
                "tags": [
                    "Sending"
                ],
                "parameters": [
                    {
                        "$ref": "#/components/parameters/SubAccount"
                    },
                    {
                        "$ref": "#/components/parameters/IdempotencyKey"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "to": {
                                        "type": "string",
                                        "format": "email"
                                    },
                                    "subject": {
                                        "type": "string"
                                    },
                                    "html_body": {
                                        "type": "string"
                                    },
                                    "text_body": {
                                        "type": "string"
                                    },
                                    "merge_vars": {
                                        "type": "object"
                                    },
                                    "campaign_ref": {
                                        "type": "string"
                                    },
                                    "lane": {
                                        "type": "string",
                                        "enum": [
                                            "transactional",
                                            "promotional"
                                        ]
                                    },
                                    "customer_id": {
                                        "type": "string",
                                        "description": "Your stable id for the recipient \u2014 persisted, echoed on webhooks, slice reports by it."
                                    },
                                    "external_id": {
                                        "type": "string",
                                        "description": "Your per-message id \u2014 echoed on webhooks; idempotent (a repeat replays, never duplicates)."
                                    },
                                    "metadata": {
                                        "type": "object",
                                        "description": "Free-form tags; declared keys (config) become report axes. Echoed on webhooks."
                                    }
                                },
                                "required": [
                                    "to",
                                    "subject",
                                    "html_body"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "202": {
                        "description": "Accepted"
                    },
                    "402": {
                        "description": "Blocked \u2014 insufficient balance/credit"
                    }
                }
            }
        },
        "/messages/batch": {
            "post": {
                "summary": "Send a batch (<=50 recipients)",
                "tags": [
                    "Sending"
                ],
                "parameters": [
                    {
                        "$ref": "#/components/parameters/SubAccount"
                    },
                    {
                        "$ref": "#/components/parameters/IdempotencyKey"
                    }
                ],
                "responses": {
                    "202": {
                        "description": "Accepted"
                    }
                }
            }
        },
        "/messages/{id}/status": {
            "get": {
                "summary": "Message delivery status",
                "tags": [
                    "Sending"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/templates": {
            "get": {
                "summary": "List templates",
                "tags": [
                    "Templates"
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            },
            "post": {
                "summary": "Create a template",
                "tags": [
                    "Templates"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "name": {
                                        "type": "string"
                                    },
                                    "subject": {
                                        "type": "string"
                                    },
                                    "html_body": {
                                        "type": "string"
                                    },
                                    "design_json": {
                                        "type": "object",
                                        "description": "Drag-drop builder design document."
                                    }
                                },
                                "required": [
                                    "name",
                                    "subject",
                                    "html_body"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Created"
                    }
                }
            }
        },
        "/templates/{id}": {
            "get": {
                "summary": "Get a template",
                "tags": [
                    "Templates"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            },
            "put": {
                "summary": "Update / save-back a template (API key or embed token)",
                "description": "Accepts a merchant-scoped embed token to persist design_json + html_body from the embedded designer.",
                "tags": [
                    "Templates"
                ],
                "security": [
                    {
                        "bearerAuth": []
                    },
                    {
                        "embedToken": []
                    }
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "name": {
                                        "type": "string"
                                    },
                                    "subject": {
                                        "type": "string"
                                    },
                                    "html_body": {
                                        "type": "string"
                                    },
                                    "design_json": {
                                        "type": "object"
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/campaigns": {
            "get": {
                "summary": "List campaigns",
                "tags": [
                    "Campaigns"
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            },
            "post": {
                "summary": "Create a campaign",
                "tags": [
                    "Campaigns"
                ],
                "responses": {
                    "201": {
                        "description": "Created"
                    }
                }
            }
        },
        "/campaigns/{id}/estimate": {
            "get": {
                "summary": "Pre-send cost estimate + live balance",
                "description": "Returns estimated cost vs live balance + daily limit, and the projected sent/partial/blocked status.",
                "tags": [
                    "Campaigns"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/campaigns/{id}/send": {
            "post": {
                "summary": "Send a campaign (truthful status)",
                "description": "Enforces the pre-send credit gate; reports sent / partial / blocked, never a fake \"sent\".",
                "tags": [
                    "Campaigns"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "202": {
                        "description": "Sending or partial"
                    },
                    "402": {
                        "description": "Blocked \u2014 insufficient balance/limit"
                    }
                }
            }
        },
        "/partners/sub-accounts": {
            "get": {
                "summary": "List merchants",
                "tags": [
                    "Reseller"
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            },
            "post": {
                "summary": "Create a merchant",
                "tags": [
                    "Reseller"
                ],
                "responses": {
                    "201": {
                        "description": "Created"
                    }
                }
            }
        },
        "/partners/sub-accounts/{id}/fund": {
            "post": {
                "summary": "Fund a merchant wallet",
                "tags": [
                    "Reseller"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "$ref": "#/components/parameters/IdempotencyKey"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "amount_micros": {
                                        "type": "integer"
                                    }
                                },
                                "required": [
                                    "amount_micros"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/embed/designer/token": {
            "post": {
                "summary": "Mint an embedded designer token (master key)",
                "description": "Returns { url, token, expires_at } scoped to one merchant, ~10 min TTL.",
                "tags": [
                    "Embedded Designer"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "sub_account_id": {
                                        "type": "integer"
                                    },
                                    "template_id": {
                                        "type": "integer"
                                    },
                                    "branding": {
                                        "type": "object"
                                    },
                                    "return_url": {
                                        "type": "string",
                                        "format": "uri"
                                    }
                                },
                                "required": [
                                    "sub_account_id"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Token minted"
                    }
                }
            }
        },
        "/embed/designer/context": {
            "get": {
                "summary": "Embedded designer bootstrap context",
                "tags": [
                    "Embedded Designer"
                ],
                "security": [
                    {
                        "embedToken": []
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/api-keys": {
            "get": {
                "summary": "List this tenant's API keys",
                "description": "Prefixes and metadata only \u2014 the key hash is never serialized.",
                "tags": [
                    "API Keys"
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            },
            "post": {
                "summary": "Generate a new API key",
                "description": "The plaintext key is returned exactly once, in this response \u2014 it is never retrievable again.",
                "tags": [
                    "API Keys"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "label": {
                                        "type": "string"
                                    },
                                    "is_sandbox": {
                                        "type": "boolean"
                                    },
                                    "scopes": {
                                        "type": "array",
                                        "items": {
                                            "type": "string",
                                            "enum": [
                                                "send",
                                                "read",
                                                "manage"
                                            ]
                                        },
                                        "description": "Omit for full (unscoped) access."
                                    },
                                    "allowed_ips": {
                                        "type": "array",
                                        "items": {
                                            "type": "string"
                                        },
                                        "description": "CIDR or bare IP. Omit for no restriction."
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Created \u2014 plaintext key included"
                    }
                }
            }
        },
        "/api-keys/{id}/revoke": {
            "delete": {
                "summary": "Revoke an API key",
                "description": "Immediate and irreversible \u2014 a revoked key can never be un-revoked, only replaced by generating a new one.",
                "tags": [
                    "API Keys"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/webhooks": {
            "get": {
                "summary": "Get this tenant's webhook configuration",
                "description": "`secret` is reported as `\"set\"` or `null` \u2014 the plaintext signing secret is never returned by this endpoint.",
                "tags": [
                    "Webhooks"
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            },
            "put": {
                "summary": "Configure the webhook URL, mode, signing secret, and subscribed events",
                "description": "Sending `secret` rotates it (set-or-rotate \u2014 there is no separate rotate endpoint). Omit `events` to leave the subscription unchanged; `[]` subscribes to all events; a non-empty array subscribes to only those.",
                "tags": [
                    "Webhooks"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "url": {
                                        "type": "string",
                                        "format": "uri"
                                    },
                                    "mode": {
                                        "type": "string",
                                        "enum": [
                                            "centralized",
                                            "per_sub_account"
                                        ]
                                    },
                                    "secret": {
                                        "type": "string"
                                    },
                                    "events": {
                                        "type": "array",
                                        "items": {
                                            "type": "string"
                                        },
                                        "description": "e.g. message.delivery, whatsapp.delivered, push.clicked, otp.failed, campaign.completed."
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/webhooks/deliveries": {
            "get": {
                "summary": "Recent webhook delivery attempts",
                "description": "Paginated, newest first \u2014 status_code, attempt_count, and error_message per delivery.",
                "tags": [
                    "Webhooks"
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/health/lanes": {
            "get": {
                "summary": "Per-channel, per-lane queue depth",
                "description": "Lets a partner's failover logic detect a backed-up lane (e.g. OTP) and reroute before it times out. Depth is 0 on the sync queue driver \u2014 meaningful under Redis/database queues.",
                "tags": [
                    "Health"
                ],
                "security": [],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/gdpr/export": {
            "post": {
                "summary": "Request a data export for a contact",
                "tags": [
                    "GDPR"
                ],
                "responses": {
                    "202": {
                        "description": "Accepted"
                    }
                }
            }
        },
        "/gdpr/deletion": {
            "post": {
                "summary": "Request deletion of a contact's data",
                "tags": [
                    "GDPR"
                ],
                "responses": {
                    "202": {
                        "description": "Accepted"
                    }
                }
            }
        },
        "/gdpr/requests": {
            "get": {
                "summary": "List data export/deletion requests",
                "tags": [
                    "GDPR"
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/gdpr/requests/{id}": {
            "get": {
                "summary": "Check a data request's status",
                "tags": [
                    "GDPR"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/gdpr/retention-policy": {
            "get": {
                "summary": "Get this tenant's data retention settings",
                "tags": [
                    "GDPR"
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            },
            "put": {
                "summary": "Update data retention settings",
                "tags": [
                    "GDPR"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "message_retention_days": {
                                        "type": "integer"
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    }
}
