{
  "openapi": "3.1.0",
  "info": {
    "title": "smartest.email AI writing API",
    "version": "2026-10-20",
    "description": "LLMHub-backed writing assistance. ENABLE_AI controls these three operations independently of ENABLE_PREVIEW_FEATURES; the broad production preview gate stays disabled. Uses session Bearer JWT authentication and current workspace membership. Generation requires any of template:create, template:edit, campaign:create or campaign:edit. Requests are limited to 10 per workspace per minute and the existing monthly AI allowance. An explicit server-owned pilot list may add a bounded beta allowance without reducing paid limits. Usage counts provider attempts, including upstream errors, timeouts and invalid results. Validation failures and canceled requests detected before dispatch do not count. Counters reset by UTC calendar month; requests spanning a boundary belong to the month reserved before dispatch. No automatic retries, saving, sending or quota refunds after dispatch. The server sends only submitted task text and instructions to LLMHub and keeps its API key server-side. Complete bounded plain-text JSON results are required; unsupported or truncated output is rejected. AI content must be reviewed before use."
  },
  "servers": [
    {
      "url": "https://api.smartest.email/api/v1"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "paths": {
    "/ai/capabilities": {
      "get": {
        "summary": "Check writing access and the current monthly request allowance",
        "responses": {
          "200": {
            "description": "Completed result; never saved or sent automatically.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Capabilities"
                }
              }
            }
          },
          "400": {
            "description": "Safe error code and message. Provider response bodies, credentials and submitted text are never included.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Safe error code and message. Provider response bodies, credentials and submitted text are never included.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Safe error code and message. Provider response bodies, credentials and submitted text are never included.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Safe error code and message. Provider response bodies, credentials and submitted text are never included.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Safe error code and message. Provider response bodies, credentials and submitted text are never included.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Safe error code and message. Provider response bodies, credentials and submitted text are never included.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Safe error code and message. Provider response bodies, credentials and submitted text are never included.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/ai/generate-copy": {
      "post": {
        "summary": "Draft email copy",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CopyRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Completed result; never saved or sent automatically.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CopyResult"
                }
              }
            }
          },
          "400": {
            "description": "Safe error code and message. Provider response bodies, credentials and submitted text are never included.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Safe error code and message. Provider response bodies, credentials and submitted text are never included.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Safe error code and message. Provider response bodies, credentials and submitted text are never included.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Safe error code and message. Provider response bodies, credentials and submitted text are never included.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Safe error code and message. Provider response bodies, credentials and submitted text are never included.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Safe error code and message. Provider response bodies, credentials and submitted text are never included.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Safe error code and message. Provider response bodies, credentials and submitted text are never included.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/ai/subject-lines": {
      "post": {
        "summary": "Suggest subject lines",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubjectRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Completed result; never saved or sent automatically.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubjectResult"
                }
              }
            }
          },
          "400": {
            "description": "Safe error code and message. Provider response bodies, credentials and submitted text are never included.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Safe error code and message. Provider response bodies, credentials and submitted text are never included.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Safe error code and message. Provider response bodies, credentials and submitted text are never included.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Safe error code and message. Provider response bodies, credentials and submitted text are never included.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Safe error code and message. Provider response bodies, credentials and submitted text are never included.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Safe error code and message. Provider response bodies, credentials and submitted text are never included.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Safe error code and message. Provider response bodies, credentials and submitted text are never included.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/ai/optimize-content": {
      "post": {
        "summary": "Rewrite text",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RewriteRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Completed result; never saved or sent automatically.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RewriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Safe error code and message. Provider response bodies, credentials and submitted text are never included.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Safe error code and message. Provider response bodies, credentials and submitted text are never included.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Safe error code and message. Provider response bodies, credentials and submitted text are never included.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Safe error code and message. Provider response bodies, credentials and submitted text are never included.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Safe error code and message. Provider response bodies, credentials and submitted text are never included.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Safe error code and message. Provider response bodies, credentials and submitted text are never included.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Safe error code and message. Provider response bodies, credentials and submitted text are never included.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT"
      }
    },
    "schemas": {
      "Language": {
        "type": "string",
        "enum": [
          "en",
          "en-gb",
          "nl",
          "de",
          "fr",
          "es",
          "pl",
          "ar",
          "pt",
          "pt-br",
          "it",
          "zh",
          "sv",
          "nb",
          "lv",
          "et",
          "fi",
          "el",
          "ja"
        ],
        "description": "The requested output language only. The builder defaults it from the template/campaign contentLocale, never the interface/profile locale. A different output language does not modify the saved document language. An unknown legacy document requires an explicit choice before generation."
      },
      "CopyRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "type": {
            "enum": [
              "welcome",
              "promotional",
              "newsletter",
              "follow_up",
              "abandoned_cart"
            ]
          },
          "industry": {
            "type": "string",
            "minLength": 0,
            "maxLength": 200,
            "pattern": "^[^\\u0000]*$"
          },
          "tone": {
            "enum": [
              "professional",
              "friendly",
              "casual",
              "urgent"
            ]
          },
          "keyPoints": {
            "type": "array",
            "maxItems": 10,
            "items": {
              "type": "string",
              "minLength": 1,
              "maxLength": 500,
              "pattern": "^[^\\u0000]*$"
            }
          },
          "length": {
            "enum": [
              "short",
              "medium",
              "long"
            ]
          },
          "context": {
            "type": "string",
            "minLength": 0,
            "maxLength": 4000,
            "pattern": "^[^\\u0000]*$"
          },
          "language": {
            "$ref": "#/components/schemas/Language"
          }
        },
        "required": [
          "type",
          "tone",
          "length",
          "language"
        ],
        "description": "Requires nonblank context or at least one nonblank key point. Industry is optional. Length controls requested writing length, not a token count. All bounds count Unicode code points."
      },
      "CopyResult": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "subject": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "pattern": "^[^\\u0000]*$"
          },
          "previewText": {
            "type": "string",
            "minLength": 1,
            "maxLength": 300,
            "pattern": "^[^\\u0000]*$"
          },
          "body": {
            "type": "string",
            "minLength": 1,
            "maxLength": 20000,
            "pattern": "^[^\\u0000]*$"
          },
          "variations": {
            "type": "array",
            "minItems": 2,
            "maxItems": 2,
            "items": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000]*$"
            }
          }
        },
        "required": [
          "subject",
          "previewText",
          "body",
          "variations"
        ],
        "description": "Plain text, not HTML. Subject, previewText and variations are single-line. Escape all output when inserting into HTML."
      },
      "SubjectRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "context": {
            "type": "string",
            "minLength": 0,
            "maxLength": 4000,
            "pattern": "^[^\\u0000]*$"
          },
          "emailContent": {
            "type": "string",
            "minLength": 0,
            "maxLength": 20000,
            "pattern": "^[^\\u0000]*$"
          },
          "count": {
            "type": "integer",
            "minimum": 1,
            "maximum": 5
          },
          "style": {
            "enum": [
              "question",
              "statement",
              "urgent",
              "personalized",
              "curiosity"
            ]
          },
          "language": {
            "$ref": "#/components/schemas/Language"
          }
        },
        "required": [
          "count",
          "style",
          "language"
        ],
        "description": "Requires nonblank context or emailContent. Returns exactly count distinct single-line plain-text subjects."
      },
      "SubjectResult": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "subjects": {
            "type": "array",
            "minItems": 1,
            "maxItems": 5,
            "uniqueItems": true,
            "items": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000]*$"
            }
          }
        },
        "required": [
          "subjects"
        ]
      },
      "RewriteRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "content": {
            "type": "string",
            "minLength": 1,
            "maxLength": 20000,
            "pattern": "^[^\\u0000]*$"
          },
          "goals": {
            "type": "array",
            "minItems": 1,
            "maxItems": 3,
            "uniqueItems": true,
            "items": {
              "enum": [
                "engagement",
                "clicks",
                "conversions"
              ]
            }
          },
          "audience": {
            "type": "string",
            "minLength": 0,
            "maxLength": 1000,
            "pattern": "^[^\\u0000]*$"
          },
          "language": {
            "$ref": "#/components/schemas/Language"
          }
        },
        "required": [
          "content",
          "goals",
          "language"
        ],
        "description": "Content must be nonblank. Goals must be unique. No recipient/contact fields are fetched."
      },
      "RewriteResult": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "optimizedContent": {
            "type": "string",
            "minLength": 1,
            "maxLength": 20000,
            "pattern": "^[^\\u0000]*$"
          },
          "suggestions": {
            "type": "array",
            "maxItems": 10,
            "items": {
              "type": "string",
              "minLength": 1,
              "maxLength": 1000,
              "pattern": "^[^\\u0000]*$"
            }
          }
        },
        "required": [
          "optimizedContent",
          "suggestions"
        ],
        "description": "Plain text, not HTML; suggestions are editorial guidance, not predicted performance or verified delivery scores."
      },
      "Capabilities": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "configured": {
            "type": "boolean"
          },
          "canGenerate": {
            "type": "boolean"
          },
          "reason": {
            "enum": [
              "",
              "disabled",
              "not_configured",
              "permission_denied",
              "plan_unavailable",
              "limit_reached"
            ]
          },
          "monthlyLimit": {
            "type": "integer",
            "minimum": -1
          },
          "used": {
            "type": "integer",
            "minimum": 0
          },
          "remaining": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0
          }
        },
        "required": [
          "enabled",
          "configured",
          "canGenerate",
          "reason",
          "monthlyLimit",
          "used",
          "remaining"
        ],
        "description": "Authenticated availability snapshot, never a substitute for per-request checks. remaining is null only for existing unlimited runtime entitlements. No key or provider settings are returned."
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "boolean"
          },
          "code": {
            "type": "string",
            "enum": [
              "ai_invalid_request",
              "ai_not_configured",
              "ai_plan_unavailable",
              "ai_limit_reached",
              "ai_provider_auth",
              "ai_provider_rate_limited",
              "ai_provider_unavailable",
              "ai_invalid_response",
              "ai_internal_error"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ]
      }
    }
  }
}
