{
  "openapi": "3.1.0",
  "info": {
    "title": "ZAPPIO Public API",
    "version": "1.0.0",
    "description": "Messaging API for WhatsApp instances, messages, groups and webhooks. Authenticate with an API key (Authorization: Bearer <key>). This contract covers only the operations reachable with an API key; the dashboard, internal and billing endpoints are not part of it.",
    "license": {
      "name": "Proprietary",
      "identifier": "LicenseRef-Proprietary"
    }
  },
  "servers": [
    {
      "url": "https://zappio.cloud/api/v1",
      "description": "Producción"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Workspace",
      "description": "Identify the API key in use."
    },
    {
      "name": "Instances",
      "description": "WhatsApp instances (one linked number each)."
    },
    {
      "name": "Groups",
      "description": "Groups known to a connected instance."
    },
    {
      "name": "Messages",
      "description": "Send and read messages."
    },
    {
      "name": "Webhooks",
      "description": "Webhook endpoints and their deliveries."
    }
  ],
  "x-common-error-codes": [
    "UNAUTHENTICATED",
    "INVALID_API_KEY",
    "INSUFFICIENT_SCOPE",
    "WORKSPACE_SUSPENDED",
    "WORKSPACE_MISMATCH",
    "RATE_LIMITED",
    "VALIDATION_FAILED",
    "NOT_FOUND",
    "METHOD_NOT_ALLOWED",
    "PAYLOAD_TOO_LARGE",
    "INTERNAL_ERROR"
  ],
  "paths": {
    "/api-key": {
      "get": {
        "operationId": "getApiKey",
        "tags": [
          "Workspace"
        ],
        "summary": "Describe the API key in use",
        "description": "Returns the key id, name and scopes, and the workspace it is bound to. Needs no particular scope.",
        "responses": {
          "200": {
            "description": "The key and its workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyInfoResponse"
                },
                "example": {
                  "data": {
                    "id": "key_01EXAMPLE00000000000000001",
                    "name": "Backend",
                    "scopes": [
                      "instances:read",
                      "instances:write",
                      "messages:read",
                      "messages:send",
                      "webhooks:read",
                      "webhooks:write"
                    ],
                    "workspace": {
                      "id": "ten_01EXAMPLE00000000000000001",
                      "name": "Acme"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/instances": {
      "get": {
        "operationId": "listInstances",
        "tags": [
          "Instances"
        ],
        "summary": "List instances",
        "description": "All instances of the workspace, oldest first. Not paginated.",
        "security": [
          {
            "bearerAuth": [
              "instances:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "The instances.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InstanceList"
                },
                "example": {
                  "data": [
                    {
                      "id": "ins_01EXAMPLE00000000000000001",
                      "name": "Support line",
                      "status": "connected",
                      "phone_number": "5255000000003",
                      "profile_name": "Acme Support",
                      "profile_picture_url": null,
                      "paired": true,
                      "capabilities": [
                        "text",
                        "image",
                        "document",
                        "audio",
                        "video",
                        "groups"
                      ],
                      "last_error": null,
                      "status_changed_at": "2026-01-31T14:05:09+00:00",
                      "connected_at": "2026-01-31T14:05:09+00:00",
                      "disconnected_at": null,
                      "last_seen_at": "2026-01-31T14:05:09+00:00",
                      "created_at": "2026-01-31T14:05:09+00:00",
                      "updated_at": "2026-01-31T14:05:09+00:00"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "createInstance",
        "tags": [
          "Instances"
        ],
        "summary": "Create an instance",
        "description": "Creates an instance in status created. Connect it afterwards to pair a number. The number of instances is limited by the plan.",
        "security": [
          {
            "bearerAuth": [
              "instances:write"
            ]
          }
        ],
        "x-error-codes": [
          "INSTANCE_LIMIT_REACHED",
          "SUBSCRIPTION_REQUIRED"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InstanceWrite"
              },
              "example": {}
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new instance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InstanceResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/instances/{instance}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/InstanceId"
        }
      ],
      "get": {
        "operationId": "getInstance",
        "tags": [
          "Instances"
        ],
        "summary": "Get an instance",
        "security": [
          {
            "bearerAuth": [
              "instances:read"
            ]
          }
        ],
        "x-error-codes": [
          "INSTANCE_NOT_FOUND"
        ],
        "responses": {
          "200": {
            "description": "The instance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InstanceResponse"
                },
                "example": {
                  "data": {
                    "id": "ins_01EXAMPLE00000000000000001",
                    "name": "Support line",
                    "status": "connected",
                    "phone_number": "5255000000003",
                    "profile_name": "Acme Support",
                    "profile_picture_url": null,
                    "paired": true,
                    "capabilities": [
                      "text",
                      "image",
                      "document",
                      "audio",
                      "video",
                      "groups"
                    ],
                    "last_error": null,
                    "status_changed_at": "2026-01-31T14:05:09+00:00",
                    "connected_at": "2026-01-31T14:05:09+00:00",
                    "disconnected_at": null,
                    "last_seen_at": "2026-01-31T14:05:09+00:00",
                    "created_at": "2026-01-31T14:05:09+00:00",
                    "updated_at": "2026-01-31T14:05:09+00:00"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "patch": {
        "operationId": "updateInstance",
        "tags": [
          "Instances"
        ],
        "summary": "Rename an instance",
        "security": [
          {
            "bearerAuth": [
              "instances:write"
            ]
          }
        ],
        "x-error-codes": [
          "INSTANCE_NOT_FOUND"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InstanceWrite"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated instance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InstanceResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "delete": {
        "operationId": "deleteInstance",
        "tags": [
          "Instances"
        ],
        "summary": "Delete an instance",
        "description": "Closes the connection if it is live and removes the instance.",
        "security": [
          {
            "bearerAuth": [
              "instances:write"
            ]
          }
        ],
        "x-error-codes": [
          "INSTANCE_NOT_FOUND",
          "INSTANCE_BUSY",
          "GATEWAY_UNAVAILABLE",
          "GATEWAY_ERROR"
        ],
        "responses": {
          "204": {
            "description": "Deleted."
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "502": {
            "$ref": "#/components/responses/GatewayFailure"
          },
          "503": {
            "$ref": "#/components/responses/GatewayFailure"
          }
        }
      }
    },
    "/instances/{instance}/connect": {
      "parameters": [
        {
          "$ref": "#/components/parameters/InstanceId"
        }
      ],
      "post": {
        "operationId": "connectInstance",
        "tags": [
          "Instances"
        ],
        "summary": "Connect an instance",
        "description": "Starts the connection. It is asynchronous and idempotent (an instance that is already connecting or connected is returned unchanged). A first-time instance moves to qr_required; fetch the QR code and scan it with the phone. A linked instance reconnects without a QR.",
        "security": [
          {
            "bearerAuth": [
              "instances:write"
            ]
          }
        ],
        "x-error-codes": [
          "INSTANCE_NOT_FOUND",
          "INVALID_INSTANCE_STATE",
          "INSTANCE_BUSY",
          "GATEWAY_UNAVAILABLE",
          "GATEWAY_ERROR"
        ],
        "responses": {
          "202": {
            "description": "The connection was requested; poll the instance or wait for the instance.connected webhook.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InstanceResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "502": {
            "$ref": "#/components/responses/GatewayFailure"
          },
          "503": {
            "$ref": "#/components/responses/GatewayFailure"
          }
        }
      }
    },
    "/instances/{instance}/disconnect": {
      "parameters": [
        {
          "$ref": "#/components/parameters/InstanceId"
        }
      ],
      "post": {
        "operationId": "disconnectInstance",
        "tags": [
          "Instances"
        ],
        "summary": "Disconnect an instance",
        "description": "Closes the connection but keeps the linked session, so connect restores it without a QR. An instance that is not live is returned unchanged.",
        "security": [
          {
            "bearerAuth": [
              "instances:write"
            ]
          }
        ],
        "x-error-codes": [
          "INSTANCE_NOT_FOUND",
          "INVALID_INSTANCE_STATE",
          "INSTANCE_BUSY",
          "GATEWAY_UNAVAILABLE",
          "GATEWAY_ERROR"
        ],
        "responses": {
          "200": {
            "description": "The instance after disconnecting.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InstanceResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "502": {
            "$ref": "#/components/responses/GatewayFailure"
          },
          "503": {
            "$ref": "#/components/responses/GatewayFailure"
          }
        }
      }
    },
    "/instances/{instance}/logout": {
      "parameters": [
        {
          "$ref": "#/components/parameters/InstanceId"
        }
      ],
      "post": {
        "operationId": "logoutInstance",
        "tags": [
          "Instances"
        ],
        "summary": "Log the instance out of WhatsApp",
        "description": "Unlinks the number from this instance and discards its session. The next connect needs a new QR scan.",
        "security": [
          {
            "bearerAuth": [
              "instances:write"
            ]
          }
        ],
        "x-error-codes": [
          "INSTANCE_NOT_FOUND",
          "INVALID_INSTANCE_STATE",
          "INSTANCE_BUSY",
          "GATEWAY_UNAVAILABLE",
          "GATEWAY_ERROR"
        ],
        "responses": {
          "200": {
            "description": "The instance after logging out.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InstanceResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "502": {
            "$ref": "#/components/responses/GatewayFailure"
          },
          "503": {
            "$ref": "#/components/responses/GatewayFailure"
          }
        }
      }
    },
    "/instances/{instance}/qr": {
      "parameters": [
        {
          "$ref": "#/components/parameters/InstanceId"
        }
      ],
      "get": {
        "operationId": "getInstanceQr",
        "tags": [
          "Instances"
        ],
        "summary": "Get the pairing QR code",
        "description": "Available only while the instance is in status qr_required. The QR rotates; the response is never cached. Needs the instances:write scope because it pairs a number.",
        "security": [
          {
            "bearerAuth": [
              "instances:write"
            ]
          }
        ],
        "x-error-codes": [
          "INSTANCE_NOT_FOUND",
          "QR_NOT_AVAILABLE"
        ],
        "responses": {
          "200": {
            "description": "The current QR code as SVG.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QrResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/instances/{instance}/groups": {
      "parameters": [
        {
          "$ref": "#/components/parameters/InstanceId"
        }
      ],
      "get": {
        "operationId": "listGroups",
        "tags": [
          "Groups"
        ],
        "summary": "List the groups of an instance",
        "description": "Groups synchronised from the connected number, by name. Use a group id as the to field of a message.",
        "security": [
          {
            "bearerAuth": [
              "instances:read"
            ]
          }
        ],
        "x-error-codes": [
          "INSTANCE_NOT_FOUND"
        ],
        "responses": {
          "200": {
            "description": "The groups.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GroupList"
                },
                "example": {
                  "data": [
                    {
                      "id": "grp_01EXAMPLE00000000000000001",
                      "name": "Team Acme",
                      "participants_count": 12,
                      "synced_at": "2026-01-31T14:05:09+00:00"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/messages": {
      "get": {
        "operationId": "listMessages",
        "tags": [
          "Messages"
        ],
        "summary": "List messages",
        "description": "Inbound and outbound messages, newest first, with cursor pagination (follow meta.next_cursor).",
        "security": [
          {
            "bearerAuth": [
              "messages:read"
            ]
          }
        ],
        "x-error-codes": [
          "INSTANCE_NOT_FOUND"
        ],
        "parameters": [
          {
            "name": "instance",
            "in": "query",
            "description": "Only messages of this instance.",
            "schema": {
              "type": "string",
              "maxLength": 40
            }
          },
          {
            "name": "direction",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/MessageDirection"
            }
          },
          {
            "name": "type",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/MessageType"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "One status or a comma-separated list of statuses.",
            "schema": {
              "type": "string",
              "maxLength": 120
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Page size (default 25).",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "Opaque cursor from a previous page (meta.next_cursor).",
            "schema": {
              "type": "string",
              "maxLength": 512
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of messages.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageList"
                },
                "example": {
                  "data": [
                    {
                      "id": "msg_01EXAMPLE00000000000000001",
                      "instance_id": "ins_01EXAMPLE00000000000000001",
                      "direction": "outbound",
                      "type": "text",
                      "status": "queued",
                      "to": "5255000000001",
                      "from": null,
                      "group_id": null,
                      "text": "Your order 1042 has shipped",
                      "caption": null,
                      "media": null,
                      "error": null,
                      "created_at": "2026-01-31T14:05:09+00:00",
                      "queued_at": "2026-01-31T14:05:09+00:00",
                      "sent_at": null,
                      "delivered_at": null,
                      "read_at": null,
                      "failed_at": null,
                      "received_at": null
                    }
                  ],
                  "links": {
                    "first": null,
                    "last": null,
                    "prev": null,
                    "next": "https://zappio.cloud/api/v1/messages?limit=2&direction=outbound&cursor=EXAMPLECURSOR"
                  },
                  "meta": {
                    "path": "https://zappio.cloud/api/v1/messages",
                    "per_page": 2,
                    "next_cursor": "EXAMPLECURSOR",
                    "prev_cursor": null
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "sendMessage",
        "tags": [
          "Messages"
        ],
        "summary": "Send a message",
        "description": "Queues a text or media message (image, document, audio, video) to a phone number or a group. Sending is asynchronous - the response is 202 with status queued; follow the status through GET /messages/{message} or the message.* webhooks. Use JSON for text and multipart/form-data for media. Send an Idempotency-Key to make retries safe.",
        "security": [
          {
            "bearerAuth": [
              "messages:send"
            ]
          }
        ],
        "x-error-codes": [
          "INSTANCE_NOT_FOUND",
          "INVALID_RECIPIENT",
          "GROUP_NOT_FOUND",
          "UNSUPPORTED_MESSAGE_TYPE",
          "INSTANCE_NOT_CONNECTED",
          "INVALID_IDEMPOTENCY_KEY",
          "IDEMPOTENCY_KEY_REUSED",
          "INVALID_MEDIA_TYPE",
          "MEDIA_TOO_LARGE",
          "TRIAL_LIMIT_REACHED",
          "SUBSCRIPTION_REQUIRED",
          "SUBSCRIPTION_PAST_DUE",
          "SEND_BACKLOG"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "1 to 255 printable ASCII characters, no spaces. Keys are remembered for 24 hours. The same key with the same request returns the original message (200 and Idempotent-Replayed true). The same key with a different request is rejected with IDEMPOTENCY_KEY_REUSED.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendTextRequest"
              },
              "example": {
                "instance": "ins_01EXAMPLE00000000000000001",
                "to": "+52 55 0000 0001",
                "type": "text",
                "text": "Your order 1042 has shipped"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/SendMediaRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Replay of an earlier request with the same Idempotency-Key. Nothing new was queued.",
            "headers": {
              "Idempotent-Replayed": {
                "description": "Always true on a replay.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageResponse"
                },
                "example": {
                  "data": {
                    "id": "msg_01EXAMPLE00000000000000001",
                    "instance_id": "ins_01EXAMPLE00000000000000001",
                    "direction": "outbound",
                    "type": "text",
                    "status": "queued",
                    "to": "5255000000001",
                    "from": null,
                    "group_id": null,
                    "text": "Your order 1042 has shipped",
                    "caption": null,
                    "media": null,
                    "error": null,
                    "created_at": "2026-01-31T14:05:09+00:00",
                    "queued_at": "2026-01-31T14:05:09+00:00",
                    "sent_at": null,
                    "delivered_at": null,
                    "read_at": null,
                    "failed_at": null,
                    "received_at": null
                  }
                }
              }
            }
          },
          "202": {
            "description": "Accepted and queued.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageResponse"
                },
                "example": {
                  "data": {
                    "id": "msg_01EXAMPLE00000000000000001",
                    "instance_id": "ins_01EXAMPLE00000000000000001",
                    "direction": "outbound",
                    "type": "text",
                    "status": "queued",
                    "to": "5255000000001",
                    "from": null,
                    "group_id": null,
                    "text": "Your order 1042 has shipped",
                    "caption": null,
                    "media": null,
                    "error": null,
                    "created_at": "2026-01-31T14:05:09+00:00",
                    "queued_at": "2026-01-31T14:05:09+00:00",
                    "sent_at": null,
                    "delivered_at": null,
                    "read_at": null,
                    "failed_at": null,
                    "received_at": null
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/messages/{message}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/MessageId"
        }
      ],
      "get": {
        "operationId": "getMessage",
        "tags": [
          "Messages"
        ],
        "summary": "Get a message",
        "security": [
          {
            "bearerAuth": [
              "messages:read"
            ]
          }
        ],
        "x-error-codes": [
          "MESSAGE_NOT_FOUND"
        ],
        "responses": {
          "200": {
            "description": "The message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageResponse"
                },
                "example": {
                  "data": {
                    "id": "msg_01EXAMPLE00000000000000001",
                    "instance_id": "ins_01EXAMPLE00000000000000001",
                    "direction": "outbound",
                    "type": "text",
                    "status": "sent",
                    "to": "5255000000001",
                    "from": null,
                    "group_id": null,
                    "text": "Your order 1042 has shipped",
                    "caption": null,
                    "media": null,
                    "error": null,
                    "created_at": "2026-01-31T14:05:09+00:00",
                    "queued_at": "2026-01-31T14:05:09+00:00",
                    "sent_at": "2026-01-31T14:05:09+00:00",
                    "delivered_at": null,
                    "read_at": null,
                    "failed_at": null,
                    "received_at": null
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/messages/{message}/media": {
      "parameters": [
        {
          "$ref": "#/components/parameters/MessageId"
        }
      ],
      "get": {
        "operationId": "downloadMessageMedia",
        "tags": [
          "Messages"
        ],
        "summary": "Download the media of a message",
        "description": "Streams the stored file as an attachment. Only messages whose media.available is true have a file.",
        "security": [
          {
            "bearerAuth": [
              "messages:read"
            ]
          }
        ],
        "x-error-codes": [
          "MESSAGE_NOT_FOUND",
          "MEDIA_NOT_AVAILABLE"
        ],
        "responses": {
          "200": {
            "description": "The file. Content-Type is the stored MIME type.",
            "content": {
              "application/octet-stream": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/webhooks": {
      "get": {
        "operationId": "listWebhooks",
        "tags": [
          "Webhooks"
        ],
        "summary": "List webhook endpoints",
        "security": [
          {
            "bearerAuth": [
              "webhooks:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "The endpoints, newest first. meta.configured is true when an endpoint is enabled and has delivered successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "createWebhook",
        "tags": [
          "Webhooks"
        ],
        "summary": "Create a webhook endpoint",
        "description": "The endpoint is created enabled. The signing secret is returned only in this response (and when it is rotated). Store it; later reads show only a hint.",
        "security": [
          {
            "bearerAuth": [
              "webhooks:write"
            ]
          }
        ],
        "x-error-codes": [
          "INVALID_WEBHOOK_URL",
          "WEBHOOK_LIMIT_REACHED"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookCreate"
              },
              "example": {
                "url": "https://tu-app.com/zappio",
                "events": [
                  "message.received",
                  "message.delivered"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The endpoint, including its secret.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "enum": [
                    "no-store"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointWithSecretResponse"
                },
                "example": {
                  "data": {
                    "id": "wh_01EXAMPLE00000000000000001",
                    "url": "https://tu-app.com/zappio",
                    "description": null,
                    "events": [
                      "message.received",
                      "message.delivered"
                    ],
                    "status": "enabled",
                    "secret_hint": "…PLE0",
                    "last_delivery": null,
                    "disabled_at": null,
                    "disabled_reason": null,
                    "created_at": "2026-01-31T14:05:09+00:00",
                    "updated_at": "2026-01-31T14:05:09+00:00",
                    "secret": "zpwh_EXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLE0"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/webhooks/{webhook}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/WebhookId"
        }
      ],
      "get": {
        "operationId": "getWebhook",
        "tags": [
          "Webhooks"
        ],
        "summary": "Get a webhook endpoint",
        "security": [
          {
            "bearerAuth": [
              "webhooks:read"
            ]
          }
        ],
        "x-error-codes": [
          "WEBHOOK_NOT_FOUND"
        ],
        "responses": {
          "200": {
            "description": "The endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "patch": {
        "operationId": "updateWebhook",
        "tags": [
          "Webhooks"
        ],
        "summary": "Update a webhook endpoint",
        "description": "Change the url, the subscribed events, the description or the status (enabled or disabled). Every field is optional.",
        "security": [
          {
            "bearerAuth": [
              "webhooks:write"
            ]
          }
        ],
        "x-error-codes": [
          "WEBHOOK_NOT_FOUND",
          "INVALID_WEBHOOK_URL"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "delete": {
        "operationId": "deleteWebhook",
        "tags": [
          "Webhooks"
        ],
        "summary": "Delete a webhook endpoint",
        "security": [
          {
            "bearerAuth": [
              "webhooks:write"
            ]
          }
        ],
        "x-error-codes": [
          "WEBHOOK_NOT_FOUND"
        ],
        "responses": {
          "204": {
            "description": "Deleted."
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/webhooks/{webhook}/rotate-secret": {
      "parameters": [
        {
          "$ref": "#/components/parameters/WebhookId"
        }
      ],
      "post": {
        "operationId": "rotateWebhookSecret",
        "tags": [
          "Webhooks"
        ],
        "summary": "Rotate the signing secret",
        "description": "Issues a new secret, returned only in this response. The previous secret stops being used immediately.",
        "security": [
          {
            "bearerAuth": [
              "webhooks:write"
            ]
          }
        ],
        "x-error-codes": [
          "WEBHOOK_NOT_FOUND"
        ],
        "responses": {
          "200": {
            "description": "The endpoint with its new secret.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "enum": [
                    "no-store"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointWithSecretResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/webhooks/{webhook}/test": {
      "parameters": [
        {
          "$ref": "#/components/parameters/WebhookId"
        }
      ],
      "post": {
        "operationId": "testWebhook",
        "tags": [
          "Webhooks"
        ],
        "summary": "Send a test event",
        "description": "Queues a webhook.test event to the endpoint. The endpoint must be enabled.",
        "security": [
          {
            "bearerAuth": [
              "webhooks:write"
            ]
          }
        ],
        "x-error-codes": [
          "WEBHOOK_NOT_FOUND",
          "WEBHOOK_DISABLED"
        ],
        "responses": {
          "202": {
            "description": "The queued test delivery.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryResponse"
                },
                "example": {
                  "data": {
                    "id": "whd_01EXAMPLE00000000000000001",
                    "webhook_id": "wh_01EXAMPLE00000000000000001",
                    "event": {
                      "id": "evt_01EXAMPLE00000000000000001",
                      "type": "webhook.test",
                      "occurred_at": "2026-01-31T14:05:09+00:00"
                    },
                    "status": "pending",
                    "attempts": 0,
                    "max_attempts": 8,
                    "next_retry_at": null,
                    "response_status": null,
                    "error_code": null,
                    "last_attempt_at": null,
                    "delivered_at": null,
                    "created_at": "2026-01-31T14:05:09+00:00"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/webhooks/{webhook}/deliveries": {
      "parameters": [
        {
          "$ref": "#/components/parameters/WebhookId"
        }
      ],
      "get": {
        "operationId": "listWebhookDeliveries",
        "tags": [
          "Webhooks"
        ],
        "summary": "List the deliveries of an endpoint",
        "description": "Newest first, with cursor pagination (follow meta.next_cursor).",
        "security": [
          {
            "bearerAuth": [
              "webhooks:read"
            ]
          }
        ],
        "x-error-codes": [
          "WEBHOOK_NOT_FOUND"
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/DeliveryStatus"
            }
          },
          {
            "name": "event",
            "in": "query",
            "description": "Event type, for example message.received.",
            "schema": {
              "type": "string",
              "maxLength": 40
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Page size (default 25).",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of deliveries.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryList"
                },
                "example": {
                  "data": [
                    {
                      "id": "whd_01EXAMPLE00000000000000001",
                      "webhook_id": "wh_01EXAMPLE00000000000000001",
                      "event": {
                        "id": "evt_01EXAMPLE00000000000000001",
                        "type": "webhook.test",
                        "occurred_at": "2026-01-31T14:05:09+00:00"
                      },
                      "status": "success",
                      "attempts": 1,
                      "max_attempts": 8,
                      "next_retry_at": null,
                      "response_status": 200,
                      "error_code": null,
                      "last_attempt_at": "2026-01-31T14:05:09+00:00",
                      "delivered_at": "2026-01-31T14:05:09+00:00",
                      "created_at": "2026-01-31T14:05:09+00:00"
                    }
                  ],
                  "meta": {
                    "next_cursor": null,
                    "per_page": 5
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/webhooks/{webhook}/deliveries/retry-failed": {
      "parameters": [
        {
          "$ref": "#/components/parameters/WebhookId"
        }
      ],
      "post": {
        "operationId": "retryFailedWebhookDeliveries",
        "tags": [
          "Webhooks"
        ],
        "summary": "Retry failed deliveries",
        "description": "Re-queues up to 100 deliveries in status failed or exhausted for one more attempt. The endpoint must be enabled.",
        "security": [
          {
            "bearerAuth": [
              "webhooks:write"
            ]
          }
        ],
        "x-error-codes": [
          "WEBHOOK_NOT_FOUND",
          "WEBHOOK_DISABLED"
        ],
        "responses": {
          "202": {
            "description": "How many deliveries were re-queued and how many still wait.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RetryFailedResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/webhook-deliveries/{delivery}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/DeliveryId"
        }
      ],
      "get": {
        "operationId": "getWebhookDelivery",
        "tags": [
          "Webhooks"
        ],
        "summary": "Get a delivery with its attempts",
        "description": "Includes the request that was sent (URL, payload and the non-secret headers; the signature and timestamp headers are not repeated) and the log of attempts.",
        "security": [
          {
            "bearerAuth": [
              "webhooks:read"
            ]
          }
        ],
        "x-error-codes": [
          "WEBHOOK_DELIVERY_NOT_FOUND"
        ],
        "responses": {
          "200": {
            "description": "The delivery.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryDetailResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/webhook-deliveries/{delivery}/retry": {
      "parameters": [
        {
          "$ref": "#/components/parameters/DeliveryId"
        }
      ],
      "post": {
        "operationId": "retryWebhookDelivery",
        "tags": [
          "Webhooks"
        ],
        "summary": "Retry one delivery",
        "description": "Queues a manual attempt. Not allowed while the delivery is still being attempted or when its endpoint is disabled or deleted.",
        "security": [
          {
            "bearerAuth": [
              "webhooks:write"
            ]
          }
        ],
        "x-error-codes": [
          "WEBHOOK_DELIVERY_NOT_FOUND",
          "WEBHOOK_RETRY_NOT_ALLOWED"
        ],
        "responses": {
          "202": {
            "description": "The delivery, queued again.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "API key",
        "description": "An API key created in the dashboard (Authorization: Bearer <key>). The scopes listed on each operation must be granted to the key: instances:read, instances:write, messages:read, messages:send, webhooks:read, webhooks:write."
      }
    },
    "parameters": {
      "InstanceId": {
        "name": "instance",
        "in": "path",
        "required": true,
        "description": "Instance id (ins_...).",
        "schema": {
          "type": "string"
        }
      },
      "MessageId": {
        "name": "message",
        "in": "path",
        "required": true,
        "description": "Message id (msg_...).",
        "schema": {
          "type": "string"
        }
      },
      "WebhookId": {
        "name": "webhook",
        "in": "path",
        "required": true,
        "description": "Webhook endpoint id.",
        "schema": {
          "type": "string"
        }
      },
      "DeliveryId": {
        "name": "delivery",
        "in": "path",
        "required": true,
        "description": "Webhook delivery id.",
        "schema": {
          "type": "string"
        }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "The API key is missing or not valid (UNAUTHENTICATED, INVALID_API_KEY).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "Forbidden": {
        "description": "The key lacks the scope (INSUFFICIENT_SCOPE), the workspace is suspended (WORKSPACE_SUSPENDED), or the plan does not allow it (for example INSTANCE_LIMIT_REACHED, WEBHOOK_LIMIT_REACHED).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "PaymentRequired": {
        "description": "The workspace needs a subscription (SUBSCRIPTION_REQUIRED, SUBSCRIPTION_PAST_DUE) or the Developer Trial message limit was reached (TRIAL_LIMIT_REACHED).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "NotFound": {
        "description": "The resource does not exist in this workspace.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "Conflict": {
        "description": "The request conflicts with the current state (for example INSTANCE_NOT_CONNECTED, INVALID_INSTANCE_STATE, INSTANCE_BUSY, QR_NOT_AVAILABLE, WEBHOOK_DISABLED, WEBHOOK_RETRY_NOT_ALLOWED).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "PayloadTooLarge": {
        "description": "The file or request body is too large (MEDIA_TOO_LARGE, PAYLOAD_TOO_LARGE).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "UnsupportedMediaType": {
        "description": "The file type is not accepted for this message type (INVALID_MEDIA_TYPE).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "ValidationFailed": {
        "description": "The request is invalid (VALIDATION_FAILED, with details.fields) or a business rule rejected it (INVALID_RECIPIENT, UNSUPPORTED_MESSAGE_TYPE, INVALID_IDEMPOTENCY_KEY, IDEMPOTENCY_KEY_REUSED, INVALID_WEBHOOK_URL).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Too many requests (RATE_LIMITED, or SEND_BACKLOG when the instance has too many messages waiting). Wait Retry-After seconds.",
        "headers": {
          "Retry-After": {
            "description": "Seconds to wait before retrying.",
            "schema": {
              "type": "integer"
            }
          },
          "X-RateLimit-Limit": {
            "description": "The limit that applied.",
            "schema": {
              "type": "integer"
            }
          },
          "X-RateLimit-Remaining": {
            "description": "Requests left in the window (0 here).",
            "schema": {
              "type": "integer"
            }
          },
          "X-RateLimit-Reset": {
            "description": "Unix time when the window resets.",
            "schema": {
              "type": "integer"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "GatewayFailure": {
        "description": "The messaging gateway failed or is unavailable (GATEWAY_ERROR 502, GATEWAY_UNAVAILABLE 503). Retry later.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      }
    },
    "schemas": {
      "ErrorResponse": {
        "type": "object",
        "required": [
          "error"
        ],
        "additionalProperties": false,
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message",
              "request_id"
            ],
            "additionalProperties": false,
            "properties": {
              "code": {
                "type": "string",
                "description": "Stable machine-readable code. Branch on this, not on the message."
              },
              "message": {
                "type": "string"
              },
              "request_id": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Correlation id; quote it when contacting support."
              },
              "details": {
                "type": "object",
                "description": "Extra safe data. VALIDATION_FAILED carries fields (field name to list of messages); RATE_LIMITED-style errors may carry retry_after."
              }
            }
          }
        }
      },
      "ApiKeyInfoResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "additionalProperties": false,
        "properties": {
          "data": {
            "type": "object",
            "required": [
              "id",
              "name",
              "scopes",
              "workspace"
            ],
            "additionalProperties": false,
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "scopes": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Scope"
                }
              },
              "workspace": {
                "type": "object",
                "required": [
                  "id",
                  "name"
                ],
                "additionalProperties": false,
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      },
      "Scope": {
        "type": "string",
        "enum": [
          "instances:read",
          "instances:write",
          "messages:read",
          "messages:send",
          "webhooks:read",
          "webhooks:write"
        ]
      },
      "InstanceStatus": {
        "type": "string",
        "description": "created (never connected), qr_required (scan the QR), connecting, connected, reconnecting (the provider is restoring the link), disconnected (closed by you or the network; the session is kept), logged_out (unlinked from the phone), error (see last_error).",
        "enum": [
          "created",
          "qr_required",
          "connecting",
          "connected",
          "reconnecting",
          "disconnected",
          "logged_out",
          "error"
        ]
      },
      "Capability": {
        "type": "string",
        "enum": [
          "text",
          "image",
          "document",
          "audio",
          "video",
          "groups"
        ]
      },
      "InstanceWrite": {
        "type": "object",
        "required": [
          "name"
        ],
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          }
        }
      },
      "Instance": {
        "type": "object",
        "required": [
          "id",
          "name",
          "status",
          "phone_number",
          "profile_name",
          "profile_picture_url",
          "paired",
          "capabilities",
          "last_error",
          "status_changed_at",
          "connected_at",
          "disconnected_at",
          "last_seen_at",
          "created_at",
          "updated_at"
        ],
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string",
            "description": "Public id (ins_...)."
          },
          "name": {
            "type": "string"
          },
          "status": {
            "$ref": "#/components/schemas/InstanceStatus"
          },
          "phone_number": {
            "type": [
              "string",
              "null"
            ],
            "description": "The linked number, digits only, once known."
          },
          "profile_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "profile_picture_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "paired": {
            "type": "boolean",
            "description": "True when a number is linked to the instance."
          },
          "capabilities": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Capability"
            }
          },
          "last_error": {
            "type": [
              "string",
              "null"
            ],
            "description": "Lowercase code of the last failure that put the instance in status error (for example gateway_unavailable)."
          },
          "status_changed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "connected_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "disconnected_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "last_seen_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "InstanceResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "additionalProperties": false,
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Instance"
          }
        }
      },
      "InstanceList": {
        "type": "object",
        "required": [
          "data"
        ],
        "additionalProperties": false,
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Instance"
            }
          }
        }
      },
      "QrResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "additionalProperties": false,
        "properties": {
          "data": {
            "type": "object",
            "required": [
              "instance_id",
              "format",
              "svg",
              "expires_at"
            ],
            "additionalProperties": false,
            "properties": {
              "instance_id": {
                "type": "string"
              },
              "format": {
                "type": "string",
                "enum": [
                  "svg"
                ]
              },
              "svg": {
                "type": "string",
                "description": "The QR code as an SVG document."
              },
              "expires_at": {
                "type": "string",
                "format": "date-time"
              }
            }
          }
        }
      },
      "Group": {
        "type": "object",
        "required": [
          "id",
          "name",
          "participants_count",
          "synced_at"
        ],
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string",
            "description": "Public id (grp_...). Use it as the to field of a message."
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "participants_count": {
            "type": [
              "integer",
              "null"
            ]
          },
          "synced_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "GroupList": {
        "type": "object",
        "required": [
          "data"
        ],
        "additionalProperties": false,
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Group"
            }
          }
        }
      },
      "MessageType": {
        "type": "string",
        "enum": [
          "text",
          "image",
          "document",
          "audio",
          "video"
        ]
      },
      "MessageDirection": {
        "type": "string",
        "enum": [
          "outbound",
          "inbound"
        ]
      },
      "MessageStatus": {
        "type": "string",
        "description": "Outbound - queued, processing, sent, delivered, read, failed. Inbound - received.",
        "enum": [
          "queued",
          "processing",
          "sent",
          "delivered",
          "read",
          "failed",
          "received"
        ]
      },
      "SendTextRequest": {
        "type": "object",
        "required": [
          "instance",
          "to",
          "type",
          "text"
        ],
        "additionalProperties": false,
        "properties": {
          "instance": {
            "type": "string",
            "maxLength": 40,
            "description": "Instance id (ins_...). It must be connected."
          },
          "to": {
            "type": "string",
            "maxLength": 64,
            "description": "A phone number in international format (country code first; spaces, dashes, parentheses and a leading + are ignored; 8 to 15 digits) or a group id (grp_...)."
          },
          "type": {
            "type": "string",
            "enum": [
              "text"
            ]
          },
          "text": {
            "type": "string",
            "maxLength": 4096
          }
        }
      },
      "SendMediaRequest": {
        "type": "object",
        "required": [
          "instance",
          "to",
          "type",
          "file"
        ],
        "additionalProperties": false,
        "properties": {
          "instance": {
            "type": "string",
            "maxLength": 40
          },
          "to": {
            "type": "string",
            "maxLength": 64
          },
          "type": {
            "type": "string",
            "enum": [
              "image",
              "document",
              "audio",
              "video"
            ]
          },
          "file": {
            "type": "string",
            "format": "binary",
            "description": "Accepted types: image (jpeg, png, webp; 5 MB), audio (mpeg, ogg, mp4, aac, amr, x-m4a; 16 MB), video (mp4, 3gpp; 16 MB), document (pdf, plain text, csv, zip, Word, Excel, PowerPoint; 16 MB). Limits are the defaults of the deployment."
          },
          "caption": {
            "type": "string",
            "maxLength": 1024,
            "description": "Ignored for audio."
          },
          "filename": {
            "type": "string",
            "maxLength": 200
          }
        }
      },
      "MessageMedia": {
        "type": "object",
        "required": [
          "mime_type",
          "size",
          "filename",
          "available"
        ],
        "additionalProperties": false,
        "properties": {
          "mime_type": {
            "type": [
              "string",
              "null"
            ]
          },
          "size": {
            "type": [
              "integer",
              "null"
            ]
          },
          "filename": {
            "type": [
              "string",
              "null"
            ]
          },
          "available": {
            "type": "boolean",
            "description": "True when the file can be downloaded from /messages/{message}/media."
          }
        }
      },
      "MessageError": {
        "type": "object",
        "required": [
          "code",
          "message"
        ],
        "additionalProperties": false,
        "properties": {
          "code": {
            "type": "string",
            "enum": [
              "MESSAGE_SEND_EXPIRED",
              "INSTANCE_NOT_CONNECTED",
              "INVALID_RECIPIENT",
              "RECIPIENT_NOT_ON_WHATSAPP",
              "MEDIA_UNAVAILABLE",
              "UNSUPPORTED_MESSAGE_TYPE",
              "GATEWAY_UNAVAILABLE",
              "MESSAGE_SEND_FAILED"
            ]
          },
          "message": {
            "type": "string"
          }
        }
      },
      "Message": {
        "type": "object",
        "required": [
          "id",
          "instance_id",
          "direction",
          "type",
          "status",
          "to",
          "from",
          "group_id",
          "text",
          "caption",
          "media",
          "error",
          "created_at",
          "queued_at",
          "sent_at",
          "delivered_at",
          "read_at",
          "failed_at",
          "received_at"
        ],
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string",
            "description": "Public id (msg_...)."
          },
          "instance_id": {
            "type": "string"
          },
          "direction": {
            "$ref": "#/components/schemas/MessageDirection"
          },
          "type": {
            "$ref": "#/components/schemas/MessageType"
          },
          "status": {
            "$ref": "#/components/schemas/MessageStatus"
          },
          "to": {
            "type": [
              "string",
              "null"
            ],
            "description": "Outbound only - the phone number (digits) or the group id."
          },
          "from": {
            "type": [
              "string",
              "null"
            ],
            "description": "Inbound only - the sender phone number (digits)."
          },
          "group_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "text": {
            "type": [
              "string",
              "null"
            ]
          },
          "caption": {
            "type": [
              "string",
              "null"
            ]
          },
          "media": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/MessageMedia"
              },
              {
                "type": "null"
              }
            ]
          },
          "error": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/MessageError"
              },
              {
                "type": "null"
              }
            ],
            "description": "Set when status is failed."
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "queued_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "sent_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "delivered_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "read_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "failed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "received_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "MessageResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "additionalProperties": false,
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Message"
          }
        }
      },
      "MessageList": {
        "type": "object",
        "required": [
          "data",
          "links",
          "meta"
        ],
        "additionalProperties": false,
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Message"
            }
          },
          "links": {
            "type": "object",
            "additionalProperties": true,
            "description": "Laravel pagination links (prev and next URLs or null). Prefer meta.next_cursor."
          },
          "meta": {
            "type": "object",
            "required": [
              "per_page",
              "next_cursor",
              "prev_cursor"
            ],
            "additionalProperties": true,
            "properties": {
              "per_page": {
                "type": "integer"
              },
              "next_cursor": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Pass as the cursor parameter to get the next page; null on the last page."
              },
              "prev_cursor": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          }
        }
      },
      "EventType": {
        "type": "string",
        "description": "Events an endpoint can subscribe to. webhook.test is sent only by the test operation.",
        "enum": [
          "message.received",
          "message.sent",
          "message.delivered",
          "message.read",
          "message.failed",
          "instance.connected",
          "instance.disconnected",
          "instance.qr_required",
          "instance.error"
        ]
      },
      "WebhookStatus": {
        "type": "string",
        "enum": [
          "enabled",
          "disabled"
        ]
      },
      "WebhookCreate": {
        "type": "object",
        "required": [
          "url",
          "events"
        ],
        "additionalProperties": false,
        "properties": {
          "url": {
            "type": "string",
            "maxLength": 2048,
            "description": "HTTPS URL of your receiver (port 443 or 8443). Private and loopback hosts are rejected outside development."
          },
          "events": {
            "type": "array",
            "minItems": 1,
            "maxItems": 20,
            "uniqueItems": true,
            "items": {
              "$ref": "#/components/schemas/EventType"
            }
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 255
          }
        }
      },
      "WebhookUpdate": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "url": {
            "type": "string",
            "maxLength": 2048
          },
          "events": {
            "type": "array",
            "minItems": 1,
            "maxItems": 20,
            "uniqueItems": true,
            "items": {
              "$ref": "#/components/schemas/EventType"
            }
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 255
          },
          "status": {
            "$ref": "#/components/schemas/WebhookStatus"
          }
        }
      },
      "DeliveryStatus": {
        "type": "string",
        "description": "pending (queued), retrying (failed, will be retried), success, failed (manual retry possible), exhausted (all attempts used).",
        "enum": [
          "pending",
          "retrying",
          "success",
          "failed",
          "exhausted"
        ]
      },
      "WebhookLastDelivery": {
        "type": "object",
        "required": [
          "id",
          "status",
          "response_status",
          "at"
        ],
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string"
          },
          "status": {
            "$ref": "#/components/schemas/DeliveryStatus"
          },
          "response_status": {
            "type": [
              "integer",
              "null"
            ]
          },
          "at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "WebhookEndpoint": {
        "type": "object",
        "required": [
          "id",
          "url",
          "description",
          "events",
          "status",
          "secret_hint",
          "last_delivery",
          "disabled_at",
          "disabled_reason",
          "created_at",
          "updated_at"
        ],
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "events": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EventType"
            }
          },
          "status": {
            "$ref": "#/components/schemas/WebhookStatus"
          },
          "secret_hint": {
            "type": "string",
            "description": "The last four characters of the secret, for identification."
          },
          "last_delivery": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/WebhookLastDelivery"
              },
              {
                "type": "null"
              }
            ]
          },
          "disabled_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "disabled_reason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why the endpoint was disabled (for example automatically after repeated failures)."
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "WebhookEndpointWithSecret": {
        "type": "object",
        "required": [
          "id",
          "url",
          "description",
          "events",
          "status",
          "secret_hint",
          "last_delivery",
          "disabled_at",
          "disabled_reason",
          "created_at",
          "updated_at",
          "secret"
        ],
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "events": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EventType"
            }
          },
          "status": {
            "$ref": "#/components/schemas/WebhookStatus"
          },
          "secret_hint": {
            "type": "string"
          },
          "last_delivery": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/WebhookLastDelivery"
              },
              {
                "type": "null"
              }
            ]
          },
          "disabled_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "disabled_reason": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "secret": {
            "type": "string",
            "description": "The signing secret (zpwh_...). Shown only here."
          }
        }
      },
      "WebhookEndpointResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "additionalProperties": false,
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebhookEndpoint"
          }
        }
      },
      "WebhookEndpointWithSecretResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "additionalProperties": false,
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebhookEndpointWithSecret"
          }
        }
      },
      "WebhookEndpointList": {
        "type": "object",
        "required": [
          "data",
          "meta"
        ],
        "additionalProperties": false,
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookEndpoint"
            }
          },
          "meta": {
            "type": "object",
            "required": [
              "configured"
            ],
            "additionalProperties": false,
            "properties": {
              "configured": {
                "type": "boolean"
              }
            }
          }
        }
      },
      "WebhookDeliveryEvent": {
        "type": "object",
        "required": [
          "id",
          "type",
          "occurred_at"
        ],
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "occurred_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "WebhookDelivery": {
        "type": "object",
        "required": [
          "id",
          "webhook_id",
          "event",
          "status",
          "attempts",
          "max_attempts",
          "next_retry_at",
          "response_status",
          "error_code",
          "last_attempt_at",
          "delivered_at",
          "created_at"
        ],
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string"
          },
          "webhook_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "event": {
            "$ref": "#/components/schemas/WebhookDeliveryEvent"
          },
          "status": {
            "$ref": "#/components/schemas/DeliveryStatus"
          },
          "attempts": {
            "type": "integer"
          },
          "max_attempts": {
            "type": "integer"
          },
          "next_retry_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "response_status": {
            "type": [
              "integer",
              "null"
            ],
            "description": "HTTP status your receiver answered with in the last attempt."
          },
          "error_code": {
            "type": [
              "string",
              "null"
            ],
            "description": "HTTP_ERROR, TIMEOUT, CONNECTION_FAILED, REDIRECT_NOT_FOLLOWED or another delivery failure code."
          },
          "last_attempt_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "delivered_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "WebhookDeliveryDetail": {
        "type": "object",
        "required": [
          "id",
          "webhook_id",
          "event",
          "status",
          "attempts",
          "max_attempts",
          "next_retry_at",
          "response_status",
          "error_code",
          "last_attempt_at",
          "delivered_at",
          "created_at",
          "request",
          "attempt_log"
        ],
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string"
          },
          "webhook_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "event": {
            "$ref": "#/components/schemas/WebhookDeliveryEvent"
          },
          "status": {
            "$ref": "#/components/schemas/DeliveryStatus"
          },
          "attempts": {
            "type": "integer"
          },
          "max_attempts": {
            "type": "integer"
          },
          "next_retry_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "response_status": {
            "type": [
              "integer",
              "null"
            ]
          },
          "error_code": {
            "type": [
              "string",
              "null"
            ]
          },
          "last_attempt_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "delivered_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "request": {
            "type": "object",
            "required": [
              "url",
              "headers",
              "payload"
            ],
            "additionalProperties": false,
            "properties": {
              "url": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "headers": {
                "type": "object",
                "additionalProperties": {
                  "type": "string"
                }
              },
              "payload": {
                "type": "object",
                "description": "The JSON body that was sent (id, type, created_at, workspace_id, data)."
              }
            }
          },
          "attempt_log": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "attempt",
                "manual",
                "response_status",
                "response_body",
                "duration_ms",
                "error_code",
                "at"
              ],
              "additionalProperties": false,
              "properties": {
                "attempt": {
                  "type": "integer"
                },
                "manual": {
                  "type": "boolean"
                },
                "response_status": {
                  "type": [
                    "integer",
                    "null"
                  ]
                },
                "response_body": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "The first 2 KB of your receiver's response."
                },
                "duration_ms": {
                  "type": [
                    "integer",
                    "null"
                  ]
                },
                "error_code": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "at": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time"
                }
              }
            }
          }
        }
      },
      "WebhookDeliveryResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "additionalProperties": false,
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebhookDelivery"
          }
        }
      },
      "WebhookDeliveryDetailResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "additionalProperties": false,
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebhookDeliveryDetail"
          }
        }
      },
      "WebhookDeliveryList": {
        "type": "object",
        "required": [
          "data",
          "meta"
        ],
        "additionalProperties": false,
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookDelivery"
            }
          },
          "meta": {
            "type": "object",
            "required": [
              "next_cursor",
              "per_page"
            ],
            "additionalProperties": false,
            "properties": {
              "next_cursor": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "per_page": {
                "type": "integer"
              }
            }
          }
        }
      },
      "RetryFailedResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "additionalProperties": false,
        "properties": {
          "data": {
            "type": "object",
            "required": [
              "requeued",
              "remaining"
            ],
            "additionalProperties": false,
            "properties": {
              "requeued": {
                "type": "integer"
              },
              "remaining": {
                "type": "integer"
              }
            }
          }
        }
      }
    }
  }
}