{
  "openapi": "3.1.0",
  "info": {
    "title": "247Rep Developer API",
    "version": "1.0.0",
    "description": "Programmatic access to your 247Rep AI assistant across WhatsApp, Telegram, Email and Voice/SMS. Send and receive messages, manage contacts and conversations, run broadcasts, place AI voice calls, and subscribe to real-time webhook events.\n\nAuthenticate with a channel-scoped API key (`rep_live_…` or `rep_test_…`) generated in your dashboard under Developer API. Every response includes rate-limit headers. Sends, broadcasts, SMS and email deduct credits from your workspace balance.",
    "contact": {
      "name": "247Rep Support",
      "email": "support@247rep.app",
      "url": "https://247rep.app/api-reference"
    }
  },
  "servers": [
    {
      "url": "https://api.247rep.app/v1",
      "description": "Production"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Account",
      "description": "Identify the key's owner and read account state."
    },
    {
      "name": "WhatsApp",
      "description": "Send and read WhatsApp messages, conversations, contacts, broadcasts and templates."
    },
    {
      "name": "Telegram",
      "description": "Send Telegram messages and read Telegram conversations."
    },
    {
      "name": "Email",
      "description": "Send email and read threads/contacts."
    },
    {
      "name": "Voice & SMS",
      "description": "Place AI voice calls and send SMS."
    },
    {
      "name": "Webhooks",
      "description": "Subscribe to real-time events."
    },
    {
      "name": "Triggers",
      "description": "REST polling endpoints for no-code tools (Zapier/Make)."
    }
  ],
  "paths": {
    "/account": {
      "get": {
        "tags": [
          "Account"
        ],
        "summary": "Get account",
        "description": "Returns the identifiers, account and channel this API key belongs to. Use `id` (the stable workspace/account id) and `assistantId` to key your integration — emails can change, these do not.",
        "operationId": "getAccount",
        "responses": {
          "200": {
            "description": "Account details.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Account"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/messages/send": {
      "post": {
        "tags": [
          "WhatsApp"
        ],
        "summary": "Send a WhatsApp message",
        "description": "Send text, image, audio, video, document, template, interactive or location. Media is uploaded to Meta then sent (link mode is unreliable for signed URLs). Media pricing: a link you host = flat 1 credit; a URL from POST /v1/media (we host it) = billed by type (image 2 / video 5 / doc-audio 2). Text 1, template 3.",
        "operationId": "sendWhatsAppMessage",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendWhatsAppMessage"
              },
              "examples": {
                "text": {
                  "value": {
                    "to": "+2348030000000",
                    "type": "text",
                    "text": {
                      "body": "Your order has shipped."
                    }
                  }
                },
                "template": {
                  "value": {
                    "to": "+2348030000000",
                    "type": "template",
                    "template": {
                      "name": "order_update",
                      "language": {
                        "code": "en"
                      }
                    }
                  }
                },
                "image": {
                  "value": {
                    "to": "+2348030000000",
                    "type": "image",
                    "image": {
                      "link": "https://example.com/pic.jpg",
                      "caption": "New arrival"
                    }
                  }
                },
                "reply": {
                  "summary": "Quoted reply to a received message",
                  "value": {
                    "to": "+2348030000000",
                    "type": "text",
                    "text": {
                      "body": "Thanks for that!"
                    },
                    "replyTo": "clx9message123"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Message accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SentMessage"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/InsufficientCredits"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/messages": {
      "get": {
        "tags": [
          "WhatsApp"
        ],
        "summary": "List messages",
        "operationId": "listMessages",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "direction",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "inbound",
                "outbound"
              ]
            },
            "description": "Filter by message direction."
          }
        ],
        "responses": {
          "200": {
            "description": "A page of messages.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Message"
                      }
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/messages/{messageId}": {
      "get": {
        "tags": [
          "WhatsApp"
        ],
        "summary": "Get a message",
        "operationId": "getMessage",
        "parameters": [
          {
            "name": "messageId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/conversations": {
      "get": {
        "tags": [
          "WhatsApp"
        ],
        "summary": "List conversations",
        "operationId": "listConversations",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "open",
                "closed"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of conversations.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Conversation"
                      }
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/conversations/{conversationId}": {
      "get": {
        "tags": [
          "WhatsApp"
        ],
        "summary": "Get a conversation",
        "operationId": "getConversation",
        "parameters": [
          {
            "name": "conversationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The conversation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Conversation"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "patch": {
        "tags": [
          "WhatsApp"
        ],
        "summary": "Update a conversation",
        "description": "Update conversation settings. Set automationEnabled=false to pause AI auto-reply on this thread so a human can take over; set true to hand it back to the AI. Same toggle as the dashboard.",
        "operationId": "updateConversation",
        "parameters": [
          {
            "name": "conversationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateConversation"
              },
              "examples": {
                "pauseAi": {
                  "summary": "Pause AI (human takes over)",
                  "value": {
                    "automationEnabled": false
                  }
                },
                "resumeAi": {
                  "summary": "Resume AI",
                  "value": {
                    "automationEnabled": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UpdatedConversation"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/conversations/{conversationId}/messages": {
      "get": {
        "tags": [
          "WhatsApp"
        ],
        "summary": "List messages in a conversation",
        "operationId": "listConversationMessages",
        "parameters": [
          {
            "name": "conversationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of messages.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Message"
                      }
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/conversations/{conversationId}/close": {
      "post": {
        "tags": [
          "WhatsApp"
        ],
        "summary": "Close a conversation",
        "operationId": "closeConversation",
        "parameters": [
          {
            "name": "conversationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Conversation closed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Conversation"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/contacts": {
      "get": {
        "tags": [
          "WhatsApp"
        ],
        "summary": "List contacts",
        "operationId": "listContacts",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Match against name or phone."
          }
        ],
        "responses": {
          "200": {
            "description": "A page of contacts.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Contact"
                      }
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "WhatsApp"
        ],
        "summary": "Create or update a contact",
        "description": "Upsert by phone (E.164). Existing contacts with the same number are updated.",
        "operationId": "upsertContact",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpsertContact"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The contact.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Contact"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          }
        }
      }
    },
    "/contacts/{contactId}": {
      "get": {
        "tags": [
          "WhatsApp"
        ],
        "summary": "Get a contact",
        "operationId": "getContact",
        "parameters": [
          {
            "name": "contactId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The contact.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Contact"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "delete": {
        "tags": [
          "WhatsApp"
        ],
        "summary": "Delete a contact",
        "operationId": "deleteContact",
        "parameters": [
          {
            "name": "contactId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted."
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/broadcast": {
      "post": {
        "tags": [
          "WhatsApp"
        ],
        "summary": "Send a broadcast",
        "description": "Send one message to many contacts (max 1000). Business-initiated broadcasts on WhatsApp typically require a template. Deducts credits per recipient.",
        "operationId": "sendBroadcast",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Broadcast"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Broadcast queued.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "broadcastId": {
                      "type": "string"
                    },
                    "recipients": {
                      "type": "integer"
                    },
                    "status": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "$ref": "#/components/responses/InsufficientCredits"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/broadcast/{broadcastId}": {
      "get": {
        "tags": [
          "WhatsApp"
        ],
        "summary": "Get broadcast status",
        "operationId": "getBroadcast",
        "parameters": [
          {
            "name": "broadcastId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Broadcast status and per-recipient results."
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/templates": {
      "get": {
        "tags": [
          "WhatsApp"
        ],
        "summary": "List message templates",
        "description": "Approved WhatsApp templates available to this number, with name, language and status.",
        "operationId": "listTemplates",
        "responses": {
          "200": {
            "description": "Templates.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Template"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/telegram/send": {
      "post": {
        "tags": [
          "Telegram"
        ],
        "summary": "Send a Telegram message",
        "description": "Requires a Telegram-scoped key. The recipient is a numeric Telegram `chatId`, obtained from an inbound message (the `message.received` webhook or GET /telegram/conversations → `telegramChatId`). You can only message a user who has started your bot first. `@username` works ONLY for public channels your bot administers — not for individual users. Media pricing: a link you host = flat 1 credit; a URL from POST /v1/media (we host it) = billed by type (photo 2 / video 5 / doc-audio 2).",
        "operationId": "sendTelegramMessage",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendTelegramMessage"
              },
              "examples": {
                "text": {
                  "value": {
                    "chatId": "123456789",
                    "type": "text",
                    "text": "Your order has shipped."
                  }
                },
                "photo": {
                  "value": {
                    "chatId": "123456789",
                    "type": "photo",
                    "url": "https://example.com/pic.jpg",
                    "caption": "New arrival"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Message sent.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SentMessage"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "402": {
            "$ref": "#/components/responses/InsufficientCredits"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/telegram/conversations": {
      "get": {
        "tags": [
          "Telegram"
        ],
        "summary": "List Telegram conversations",
        "description": "Each conversation includes `telegramChatId` — the id you pass to /telegram/send to reply.",
        "operationId": "listTelegramConversations",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of conversations.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Conversation"
                      }
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/email/account": {
      "get": {
        "tags": [
          "Email"
        ],
        "summary": "Get email account",
        "operationId": "getEmailAccount",
        "responses": {
          "200": {
            "description": "Email account details."
          }
        }
      }
    },
    "/email/send": {
      "post": {
        "tags": [
          "Email"
        ],
        "summary": "Send an email",
        "operationId": "sendEmail",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendEmail"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Email sent.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SentMessage"
                }
              }
            }
          },
          "402": {
            "$ref": "#/components/responses/InsufficientCredits"
          }
        }
      }
    },
    "/email/threads": {
      "get": {
        "tags": [
          "Email"
        ],
        "summary": "List email threads",
        "operationId": "listEmailThreads",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "folder",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of threads."
          }
        }
      }
    },
    "/email/threads/{threadId}": {
      "get": {
        "tags": [
          "Email"
        ],
        "summary": "Get an email thread",
        "operationId": "getEmailThread",
        "parameters": [
          {
            "name": "threadId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The thread with messages."
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "patch": {
        "tags": [
          "Email"
        ],
        "summary": "Update an email thread",
        "description": "Mark read/unread, archive, etc.",
        "operationId": "updateEmailThread",
        "parameters": [
          {
            "name": "threadId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated."
          }
        }
      }
    },
    "/email/contacts": {
      "get": {
        "tags": [
          "Email"
        ],
        "summary": "List email contacts",
        "operationId": "listEmailContacts",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of contacts."
          }
        }
      }
    },
    "/email/webhooks": {
      "get": {
        "tags": [
          "Email"
        ],
        "summary": "List email webhooks",
        "operationId": "listEmailWebhooks",
        "responses": {
          "200": {
            "description": "Email webhook subscriptions."
          }
        }
      },
      "post": {
        "tags": [
          "Email"
        ],
        "summary": "Create an email webhook",
        "operationId": "createEmailWebhook",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Created."
          }
        }
      }
    },
    "/email/webhooks/{webhookId}": {
      "delete": {
        "tags": [
          "Email"
        ],
        "summary": "Delete an email webhook",
        "operationId": "deleteEmailWebhook",
        "parameters": [
          {
            "name": "webhookId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted."
          }
        }
      }
    },
    "/voip/calls": {
      "post": {
        "tags": [
          "Voice & SMS"
        ],
        "summary": "Place an AI voice call",
        "description": "Start an outbound AI-handled phone call to a number (E.164). Deducts voice credits per minute.",
        "operationId": "placeCall",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PlaceCall"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Call started.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "callId": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "$ref": "#/components/responses/InsufficientCredits"
          }
        }
      }
    },
    "/voip/sms": {
      "post": {
        "tags": [
          "Voice & SMS"
        ],
        "summary": "Send an SMS",
        "operationId": "sendSms",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendSms"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "SMS sent.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SentMessage"
                }
              }
            }
          },
          "402": {
            "$ref": "#/components/responses/InsufficientCredits"
          }
        }
      }
    },
    "/voip/conversations": {
      "get": {
        "tags": [
          "Voice & SMS"
        ],
        "summary": "List voice/SMS conversations",
        "operationId": "listVoipConversations",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of conversations."
          }
        }
      }
    },
    "/webhooks": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "List webhook subscriptions",
        "operationId": "listWebhooks",
        "responses": {
          "200": {
            "description": "Subscriptions.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WebhookSubscription"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Create a webhook subscription",
        "description": "Subscribe a URL to events. Deliveries are POSTed as JSON and signed with HMAC-SHA256 (verify the signature header against your secret).",
        "operationId": "createWebhook",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateWebhook"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookSubscription"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          }
        }
      }
    },
    "/webhooks/{webhookId}": {
      "delete": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Delete a webhook subscription",
        "operationId": "deleteWebhook",
        "parameters": [
          {
            "name": "webhookId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted."
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/triggers/new-message": {
      "get": {
        "tags": [
          "Triggers"
        ],
        "summary": "Poll new inbound messages",
        "description": "Zapier/Make REST polling. Up to 50 most-recent inbound messages, newest first, deduped by `id`.",
        "operationId": "triggerNewMessage",
        "responses": {
          "200": {
            "description": "Recent inbound messages."
          }
        }
      }
    },
    "/triggers/new-contact": {
      "get": {
        "tags": [
          "Triggers"
        ],
        "summary": "Poll new contacts",
        "operationId": "triggerNewContact",
        "responses": {
          "200": {
            "description": "Recent contacts."
          }
        }
      }
    },
    "/triggers/new-order": {
      "get": {
        "tags": [
          "Triggers"
        ],
        "summary": "Poll new orders",
        "operationId": "triggerNewOrder",
        "responses": {
          "200": {
            "description": "Recent orders."
          }
        }
      }
    },
    "/triggers/new-appointment": {
      "get": {
        "tags": [
          "Triggers"
        ],
        "summary": "Poll new appointments",
        "operationId": "triggerNewAppointment",
        "responses": {
          "200": {
            "description": "Recent appointments."
          }
        }
      }
    },
    "/triggers/campaign-completed": {
      "get": {
        "tags": [
          "Triggers"
        ],
        "summary": "Poll completed campaigns",
        "operationId": "triggerCampaignCompleted",
        "responses": {
          "200": {
            "description": "Recently completed campaigns."
          }
        }
      }
    },
    "/messages/{messageId}/react": {
      "post": {
        "tags": [
          "WhatsApp"
        ],
        "summary": "React to a WhatsApp message",
        "description": "Add an emoji reaction to a message (the same affordance as the dashboard). Send an empty emoji to remove your reaction. Free — no credits are charged.",
        "operationId": "reactToMessage",
        "parameters": [
          {
            "name": "messageId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The 247Rep message id (from a webhook or GET /v1/messages). A raw wamid is also accepted."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReactToMessage"
              },
              "examples": {
                "add": {
                  "summary": "Add a reaction",
                  "value": {
                    "emoji": "👍"
                  }
                },
                "remove": {
                  "summary": "Remove your reaction",
                  "value": {
                    "emoji": ""
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Reaction sent.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReactionResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/telegram/messages/{messageId}/react": {
      "post": {
        "tags": [
          "Telegram"
        ],
        "summary": "React to a Telegram message",
        "description": "Add an emoji reaction to a message (Bot API setMessageReaction). Send an empty emoji to remove it. Telegram permits only a fixed set of reaction emoji. Free — no credits.",
        "operationId": "reactToTelegramMessage",
        "parameters": [
          {
            "name": "messageId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The 247Rep message id (from a webhook or GET /v1/telegram/conversations/{id}/messages)."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReactToMessage"
              },
              "examples": {
                "add": {
                  "summary": "Add a reaction",
                  "value": {
                    "emoji": "🔥"
                  }
                },
                "remove": {
                  "summary": "Remove your reaction",
                  "value": {
                    "emoji": ""
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Reaction set.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReactionResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/media": {
      "post": {
        "tags": [
          "Media"
        ],
        "summary": "Upload a file and get a hosted URL",
        "description": "Upload a file to 247Rep and receive a hosted URL you can pass as the `link` (WhatsApp) or `url` (Telegram) on a send. Use this so you never have to expose your own storage publicly. Uploading is FREE; the SEND that references the returned URL is billed by media type (image 2 / video 5 / doc-audio 2). Sending a link you host yourself stays a flat 1 credit. Max 25MB.",
        "operationId": "uploadMedia",
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "file"
                ],
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary",
                    "description": "The file bytes."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Stored.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UploadedMedia"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "413": {
            "description": "File too large (max 25MB).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Your API key as a Bearer token: `Authorization: Bearer rep_live_…`. Keys are channel-scoped (WhatsApp / Telegram / Email) — using a key on the wrong channel returns 403. `rep_test_…` keys operate in test mode."
      }
    },
    "parameters": {
      "Limit": {
        "name": "limit",
        "in": "query",
        "schema": {
          "type": "integer",
          "default": 50,
          "maximum": 100,
          "minimum": 1
        },
        "description": "Page size (max 100)."
      },
      "Cursor": {
        "name": "cursor",
        "in": "query",
        "schema": {
          "type": "string"
        },
        "description": "Opaque cursor from a previous page's `pagination.nextCursor`."
      },
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "schema": {
          "type": "string"
        },
        "description": "Optional. A unique key to safely retry a write without duplicating it (Stripe-style)."
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Missing, malformed or revoked API key.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Forbidden": {
        "description": "Key is scoped to a different channel than the endpoint.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "BadRequest": {
        "description": "Validation error (see `message`).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "Resource not found.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "InsufficientCredits": {
        "description": "Workspace credit balance is too low for this action.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "IdempotencyConflict": {
        "description": "An Idempotency-Key was reused with a different payload, or a matching request is still in flight.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Rate limit exceeded. Retry after the `Retry-After` header (seconds).",
        "headers": {
          "Retry-After": {
            "schema": {
              "type": "integer"
            }
          },
          "X-RateLimit-Limit": {
            "schema": {
              "type": "integer"
            }
          },
          "X-RateLimit-Remaining": {
            "schema": {
              "type": "integer"
            }
          },
          "X-RateLimit-Reset": {
            "schema": {
              "type": "integer"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "description": "Machine-readable error code, e.g. INVALID_KEY, INSUFFICIENT_CREDITS, RATE_LIMIT_EXCEEDED, VALIDATION_ERROR, FORBIDDEN, NOT_FOUND."
          },
          "message": {
            "type": "string"
          },
          "docs": {
            "type": "string",
            "format": "uri"
          }
        },
        "required": [
          "code",
          "message"
        ]
      },
      "Pagination": {
        "type": "object",
        "properties": {
          "nextCursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to fetch the next page. Null on the last page."
          },
          "hasMore": {
            "type": "boolean"
          }
        }
      },
      "Account": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Stable account/workspace id this key belongs to."
          },
          "assistantId": {
            "type": "string",
            "description": "The channel/assistant this key drives."
          },
          "keyId": {
            "type": "string",
            "description": "The id of the API key that made the request."
          },
          "workspace": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "email": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "assistant": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "platform": {
                "type": "string",
                "enum": [
                  "WHATSAPP",
                  "TELEGRAM",
                  "EMAIL",
                  "VOIP",
                  "WEB"
                ]
              }
            }
          },
          "whatsappNumber": {
            "type": [
              "string",
              "null"
            ]
          },
          "creditsBalance": {
            "type": "number"
          },
          "environment": {
            "type": "string",
            "enum": [
              "live",
              "test"
            ]
          },
          "messagingTier": {
            "type": [
              "string",
              "null"
            ],
            "description": "WhatsApp messaging limit tier (from Meta)."
          },
          "qualityRating": {
            "type": [
              "string",
              "null"
            ],
            "description": "WhatsApp number quality rating (from Meta)."
          }
        }
      },
      "SendWhatsAppMessage": {
        "type": "object",
        "required": [
          "to",
          "type"
        ],
        "properties": {
          "to": {
            "type": "string",
            "description": "Recipient in E.164, e.g. +2348030000000."
          },
          "type": {
            "type": "string",
            "enum": [
              "text",
              "image",
              "audio",
              "video",
              "document",
              "template",
              "interactive",
              "location"
            ]
          },
          "text": {
            "type": "object",
            "properties": {
              "body": {
                "type": "string",
                "maxLength": 4096
              }
            }
          },
          "image": {
            "type": "object",
            "properties": {
              "link": {
                "type": "string",
                "format": "uri"
              },
              "caption": {
                "type": "string",
                "maxLength": 1024
              }
            }
          },
          "audio": {
            "type": "object",
            "properties": {
              "link": {
                "type": "string",
                "format": "uri"
              }
            }
          },
          "video": {
            "type": "object",
            "properties": {
              "link": {
                "type": "string",
                "format": "uri"
              },
              "caption": {
                "type": "string",
                "maxLength": 1024
              }
            }
          },
          "document": {
            "type": "object",
            "properties": {
              "link": {
                "type": "string",
                "format": "uri"
              },
              "caption": {
                "type": "string",
                "maxLength": 1024
              },
              "filename": {
                "type": "string",
                "maxLength": 256
              }
            }
          },
          "template": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string"
              },
              "language": {
                "type": "object",
                "properties": {
                  "code": {
                    "type": "string"
                  }
                }
              },
              "components": {
                "type": "array",
                "items": {}
              }
            }
          },
          "interactive": {
            "description": "WhatsApp interactive object (buttons/list), passed through to Meta."
          },
          "location": {
            "type": "object",
            "properties": {
              "latitude": {
                "type": "number"
              },
              "longitude": {
                "type": "number"
              },
              "name": {
                "type": "string"
              },
              "address": {
                "type": "string"
              }
            }
          },
          "replyTo": {
            "type": "string",
            "description": "Optional. Reply to an earlier message as a WhatsApp quoted reply. Accepts the 247Rep message id (the id returned by webhooks and GET /v1/messages) or the raw WhatsApp wamid. Ignored for template sends (Meta does not support quoting on templates)."
          }
        }
      },
      "SendTelegramMessage": {
        "type": "object",
        "required": [
          "chatId",
          "type"
        ],
        "properties": {
          "chatId": {
            "type": "string",
            "description": "Numeric Telegram chat id (e.g. \"123456789\"). Get it from an inbound message. @channelusername works only for public channels your bot administers."
          },
          "type": {
            "type": "string",
            "enum": [
              "text",
              "photo",
              "video",
              "document",
              "audio"
            ],
            "default": "text"
          },
          "text": {
            "type": "string",
            "maxLength": 4096,
            "description": "Required when type is text."
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Required for media types. Must be HTTPS and publicly fetchable by Telegram."
          },
          "caption": {
            "type": "string",
            "maxLength": 1024
          },
          "filename": {
            "type": "string",
            "maxLength": 256
          },
          "parseMode": {
            "type": "string",
            "enum": [
              "HTML",
              "MarkdownV2"
            ],
            "default": "HTML"
          },
          "replyTo": {
            "type": "string",
            "description": "Optional. Reply to an earlier message as a Telegram reply. Accepts the 247Rep message id (from webhooks / GET /v1/telegram/conversations/{id}/messages) or Telegram's numeric message_id. Resolved within the target chat (Telegram message ids are only unique per chat)."
          }
        }
      },
      "SendEmail": {
        "type": "object",
        "required": [
          "to",
          "subject"
        ],
        "properties": {
          "to": {
            "oneOf": [
              {
                "type": "string",
                "format": "email"
              },
              {
                "type": "array",
                "items": {
                  "type": "string",
                  "format": "email"
                }
              }
            ]
          },
          "cc": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "email"
            }
          },
          "bcc": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "email"
            }
          },
          "subject": {
            "type": "string",
            "maxLength": 998
          },
          "html": {
            "type": "string",
            "description": "HTML body (or use text)."
          },
          "text": {
            "type": "string",
            "description": "Plain-text body."
          },
          "replyTo": {
            "type": "string",
            "format": "email"
          },
          "threadId": {
            "type": "string",
            "description": "Send as a reply within an existing thread."
          },
          "attachments": {
            "type": "array",
            "maxItems": 20,
            "items": {
              "type": "object",
              "properties": {
                "filename": {
                  "type": "string"
                },
                "contentType": {
                  "type": "string"
                },
                "content": {
                  "type": "string",
                  "description": "Base64 content."
                },
                "url": {
                  "type": "string",
                  "format": "uri"
                }
              }
            }
          }
        }
      },
      "SendSms": {
        "type": "object",
        "required": [
          "to",
          "body"
        ],
        "properties": {
          "to": {
            "type": "string",
            "description": "Recipient number (E.164)."
          },
          "body": {
            "type": "string",
            "minLength": 1,
            "maxLength": 1600
          },
          "channelId": {
            "type": "string",
            "description": "Optional — the voice/SMS channel to send from."
          }
        }
      },
      "PlaceCall": {
        "type": "object",
        "required": [
          "to"
        ],
        "properties": {
          "to": {
            "type": "string",
            "description": "Number to call (E.164)."
          },
          "channelId": {
            "type": "string"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true,
            "description": "Arbitrary context passed to the AI."
          }
        }
      },
      "UpsertContact": {
        "type": "object",
        "required": [
          "phone"
        ],
        "properties": {
          "phone": {
            "type": "string",
            "description": "E.164."
          },
          "name": {
            "type": "string",
            "maxLength": 200
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true
          }
        }
      },
      "Broadcast": {
        "type": "object",
        "required": [
          "message"
        ],
        "properties": {
          "contactIds": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "minItems": 1,
            "maxItems": 1000,
            "description": "Target contacts. Omit to broadcast to all."
          },
          "message": {
            "type": "object",
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "text",
                  "image",
                  "template"
                ]
              },
              "text": {
                "type": "object",
                "properties": {
                  "body": {
                    "type": "string",
                    "maxLength": 4096
                  }
                }
              },
              "image": {
                "type": "object",
                "properties": {
                  "link": {
                    "type": "string",
                    "format": "uri"
                  },
                  "caption": {
                    "type": "string"
                  }
                }
              },
              "template": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "language": {
                    "type": "object",
                    "properties": {
                      "code": {
                        "type": "string"
                      }
                    }
                  },
                  "components": {
                    "type": "array",
                    "items": {}
                  }
                }
              }
            }
          }
        }
      },
      "CreateWebhook": {
        "type": "object",
        "required": [
          "url",
          "events"
        ],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048
          },
          "events": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "string",
              "enum": [
                "message.received",
                "message.sent",
                "message.delivered",
                "message.read",
                "message.failed"
              ]
            }
          },
          "secret": {
            "type": "string",
            "maxLength": 256,
            "description": "Used to HMAC-sign deliveries so you can verify them."
          }
        }
      },
      "WebhookSubscription": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Message": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "conversationId": {
            "type": "string"
          },
          "direction": {
            "type": "string",
            "enum": [
              "inbound",
              "outbound"
            ]
          },
          "type": {
            "type": "string"
          },
          "text": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": [
              "string",
              "null"
            ],
            "description": "sent, delivered, read, failed."
          },
          "from": {
            "type": [
              "string",
              "null"
            ]
          },
          "to": {
            "type": [
              "string",
              "null"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Conversation": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "contactName": {
            "type": [
              "string",
              "null"
            ]
          },
          "contactPhone": {
            "type": [
              "string",
              "null"
            ]
          },
          "telegramChatId": {
            "type": [
              "string",
              "null"
            ],
            "description": "For Telegram — the chatId to reply with."
          },
          "status": {
            "type": "string",
            "enum": [
              "open",
              "closed"
            ]
          },
          "lastMessageAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "Contact": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "phone": {
            "type": "string"
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "email": {
            "type": [
              "string",
              "null"
            ]
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Template": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "language": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "category": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "SentMessage": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "messageId": {
            "type": "string"
          },
          "conversationId": {
            "type": [
              "string",
              "null"
            ]
          },
          "creditsCharged": {
            "type": [
              "number",
              "null"
            ]
          },
          "replyTo": {
            "type": "string",
            "description": "Present when the send was a quoted reply; the 247Rep id of the replied-to message."
          }
        }
      },
      "ReactToMessage": {
        "type": "object",
        "required": [
          "emoji"
        ],
        "properties": {
          "emoji": {
            "type": "string",
            "maxLength": 16,
            "description": "Emoji to react with, e.g. \"👍\". Empty string removes the reaction."
          }
        }
      },
      "ReactionResult": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "messageId": {
            "type": "string"
          },
          "emoji": {
            "type": "string"
          },
          "removed": {
            "type": "boolean"
          }
        }
      },
      "UpdateConversation": {
        "type": "object",
        "properties": {
          "automationEnabled": {
            "type": "boolean",
            "description": "false pauses AI auto-reply on this conversation; true resumes it."
          }
        }
      },
      "UpdatedConversation": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "id": {
            "type": "string"
          },
          "automationEnabled": {
            "type": "boolean"
          },
          "status": {
            "type": "string"
          }
        }
      },
      "UploadedMedia": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "description": "247Rep-hosted URL. Pass this as the media link/url on a send; it will be billed by media type."
          },
          "mimeType": {
            "type": "string"
          },
          "size": {
            "type": "integer",
            "description": "Bytes."
          },
          "filename": {
            "type": "string"
          }
        }
      }
    }
  }
}