{
  "openapi": "3.1.0",
  "info": {
    "title": "Zyphon Gateway API",
    "version": "1.0.0",
    "description": "Public messaging API (port 8080) and Admin control plane (port 8081). Secrets never appear in responses; provider credentials use secret_set."
  },
  "servers": [
    { "url": "http://127.0.0.1:8080", "description": "Public API" },
    { "url": "http://127.0.0.1:8081", "description": "Admin API" }
  ],
  "tags": [
    { "name": "Public" },
    { "name": "Admin Auth" },
    { "name": "Applications" },
    { "name": "Providers" },
    { "name": "Templates" },
    { "name": "Logs" },
    { "name": "Observability" }
  ],
  "components": {
    "securitySchemes": {
      "ApiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key"
      },
      "AdminBearer": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "session token"
      },
      "CsrfHeader": {
        "type": "apiKey",
        "in": "header",
        "name": "X-CSRF-Token"
      }
    },
    "schemas": {
      "Channel": {
        "type": "string",
        "enum": ["email", "sms", "whatsapp"]
      },
      "Attachment": {
        "type": "object",
        "required": ["filename", "contentType"],
        "properties": {
          "filename": { "type": "string", "description": "e.g. invoice.pdf, receipt.png" },
          "contentType": {
            "type": "string",
            "description": "MIME type, e.g. application/pdf, text/html, image/png, video/mp4"
          },
          "content": { "type": "string", "description": "Base64-encoded file bytes (email or Meta WhatsApp media upload)" },
          "url": { "type": "string", "description": "Public HTTPS media URL (WhatsApp media or Twilio SMS/WA MediaUrl)" }
        }
      },
      "ContentPayload": {
        "type": "object",
        "required": ["body"],
        "properties": {
          "type": {
            "type": "string",
            "enum": ["text", "html", "template"],
            "description": "text = plain body; html = render body as HTML; template = resolve Zyphon template id"
          },
          "subject": { "type": "string" },
          "body": { "type": "string", "description": "Plain text or HTML markup depending on type" },
          "template": { "type": "string", "description": "Zyphon template id when type=template" },
          "variables": {
            "type": "object",
            "additionalProperties": { "type": "string" }
          },
          "attachments": {
            "type": "array",
            "description": "Email attachments (base64). Supported by SMTP, SendGrid, Mailgun, and Zoho ZeptoMail.",
            "items": { "$ref": "#/components/schemas/Attachment" }
          }
        }
      },
      "SendRequest": {
        "type": "object",
        "required": ["channel", "recipient", "content"],
        "properties": {
          "channel": { "$ref": "#/components/schemas/Channel" },
          "recipient": { "type": "string" },
          "content": { "$ref": "#/components/schemas/ContentPayload" },
          "metadata": { "type": "object", "additionalProperties": true }
        }
      },
      "SendResponse": {
        "type": "object",
        "properties": {
          "message_id": { "type": "string" },
          "request_id": { "type": "string" },
          "status": { "type": "string" },
          "channel": { "$ref": "#/components/schemas/Channel" },
          "provider": { "type": ["string", "null"] },
          "failover": { "type": "boolean" },
          "attempts": { "type": "array", "items": { "type": "object" } },
          "latency_ms": { "type": "number" },
          "error": { "type": "object" }
        }
      },
      "ZyphonError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": { "type": "string" },
              "message": { "type": "string" }
            }
          }
        }
      },
      "AdminProvider": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "channel": { "$ref": "#/components/schemas/Channel" },
          "type": { "type": "string" },
          "name": { "type": "string" },
          "config": { "type": "object", "additionalProperties": true },
          "secret_set": {
            "type": "boolean",
            "description": "True when encrypted credentials exist; secret values are never returned"
          },
          "status": {
            "type": "string",
            "enum": ["Connected", "Paused briefly", "Needs attention"]
          },
          "sent": { "type": "integer" },
          "failed": { "type": "integer" }
        }
      },
      "MessageTemplate": {
        "type": "object",
        "required": ["id", "name", "channel", "body"],
        "properties": {
          "id": { "type": "string" },
          "name": { "type": "string" },
          "channel": { "$ref": "#/components/schemas/Channel" },
          "subject": { "type": "string" },
          "body": { "type": "string" },
          "dlt_id": { "type": "string" },
          "header": { "type": "string" },
          "category": {
            "type": "string",
            "enum": ["transactional", "promotional", "otp", "service"]
          },
          "variables": {
            "type": "array",
            "items": { "type": "string" }
          }
        }
      }
    }
  },
  "paths": {
    "/api/v1/health": {
      "get": {
        "tags": ["Public"],
        "summary": "Public health check",
        "responses": {
          "200": {
            "description": "Gateway is up",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": { "type": "string" },
                    "uptime": { "type": "number" }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/messages": {
      "post": {
        "tags": ["Public"],
        "summary": "Dispatch a message",
        "security": [{ "ApiKey": [] }],
        "parameters": [
          {
            "name": "X-Idempotency-Key",
            "in": "header",
            "schema": { "type": "string" }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/SendRequest" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Delivered or accepted",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/SendResponse" }
              }
            }
          },
          "401": { "description": "Unauthenticated", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ZyphonError" } } } },
          "403": { "description": "Forbidden", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ZyphonError" } } } },
          "422": { "description": "Validation failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ZyphonError" } } } }
        }
      }
    },
    "/api/v1/messages/{id}": {
      "get": {
        "tags": ["Public"],
        "summary": "Look up a message by id",
        "security": [{ "ApiKey": [] }],
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": {
            "description": "Message record",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/SendResponse" }
              }
            }
          },
          "404": { "description": "Not found" }
        }
      }
    },
    "/webhooks/{provider}": {
      "post": {
        "tags": ["Public"],
        "summary": "Provider delivery webhook",
        "parameters": [
          { "name": "provider", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": { "description": "Accepted" }
        }
      }
    },
    "/admin/auth/login": {
      "post": {
        "tags": ["Admin Auth"],
        "summary": "Admin login",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["password"],
                "properties": {
                  "password": { "type": "string" }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Session created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "token": { "type": "string" },
                    "csrf_token": { "type": "string" },
                    "role": { "type": "string" }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/admin/auth/logout": {
      "post": {
        "tags": ["Admin Auth"],
        "summary": "Admin logout",
        "security": [{ "AdminBearer": [] }, { "CsrfHeader": [] }],
        "responses": { "200": { "description": "Logged out" } }
      }
    },
    "/admin/auth/me": {
      "get": {
        "tags": ["Admin Auth"],
        "summary": "Current admin session",
        "security": [{ "AdminBearer": [] }],
        "responses": { "200": { "description": "Session info" } }
      }
    },
    "/admin/providers": {
      "get": {
        "tags": ["Providers"],
        "summary": "List providers (secrets redacted; secret_set flag)",
        "security": [{ "AdminBearer": [] }],
        "responses": {
          "200": {
            "description": "Provider list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": { "$ref": "#/components/schemas/AdminProvider" }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": ["Providers"],
        "summary": "Create provider",
        "security": [{ "AdminBearer": [] }, { "CsrfHeader": [] }],
        "responses": { "201": { "description": "Created" } }
      }
    },
    "/admin/providers/{id}": {
      "patch": {
        "tags": ["Providers"],
        "summary": "Update provider",
        "security": [{ "AdminBearer": [] }, { "CsrfHeader": [] }],
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": { "200": { "description": "Updated" } }
      },
      "delete": {
        "tags": ["Providers"],
        "summary": "Delete provider",
        "security": [{ "AdminBearer": [] }, { "CsrfHeader": [] }],
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": { "200": { "description": "Deleted" } }
      }
    },
    "/admin/templates": {
      "get": {
        "tags": ["Templates"],
        "summary": "List message templates",
        "security": [{ "AdminBearer": [] }],
        "responses": {
          "200": {
            "description": "Templates",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "templates": {
                      "type": "array",
                      "items": { "$ref": "#/components/schemas/MessageTemplate" }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": ["Templates"],
        "summary": "Create or upsert template",
        "security": [{ "AdminBearer": [] }, { "CsrfHeader": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/MessageTemplate" }
            }
          }
        },
        "responses": { "200": { "description": "Saved" } }
      }
    },
    "/admin/templates/{id}": {
      "put": {
        "tags": ["Templates"],
        "summary": "Update template",
        "security": [{ "AdminBearer": [] }, { "CsrfHeader": [] }],
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": { "200": { "description": "Updated" } }
      },
      "delete": {
        "tags": ["Templates"],
        "summary": "Delete template",
        "security": [{ "AdminBearer": [] }, { "CsrfHeader": [] }],
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": { "200": { "description": "Deleted" } }
      }
    },
    "/admin/applications": {
      "get": {
        "tags": ["Applications"],
        "summary": "List applications",
        "security": [{ "AdminBearer": [] }],
        "responses": { "200": { "description": "Application list" } }
      },
      "post": {
        "tags": ["Applications"],
        "summary": "Create application",
        "security": [{ "AdminBearer": [] }, { "CsrfHeader": [] }],
        "responses": { "201": { "description": "Created" } }
      }
    },
    "/admin/catalog": {
      "get": {
        "tags": ["Providers"],
        "summary": "Provider field catalog for dashboard forms",
        "security": [{ "AdminBearer": [] }],
        "responses": { "200": { "description": "Catalog by channel" } }
      }
    },
    "/admin/dlt": {
      "get": {
        "tags": ["Templates"],
        "summary": "India DLT configuration",
        "security": [{ "AdminBearer": [] }],
        "responses": { "200": { "description": "DLT config" } }
      },
      "put": {
        "tags": ["Templates"],
        "summary": "Update DLT configuration",
        "security": [{ "AdminBearer": [] }, { "CsrfHeader": [] }],
        "responses": { "200": { "description": "Saved" } }
      }
    },
    "/admin/stats": {
      "get": {
        "tags": ["Observability"],
        "summary": "Dashboard KPI stats",
        "security": [{ "AdminBearer": [] }],
        "responses": { "200": { "description": "Stats" } }
      }
    },
    "/admin/insights": {
      "get": {
        "tags": ["Observability"],
        "summary": "Aggregated insights from metrics and logs",
        "security": [{ "AdminBearer": [] }],
        "responses": { "200": { "description": "Insights" } }
      }
    },
    "/admin/logs/search": {
      "get": {
        "tags": ["Logs"],
        "summary": "Search retained daily logs",
        "security": [{ "AdminBearer": [] }],
        "parameters": [
          { "name": "q", "in": "query", "schema": { "type": "string" } },
          { "name": "limit", "in": "query", "schema": { "type": "integer" } }
        ],
        "responses": { "200": { "description": "Log records" } }
      }
    },
    "/admin/logs/files": {
      "get": {
        "tags": ["Logs"],
        "summary": "List daily log files",
        "security": [{ "AdminBearer": [] }],
        "responses": { "200": { "description": "File list" } }
      }
    },
    "/admin/events": {
      "get": {
        "tags": ["Observability"],
        "summary": "SSE event stream",
        "security": [{ "AdminBearer": [] }],
        "responses": {
          "200": {
            "description": "text/event-stream",
            "content": { "text/event-stream": { "schema": { "type": "string" } } }
          }
        }
      }
    },
    "/admin/openapi.json": {
      "get": {
        "tags": ["Observability"],
        "summary": "This OpenAPI document",
        "responses": {
          "200": {
            "description": "OpenAPI 3.1 JSON",
            "content": {
              "application/json": {
                "schema": { "type": "object" }
              }
            }
          }
        }
      }
    }
  }
}
