{
  "openapi": "3.0.0",
  "info": {
    "title": "Flowella REST API",
    "version": "2.1.0",
    "description": "Public v1 HTTP API for Flowella. Authenticate with `Authorization: Bearer <api_key>` (`flo_` prefix). Canonical base: `https://api.flowella.io/v1`. Legacy `https://app.flowella.io/api/v1/...` requests are permanently redirected (308) to the canonical host, preserving method and body."
  },
  "servers": [
    {
      "url": "https://api.flowella.io",
      "description": "Canonical API host"
    },
    {
      "url": "https://app.flowella.io",
      "description": "Legacy app host — /api/v1 permanently redirects (308) to the API host /v1"
    }
  ],
  "tags": [
    {
      "name": "System",
      "description": "Health and auth checks"
    },
    {
      "name": "Messages",
      "description": "Send WhatsApp messages"
    },
    {
      "name": "Conversations",
      "description": "Inbox conversations"
    },
    {
      "name": "Contacts",
      "description": "CRM contacts"
    },
    {
      "name": "Templates",
      "description": "WhatsApp templates and bulk send"
    },
    {
      "name": "Analytics",
      "description": "Usage and delivery metrics"
    }
  ],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "API key",
        "description": "Organization API key (`flo_…`). Paste the full key; Scalar sends `Authorization: Bearer <key>`."
      }
    },
    "schemas": {},
    "parameters": {}
  },
  "paths": {
    "/v1/ping": {
      "get": {
        "operationId": "v1Ping",
        "summary": "Ping (auth check)",
        "description": "Returns `ok` and the organization id for the resolved API key. Use to verify credentials.",
        "tags": [
          "System"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Authenticated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "organizationId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "ok",
                    "organizationId"
                  ],
                  "example": {
                    "ok": true,
                    "organizationId": "clxxxxxxxxxxxxxxxxxxxxxxxx"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "example": {
                    "error": {
                      "code": "UNAUTHORIZED",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "example": {
                    "error": {
                      "code": "UNAUTHORIZED",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/messages": {
      "post": {
        "operationId": "v1SendMessage",
        "summary": "Send WhatsApp text message",
        "tags": [
          "Messages"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "to": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 32
                  },
                  "text": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4096
                  },
                  "whatsappChannelId": {
                    "type": "string",
                    "format": "cuid"
                  }
                },
                "required": [
                  "to",
                  "text"
                ],
                "example": {
                  "to": "+15551234567",
                  "text": "Hello from Flowella API"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Message accepted and stored",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "conversationId": {
                      "type": "string"
                    },
                    "contactId": {
                      "type": "string"
                    },
                    "metaMessageId": {
                      "type": "string",
                      "nullable": true
                    }
                  },
                  "required": [
                    "id",
                    "conversationId",
                    "contactId",
                    "metaMessageId"
                  ],
                  "example": {
                    "id": "clxxxxxxxxxxxxxxxxxxxxxxxx",
                    "conversationId": "clxxxxxxxxxxxxxxxxxxxxxxxx",
                    "contactId": "clxxxxxxxxxxxxxxxxxxxxxxxx",
                    "metaMessageId": "wamid.xxx"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation or Meta error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "example": {
                    "error": {
                      "code": "UNAUTHORIZED",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "example": {
                    "error": {
                      "code": "UNAUTHORIZED",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "example": {
                    "error": {
                      "code": "UNAUTHORIZED",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden (e.g. opt-out, Meta not connected)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "example": {
                    "error": {
                      "code": "UNAUTHORIZED",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Channel not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "example": {
                    "error": {
                      "code": "UNAUTHORIZED",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "example": {
                    "error": {
                      "code": "UNAUTHORIZED",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/conversations": {
      "get": {
        "operationId": "v1ListConversations",
        "summary": "List conversations",
        "tags": [
          "Conversations"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "cuid"
            },
            "required": false,
            "name": "cursor",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "OPEN",
                "CLOSED",
                "PENDING",
                "ARCHIVED",
                "SNOOZED"
              ]
            },
            "required": false,
            "name": "status",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated conversations",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "OPEN",
                              "CLOSED",
                              "PENDING",
                              "ARCHIVED",
                              "SNOOZED"
                            ]
                          },
                          "lastMessageAt": {
                            "type": "string",
                            "nullable": true
                          },
                          "createdAt": {
                            "type": "string"
                          },
                          "whatsappChannelId": {
                            "type": "string"
                          },
                          "contact": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "name": {
                                "type": "string",
                                "nullable": true
                              },
                              "phone": {
                                "type": "string"
                              },
                              "waId": {
                                "type": "string",
                                "nullable": true
                              }
                            },
                            "required": [
                              "id",
                              "name",
                              "phone",
                              "waId"
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "status",
                          "lastMessageAt",
                          "createdAt",
                          "whatsappChannelId",
                          "contact"
                        ]
                      }
                    },
                    "nextCursor": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "items"
                  ],
                  "example": {
                    "items": []
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad query",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "example": {
                    "error": {
                      "code": "UNAUTHORIZED",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "example": {
                    "error": {
                      "code": "UNAUTHORIZED",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "example": {
                    "error": {
                      "code": "UNAUTHORIZED",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "example": {
                    "error": {
                      "code": "UNAUTHORIZED",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/contacts": {
      "get": {
        "operationId": "v1ListContacts",
        "summary": "List contacts",
        "tags": [
          "Contacts"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "cuid"
            },
            "required": false,
            "name": "cursor",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated contacts",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "phone": {
                            "type": "string"
                          },
                          "waId": {
                            "type": "string",
                            "nullable": true
                          },
                          "name": {
                            "type": "string",
                            "nullable": true
                          },
                          "email": {
                            "type": "string",
                            "nullable": true
                          },
                          "isOptedOut": {
                            "type": "boolean"
                          },
                          "createdAt": {
                            "type": "string"
                          },
                          "updatedAt": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "phone",
                          "waId",
                          "name",
                          "email",
                          "isOptedOut",
                          "createdAt",
                          "updatedAt"
                        ]
                      }
                    },
                    "nextCursor": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "items"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad query",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "example": {
                    "error": {
                      "code": "UNAUTHORIZED",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "example": {
                    "error": {
                      "code": "UNAUTHORIZED",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "example": {
                    "error": {
                      "code": "UNAUTHORIZED",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "example": {
                    "error": {
                      "code": "UNAUTHORIZED",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "v1UpsertContact",
        "summary": "Create or update contact",
        "tags": [
          "Contacts"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "phone": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 32
                  },
                  "name": {
                    "type": "string",
                    "nullable": true,
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "email": {
                    "type": "string",
                    "nullable": true,
                    "format": "email"
                  },
                  "waId": {
                    "type": "string",
                    "nullable": true,
                    "minLength": 1,
                    "maxLength": 64
                  }
                },
                "required": [
                  "phone"
                ],
                "example": {
                  "phone": "+15551234567",
                  "name": "Ada Lovelace",
                  "email": "ada@example.com"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Contact upserted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "phone": {
                      "type": "string"
                    },
                    "waId": {
                      "type": "string",
                      "nullable": true
                    },
                    "name": {
                      "type": "string",
                      "nullable": true
                    },
                    "email": {
                      "type": "string",
                      "nullable": true
                    },
                    "isOptedOut": {
                      "type": "boolean"
                    },
                    "createdAt": {
                      "type": "string"
                    },
                    "updatedAt": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "phone",
                    "waId",
                    "name",
                    "email",
                    "isOptedOut",
                    "createdAt",
                    "updatedAt"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad body",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "example": {
                    "error": {
                      "code": "UNAUTHORIZED",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "example": {
                    "error": {
                      "code": "UNAUTHORIZED",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "example": {
                    "error": {
                      "code": "UNAUTHORIZED",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "example": {
                    "error": {
                      "code": "UNAUTHORIZED",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/opt-outs": {
      "post": {
        "operationId": "v1OptOutsMutate",
        "summary": "Set or clear per-channel WhatsApp opt-out",
        "description": "`action: set` creates or reactivates an opt-out for the given channel and phone. `action: clear` revokes it. Idempotent clears are safe.",
        "tags": [
          "Contacts"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "object",
                    "properties": {
                      "action": {
                        "type": "string",
                        "enum": [
                          "set"
                        ]
                      },
                      "whatsappChannelId": {
                        "type": "string",
                        "format": "cuid"
                      },
                      "phone": {
                        "type": "string",
                        "minLength": 3,
                        "maxLength": 32
                      },
                      "reason": {
                        "type": "string",
                        "maxLength": 500
                      }
                    },
                    "required": [
                      "action",
                      "whatsappChannelId",
                      "phone"
                    ],
                    "example": {
                      "action": "set",
                      "whatsappChannelId": "clxxxxxxxxxxxxxxxxxxxxxxxx",
                      "phone": "+15551234567",
                      "reason": "User requested via CRM"
                    }
                  },
                  {
                    "type": "object",
                    "properties": {
                      "action": {
                        "type": "string",
                        "enum": [
                          "clear"
                        ]
                      },
                      "whatsappChannelId": {
                        "type": "string",
                        "format": "cuid"
                      },
                      "phone": {
                        "type": "string",
                        "minLength": 3,
                        "maxLength": 32
                      }
                    },
                    "required": [
                      "action",
                      "whatsappChannelId",
                      "phone"
                    ],
                    "example": {
                      "action": "clear",
                      "whatsappChannelId": "clxxxxxxxxxxxxxxxxxxxxxxxx",
                      "phone": "+15551234567"
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Current opt-out state",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "optOutId": {
                      "type": "string",
                      "nullable": true
                    },
                    "active": {
                      "type": "boolean"
                    },
                    "revokedAt": {
                      "type": "string",
                      "nullable": true
                    }
                  },
                  "required": [
                    "optOutId",
                    "active",
                    "revokedAt"
                  ],
                  "example": {
                    "optOutId": "clxxxxxxxxxxxxxxxxxxxxxxxx",
                    "active": true,
                    "revokedAt": null
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad body",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "example": {
                    "error": {
                      "code": "UNAUTHORIZED",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "example": {
                    "error": {
                      "code": "UNAUTHORIZED",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "example": {
                    "error": {
                      "code": "UNAUTHORIZED",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden (e.g. integration disabled)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "example": {
                    "error": {
                      "code": "UNAUTHORIZED",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Channel not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "example": {
                    "error": {
                      "code": "UNAUTHORIZED",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "example": {
                    "error": {
                      "code": "UNAUTHORIZED",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/templates": {
      "get": {
        "operationId": "v1ListTemplates",
        "summary": "List WhatsApp templates",
        "tags": [
          "Templates"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128
            },
            "required": false,
            "name": "cursor",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "DRAFT",
                "PENDING",
                "APPROVED",
                "REJECTED",
                "PAUSED",
                "DISABLED"
              ]
            },
            "required": false,
            "name": "status",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "cuid"
            },
            "required": false,
            "name": "whatsappChannelId",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            },
            "required": false,
            "name": "search",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated templates",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "source": {
                            "type": "string",
                            "enum": [
                              "meta",
                              "draft"
                            ]
                          },
                          "name": {
                            "type": "string"
                          },
                          "language": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "DRAFT",
                              "PENDING",
                              "APPROVED",
                              "REJECTED",
                              "PAUSED",
                              "DISABLED"
                            ]
                          },
                          "wabaId": {
                            "type": "string"
                          },
                          "whatsappChannelId": {
                            "type": "string",
                            "nullable": true
                          },
                          "metaTemplateId": {
                            "type": "string",
                            "nullable": true
                          },
                          "createdAt": {
                            "type": "string",
                            "nullable": true
                          },
                          "updatedAt": {
                            "type": "string",
                            "nullable": true
                          }
                        },
                        "required": [
                          "id",
                          "source",
                          "name",
                          "language",
                          "status",
                          "wabaId",
                          "whatsappChannelId",
                          "metaTemplateId",
                          "createdAt",
                          "updatedAt"
                        ]
                      }
                    },
                    "nextCursor": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "items"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad query",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "example": {
                    "error": {
                      "code": "UNAUTHORIZED",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "example": {
                    "error": {
                      "code": "UNAUTHORIZED",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "example": {
                    "error": {
                      "code": "UNAUTHORIZED",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Channel not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "example": {
                    "error": {
                      "code": "UNAUTHORIZED",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "example": {
                    "error": {
                      "code": "UNAUTHORIZED",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/templates/send": {
      "post": {
        "operationId": "v1SendTemplatesBulk",
        "summary": "Queue template send job",
        "tags": [
          "Templates"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "templateId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 128
                  },
                  "templateWabaId": {
                    "type": "string",
                    "minLength": 1
                  },
                  "whatsappChannelId": {
                    "type": "string",
                    "format": "cuid"
                  },
                  "headerMedia": {
                    "type": "object",
                    "properties": {
                      "url": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 4000,
                        "format": "uri"
                      },
                      "fileName": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 240
                      }
                    },
                    "required": [
                      "url"
                    ]
                  },
                  "recipients": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "phone": {
                          "type": "string",
                          "minLength": 3,
                          "maxLength": 32
                        },
                        "contactId": {
                          "type": "string",
                          "nullable": true,
                          "format": "cuid"
                        },
                        "bodyParameters": {
                          "type": "array",
                          "items": {
                            "type": "string",
                            "minLength": 1
                          },
                          "maxItems": 20
                        },
                        "buttonParameters": {
                          "type": "array",
                          "items": {
                            "oneOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "index": {
                                    "type": "integer",
                                    "nullable": true,
                                    "minimum": 0,
                                    "maximum": 9
                                  },
                                  "subType": {
                                    "type": "string",
                                    "enum": [
                                      "url"
                                    ]
                                  },
                                  "text": {
                                    "type": "string",
                                    "minLength": 1,
                                    "maxLength": 2000
                                  }
                                },
                                "required": [
                                  "index",
                                  "subType",
                                  "text"
                                ]
                              },
                              {
                                "type": "object",
                                "properties": {
                                  "index": {
                                    "type": "integer",
                                    "nullable": true,
                                    "minimum": 0,
                                    "maximum": 9
                                  },
                                  "subType": {
                                    "type": "string",
                                    "enum": [
                                      "flow"
                                    ]
                                  },
                                  "flowToken": {
                                    "type": "string",
                                    "minLength": 1,
                                    "maxLength": 256
                                  },
                                  "flowActionData": {
                                    "type": "object",
                                    "additionalProperties": {
                                      "nullable": true
                                    }
                                  }
                                },
                                "required": [
                                  "index",
                                  "subType",
                                  "flowToken"
                                ]
                              },
                              {
                                "type": "object",
                                "properties": {
                                  "index": {
                                    "type": "integer",
                                    "nullable": true,
                                    "minimum": 0,
                                    "maximum": 9
                                  },
                                  "subType": {
                                    "type": "string",
                                    "enum": [
                                      "copy_code"
                                    ]
                                  },
                                  "couponCode": {
                                    "type": "string",
                                    "minLength": 1,
                                    "maxLength": 20,
                                    "pattern": "^[a-zA-Z0-9]+$"
                                  }
                                },
                                "required": [
                                  "index",
                                  "subType",
                                  "couponCode"
                                ]
                              }
                            ]
                          },
                          "maxItems": 20
                        }
                      },
                      "required": [
                        "phone"
                      ]
                    },
                    "minItems": 1,
                    "maxItems": 50000
                  },
                  "scheduledAt": {
                    "type": "string",
                    "nullable": true
                  },
                  "throttlePerHour": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 100000
                  }
                },
                "required": [
                  "templateId",
                  "whatsappChannelId",
                  "recipients"
                ],
                "example": {
                  "templateId": "clxxxxxxxxxxxxxxxxxxxxxxxx",
                  "whatsappChannelId": "clxxxxxxxxxxxxxxxxxxxxxxxx",
                  "recipients": [
                    {
                      "phone": "+15551234567",
                      "bodyParameters": [
                        "Ada"
                      ]
                    }
                  ]
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Request accepted for durable processing",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "accepted"
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "status"
                  ],
                  "example": {
                    "id": "v1ts-0123456789abcdef",
                    "status": "accepted"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad body",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "example": {
                    "error": {
                      "code": "UNAUTHORIZED",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "example": {
                    "error": {
                      "code": "UNAUTHORIZED",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "example": {
                    "error": {
                      "code": "UNAUTHORIZED",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "example": {
                    "error": {
                      "code": "UNAUTHORIZED",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          }
        },
        "description": "Accepts a bulk template send and processes it in the background. The request is validated at the door, queued durably, and returns `202 Accepted` immediately with a job id. Send an `Idempotency-Key` header to make retries safe: repeats of the same key within seven days return the original job id instead of sending the batch again. Without the header, Flowella derives a key from the request body, so an identical batch submitted twice in quick succession is not double-sent. Recipients are processed individually, so one invalid number does not block the rest of the batch.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Unique key (up to 200 characters) identifying this batch. Repeats of the same key within seven days return the original job id without re-sending. If omitted, Flowella derives a key from the request body.",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          }
        ]
      }
    },
    "/v1/analytics": {
      "get": {
        "operationId": "v1AnalyticsOutbound",
        "summary": "Outbound message analytics",
        "description": "Aggregates outbound message counts and rates by status for a date range.",
        "tags": [
          "Analytics"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "nullable": true
            },
            "required": false,
            "name": "startDate",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "nullable": true
            },
            "required": false,
            "name": "endDate",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Analytics for period",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "period": {
                      "type": "object",
                      "properties": {
                        "start": {
                          "type": "string"
                        },
                        "end": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "start",
                        "end"
                      ]
                    },
                    "outboundMessages": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer",
                          "minimum": 0
                        },
                        "counts": {
                          "type": "object",
                          "properties": {
                            "PENDING": {
                              "type": "integer",
                              "minimum": 0
                            },
                            "SENT": {
                              "type": "integer",
                              "minimum": 0
                            },
                            "DELIVERED": {
                              "type": "integer",
                              "minimum": 0
                            },
                            "READ": {
                              "type": "integer",
                              "minimum": 0
                            },
                            "FAILED": {
                              "type": "integer",
                              "minimum": 0
                            }
                          }
                        },
                        "deliveryRate": {
                          "type": "number"
                        },
                        "readRate": {
                          "type": "number"
                        },
                        "failureRate": {
                          "type": "number"
                        }
                      },
                      "required": [
                        "total",
                        "counts",
                        "deliveryRate",
                        "readRate",
                        "failureRate"
                      ]
                    }
                  },
                  "required": [
                    "period",
                    "outboundMessages"
                  ],
                  "example": {
                    "period": {
                      "start": "2025-01-01T00:00:00.000Z",
                      "end": "2025-02-01T00:00:00.000Z"
                    },
                    "outboundMessages": {
                      "total": 42,
                      "counts": {
                        "PENDING": 0,
                        "SENT": 10,
                        "DELIVERED": 20,
                        "READ": 10,
                        "FAILED": 2
                      },
                      "deliveryRate": 0.85,
                      "readRate": 0.33,
                      "failureRate": 0.05
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid range",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "example": {
                    "error": {
                      "code": "UNAUTHORIZED",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "example": {
                    "error": {
                      "code": "UNAUTHORIZED",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "example": {
                    "error": {
                      "code": "UNAUTHORIZED",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "example": {
                    "error": {
                      "code": "UNAUTHORIZED",
                      "message": "Invalid API key"
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
