{
  "openapi": "3.1.0",
  "info": {
    "title": "Gavi WhatsApp API",
    "description": "Complete API for sending WhatsApp messages, templates, media, and broadcasts.",
    "version": "1.0.0",
    "contact": {
      "name": "Gavi WhatsApp Automations",
      "url": "https://www.gaviventures.com",
      "email": "hello@gaviventures.com"
    },
    "x-logo": {
      "url": "https://www.gaviventures.com/gavilogo.png"
    }
  },
  "servers": [
    {
      "url": "https://www.gaviventures.com",
      "description": "Production"
    }
  ],
  "security": [
    {
      "BearerAuth": []
    }
  ],
  "paths": {
    "/api/v1/messages/send": {
      "post": {
        "operationId": "sendMessage",
        "summary": "Send a text message",
        "description": "Send a text message to a WhatsApp number. The recipient must have an active conversation window (messaged you in the last 24 hours) or use send template instead.",
        "tags": ["Messages"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["to", "text"],
                "properties": {
                  "to": {
                    "type": "string",
                    "description": "Recipient phone number in international format",
                    "example": "+919876543210"
                  },
                  "text": {
                    "type": "string",
                    "description": "Message text",
                    "example": "Your order has shipped!"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Message sent successfully",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/MessageResponse" }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/api/v1/messages/template": {
      "post": {
        "operationId": "sendTemplate",
        "summary": "Send a template message",
        "description": "Send a pre-approved template message. Required for initiating conversations (first message to a user). Use GET /api/v1/templates to list available templates.",
        "tags": ["Messages"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["to", "template", "language"],
                "properties": {
                  "to": {
                    "type": "string",
                    "description": "Recipient phone number in international format",
                    "example": "+919876543210"
                  },
                  "template": {
                    "type": "string",
                    "description": "Template name",
                    "example": "order_confirmation"
                  },
                  "language": {
                    "type": "string",
                    "description": "Template language code",
                    "example": "en"
                  },
                  "variables": {
                    "type": "object",
                    "description": "Template variable values keyed by position",
                    "additionalProperties": { "type": "string" },
                    "example": { "1": "ORD-1234", "2": "$49.99" }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Template message sent successfully",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/MessageResponse" }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/api/v1/messages/media": {
      "post": {
        "operationId": "sendMedia",
        "summary": "Send media message",
        "description": "Send media (image, video, document, audio) via a public URL.",
        "tags": ["Messages"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["to", "type", "url"],
                "properties": {
                  "to": {
                    "type": "string",
                    "description": "Recipient phone number in international format",
                    "example": "+919876543210"
                  },
                  "type": {
                    "type": "string",
                    "enum": ["image", "video", "document", "audio"],
                    "description": "Media type"
                  },
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "description": "Public URL to the media file",
                    "example": "https://example.com/receipt.png"
                  },
                  "caption": {
                    "type": "string",
                    "description": "Optional caption for image/video"
                  },
                  "filename": {
                    "type": "string",
                    "description": "Filename for document type"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Media message sent successfully",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/MessageResponse" }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/api/v1/messages": {
      "get": {
        "operationId": "getMessages",
        "summary": "Get message history",
        "description": "Get sent message history. Filter by phone number. Returns delivery status for each message.",
        "tags": ["Messages"],
        "parameters": [
          {
            "name": "phone",
            "in": "query",
            "description": "Filter by recipient phone number",
            "schema": { "type": "string" }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Max messages to return (1-100, default 20)",
            "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 20 }
          }
        ],
        "responses": {
          "200": {
            "description": "Message history",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "messages": {
                      "type": "array",
                      "items": { "$ref": "#/components/schemas/Message" }
                    }
                  }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/api/v1/templates": {
      "get": {
        "operationId": "getTemplates",
        "summary": "List message templates",
        "description": "List available message templates. Add ?sync=true to refresh from Meta (slower but up-to-date).",
        "tags": ["Templates"],
        "parameters": [
          {
            "name": "sync",
            "in": "query",
            "description": "Set to 'true' to pull latest from Meta",
            "schema": { "type": "string", "enum": ["true", "false"] }
          }
        ],
        "responses": {
          "200": {
            "description": "List of templates",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "templates": {
                      "type": "array",
                      "items": { "$ref": "#/components/schemas/Template" }
                    }
                  }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/api/v1/broadcasts": {
      "post": {
        "operationId": "sendBroadcast",
        "summary": "Send broadcast",
        "description": "Send a template message to multiple recipients at once. Use 'variables' for the same values to all, or 'variables_per_recipient' to personalize each.",
        "tags": ["Broadcasts"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["recipients", "template", "language"],
                "properties": {
                  "recipients": {
                    "type": "array",
                    "items": { "type": "string" },
                    "description": "List of phone numbers",
                    "example": ["+919876543210", "+919876543211"]
                  },
                  "template": {
                    "type": "string",
                    "description": "Approved template name",
                    "example": "promo_offer"
                  },
                  "language": {
                    "type": "string",
                    "example": "en"
                  },
                  "variables": {
                    "type": "object",
                    "description": "Same variables for all recipients",
                    "additionalProperties": { "type": "string" }
                  },
                  "variables_per_recipient": {
                    "type": "array",
                    "description": "Per-recipient variable values (must match recipients array length)",
                    "items": {
                      "type": "object",
                      "additionalProperties": { "type": "string" }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Broadcast sent",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/BroadcastResponse" }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/api/v1/webhooks": {
      "post": {
        "operationId": "createWebhook",
        "summary": "Register a webhook",
        "description": "Register a webhook URL to receive real-time events. Returns a secret for HMAC-SHA256 signature verification.",
        "tags": ["Webhooks"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["url", "events"],
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "description": "Webhook endpoint URL",
                    "example": "https://myapp.com/api/whatsapp-webhook"
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": ["message.received", "message.sent", "message.delivered", "message.read", "message.failed"]
                    },
                    "description": "Events to subscribe to"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Webhook registered",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Webhook" }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      },
      "get": {
        "operationId": "listWebhooks",
        "summary": "List webhooks",
        "description": "List all registered webhook endpoints for your account.",
        "tags": ["Webhooks"],
        "responses": {
          "200": {
            "description": "List of webhooks",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "webhooks": {
                      "type": "array",
                      "items": { "$ref": "#/components/schemas/Webhook" }
                    }
                  }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key from Settings → API Keys"
      }
    },
    "schemas": {
      "MessageResponse": {
        "type": "object",
        "properties": {
          "message_id": { "type": "string", "example": "wamid.abc123" },
          "status": { "type": "string", "example": "sent" }
        }
      },
      "Message": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "to": { "type": "string" },
          "template": { "type": "string" },
          "status": { "type": "string", "enum": ["sent", "delivered", "read", "failed"] },
          "error": { "type": "string", "nullable": true },
          "sent_at": { "type": "string", "format": "date-time" },
          "delivered_at": { "type": "string", "format": "date-time", "nullable": true },
          "read_at": { "type": "string", "format": "date-time", "nullable": true }
        }
      },
      "Template": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "name": { "type": "string" },
          "status": { "type": "string" },
          "category": { "type": "string" },
          "language": { "type": "string" },
          "body_text": { "type": "string" },
          "variables": { "type": "array", "items": { "type": "string" } }
        }
      },
      "BroadcastResponse": {
        "type": "object",
        "properties": {
          "broadcast_id": { "type": "string" },
          "total": { "type": "integer" },
          "sent": { "type": "integer" },
          "failed": { "type": "integer" },
          "results": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "to": { "type": "string" },
                "status": { "type": "string" },
                "message_id": { "type": "string" }
              }
            }
          }
        }
      },
      "Webhook": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "url": { "type": "string", "format": "uri" },
          "secret": { "type": "string" },
          "events": { "type": "array", "items": { "type": "string" } },
          "is_active": { "type": "boolean" },
          "created_at": { "type": "string", "format": "date-time" }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": { "type": "string" }
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Bad request — missing or invalid parameters",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/Error" }
          }
        }
      },
      "Unauthorized": {
        "description": "Invalid or missing API key",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/Error" }
          }
        }
      },
      "ServerError": {
        "description": "Server error",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/Error" }
          }
        }
      }
    }
  }
}
