{
  "openapi": "3.0.3",
  "info": {
    "title": "Cronate API",
    "version": "1.0.0",
    "description": "Public Cronate API for custom dashboards. Authenticate with workspace API keys (Starter+). WhatsApp Cloud API traffic always goes through Cronate — Meta tokens are never exposed. Conversation fees are billed by Meta to the merchant WABA (no Cronate markup). Plan quotas (email, AI credits, inboxes, automation runs) are shared with the Cronate dashboard."
  },
  "servers": [
    {
      "url": "https://api.cronate.com/v1",
      "description": "Production"
    }
  ],
  "security": [{ "ApiKeyBearer": [] }],
  "components": {
    "securitySchemes": {
      "ApiKeyBearer": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "crn_live_…",
        "description": "API key from Settings → API. Format: crn_live_<secret> or crn_test_<secret>."
      }
    },
    "schemas": {
      "ApiError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "required": ["code", "message"],
            "properties": {
              "code": { "type": "string" },
              "message": { "type": "string" },
              "details": {}
            }
          }
        }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Missing or invalid API key",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/ApiError" }
          }
        }
      },
      "Forbidden": {
        "description": "Plan lacks apiAccess or role cannot write",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/ApiError" }
          }
        }
      }
    }
  },
  "tags": [
    { "name": "WhatsApp", "description": "WABA via Cronate — accounts, inbox, send, templates, tickets" },
    { "name": "Meta", "description": "Instagram & Messenger inbox" },
    { "name": "Email", "description": "Templates, campaigns, domains, transactional, asset uploads" },
    { "name": "CRM", "description": "Contacts, tags, stages, products, forms (incl. file fields), reminders" },
    { "name": "Flows", "description": "Automations and runs" },
    { "name": "Bot", "description": "Website chatbot config and conversations" }
  ],
  "paths": {
    "/wa/accounts": {
      "get": {
        "tags": ["WhatsApp"],
        "summary": "List WhatsApp accounts",
        "description": "Connected WABA phone numbers for the workspace. Tokens are never returned.",
        "responses": {
          "200": { "description": "Account list" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" }
        }
      }
    },
    "/wa/conversations": {
      "get": {
        "tags": ["WhatsApp"],
        "summary": "List WhatsApp conversations",
        "responses": {
          "200": { "description": "Conversation list" },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/wa/conversations/{id}/send": {
      "post": {
        "tags": ["WhatsApp"],
        "summary": "Send a WhatsApp message",
        "description": "Sends via Cronate using the merchant WABA token stored by Cronate. Clients must not call Meta Graph directly.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": { "description": "Message sent" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" }
        }
      }
    },
    "/wa/templates": {
      "get": {
        "tags": ["WhatsApp"],
        "summary": "List WhatsApp templates",
        "responses": { "200": { "description": "Templates" } }
      }
    },
    "/wa/tickets": {
      "get": {
        "tags": ["WhatsApp"],
        "summary": "List WhatsApp tickets",
        "responses": { "200": { "description": "Tickets" } }
      }
    },
    "/wa/sse": {
      "get": {
        "tags": ["WhatsApp"],
        "summary": "WhatsApp inbox SSE stream",
        "responses": { "200": { "description": "text/event-stream" } }
      }
    },
    "/meta/accounts": {
      "get": {
        "tags": ["Meta"],
        "summary": "List Instagram / Messenger accounts",
        "responses": { "200": { "description": "Accounts" } }
      }
    },
    "/meta/conversations": {
      "get": {
        "tags": ["Meta"],
        "summary": "List Meta conversations",
        "responses": { "200": { "description": "Conversations" } }
      }
    },
    "/meta/conversations/{id}/send": {
      "post": {
        "tags": ["Meta"],
        "summary": "Send Instagram / Messenger message",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": { "200": { "description": "Sent" } }
      }
    },
    "/meta/comments": {
      "get": {
        "tags": ["Meta"],
        "summary": "List comments",
        "responses": { "200": { "description": "Comments" } }
      }
    },
    "/mail/templates": {
      "get": {
        "tags": ["Email"],
        "summary": "List email templates",
        "responses": { "200": { "description": "Templates" } }
      }
    },
    "/mail/campaigns": {
      "get": {
        "tags": ["Email"],
        "summary": "List campaigns",
        "responses": { "200": { "description": "Campaigns" } }
      }
    },
    "/mail/transactional/send": {
      "post": {
        "tags": ["Email"],
        "summary": "Send transactional email",
        "responses": { "200": { "description": "Queued / sent" } }
      }
    },
    "/mail/domains": {
      "get": {
        "tags": ["Email"],
        "summary": "List sending domains",
        "responses": { "200": { "description": "Domains" } }
      }
    },
    "/mail/analytics/summary": {
      "get": {
        "tags": ["Email"],
        "summary": "Email analytics summary",
        "responses": { "200": { "description": "Summary" } }
      }
    },
    "/mail/assets/upload": {
      "post": {
        "tags": ["Email"],
        "summary": "Upload an asset to R2",
        "description": "Multipart upload (max 15 MB). Field `file` is required; optional `purpose` one of flows|campaigns|mail|assets|chat|forms (default assets). Purpose `forms` restricts MIME to images, PDF, and common Office types. Returns `{ key, url, contentType, size, purpose }`.",
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": ["file"],
                "properties": {
                  "file": { "type": "string", "format": "binary" },
                  "purpose": {
                    "type": "string",
                    "enum": ["flows", "campaigns", "mail", "assets", "chat", "forms"]
                  },
                  "fileName": { "type": "string", "description": "Optional filename override" }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Uploaded" },
          "400": { "description": "Invalid upload" },
          "413": { "description": "File too large (max 15 MB)" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" }
        }
      }
    },
    "/crm/contacts": {
      "get": {
        "tags": ["CRM"],
        "summary": "List contacts",
        "responses": { "200": { "description": "Contacts" } }
      },
      "post": {
        "tags": ["CRM"],
        "summary": "Create or resolve contact",
        "responses": { "200": { "description": "Contact" } }
      }
    },
    "/crm/tags": {
      "get": {
        "tags": ["CRM"],
        "summary": "List tags",
        "responses": { "200": { "description": "Tags" } }
      }
    },
    "/crm/stages": {
      "get": {
        "tags": ["CRM"],
        "summary": "List pipeline stages",
        "responses": { "200": { "description": "Stages" } }
      }
    },
    "/crm/products": {
      "get": {
        "tags": ["CRM"],
        "summary": "List products",
        "responses": { "200": { "description": "Products" } }
      }
    },
    "/crm/forms": {
      "get": {
        "tags": ["CRM"],
        "summary": "List forms",
        "responses": { "200": { "description": "Forms" } }
      },
      "post": {
        "tags": ["CRM"],
        "summary": "Create form",
        "responses": { "200": { "description": "Form" } }
      }
    },
    "/crm/forms/{id}": {
      "get": {
        "tags": ["CRM"],
        "summary": "Get form",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": { "200": { "description": "Form with fields" } }
      },
      "patch": {
        "tags": ["CRM"],
        "summary": "Update form",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": { "200": { "description": "Form" } }
      },
      "delete": {
        "tags": ["CRM"],
        "summary": "Delete form",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": { "200": { "description": "Deleted" } }
      }
    },
    "/crm/forms/{id}/publish": {
      "post": {
        "tags": ["CRM"],
        "summary": "Publish form",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": { "200": { "description": "Published form with shareToken" } }
      }
    },
    "/crm/forms/{id}/unpublish": {
      "post": {
        "tags": ["CRM"],
        "summary": "Unpublish form",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": { "200": { "description": "Draft form" } }
      }
    },
    "/crm/forms/{id}/fields": {
      "post": {
        "tags": ["CRM"],
        "summary": "Add form field",
        "description": "answerType: text|textarea|number|boolean|date|select|email|phone|file",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": { "200": { "description": "Field" } }
      }
    },
    "/crm/forms/{id}/responses": {
      "get": {
        "tags": ["CRM"],
        "summary": "List form responses",
        "description": "File field answers are stored as public HTTPS URLs.",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": { "200": { "description": "Responses" } }
      }
    },
    "/crm/public/forms/{token}": {
      "get": {
        "tags": ["CRM"],
        "summary": "Get published form by share token",
        "security": [],
        "parameters": [
          { "name": "token", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": { "200": { "description": "Public form definition" } }
      }
    },
    "/crm/public/forms/{token}/submit": {
      "post": {
        "tags": ["CRM"],
        "summary": "Submit form answers",
        "security": [],
        "description": "Body: `{ contactId?, answers: Record<fieldId, string> }`. File answers must be HTTPS URLs from a prior upload.",
        "parameters": [
          { "name": "token", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": { "200": { "description": "Submitted" } }
      }
    },
    "/crm/public/forms/{token}/upload": {
      "post": {
        "tags": ["CRM"],
        "summary": "Upload a file for a published form",
        "security": [],
        "description": "Multipart (max 15 MB). Field `file` required. MIME allowlist: images, PDF, common Office types. Returns `{ key, url, contentType, size }`. Put `url` into the file field answer on submit.",
        "parameters": [
          { "name": "token", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": ["file"],
                "properties": {
                  "file": { "type": "string", "format": "binary" }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Uploaded" },
          "400": { "description": "Invalid upload" },
          "413": { "description": "File too large (max 15 MB)" }
        }
      }
    },
    "/crm/reminders": {
      "get": {
        "tags": ["CRM"],
        "summary": "List reminders",
        "responses": { "200": { "description": "Reminders" } }
      }
    },
    "/flows": {
      "get": {
        "tags": ["Flows"],
        "summary": "List flows",
        "responses": { "200": { "description": "Flows" } }
      },
      "post": {
        "tags": ["Flows"],
        "summary": "Create flow",
        "responses": { "200": { "description": "Flow" } }
      }
    },
    "/flows/runs": {
      "get": {
        "tags": ["Flows"],
        "summary": "List flow runs",
        "responses": { "200": { "description": "Runs" } }
      }
    },
    "/flows/agent": {
      "get": {
        "tags": ["Flows"],
        "summary": "Get WhatsApp AI agent config",
        "responses": { "200": { "description": "Agent" } }
      }
    },
    "/bot/config": {
      "get": {
        "tags": ["Bot"],
        "summary": "Get website bot config",
        "responses": { "200": { "description": "Config" } }
      },
      "put": {
        "tags": ["Bot"],
        "summary": "Update website bot config",
        "responses": { "200": { "description": "Config" } }
      }
    },
    "/bot/conversations": {
      "get": {
        "tags": ["Bot"],
        "summary": "List bot conversations",
        "responses": { "200": { "description": "Conversations" } }
      }
    }
  }
}
