{
  "openapi": "3.1.0",
  "info": {
    "title": "Ricky API",
    "version": "1.0.0",
    "description": "REST API for one Ricky organization: contacts, conversations, messages, templates and webhooks. Requests and responses are JSON with snake_case fields; IDs are UUIDs except template IDs; times are ISO 8601 in UTC.",
    "contact": {
      "name": "Ricky",
      "url": "https://getricky.ai/docs/api",
      "email": "ricardo@getricky.ai"
    }
  },
  "externalDocs": {
    "description": "Guides",
    "url": "https://getricky.ai/docs/api"
  },
  "servers": [
    {
      "url": "https://getricky.ai/api/v1"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Contacts",
      "description": "People in the CRM and their custom fields."
    },
    {
      "name": "Conversations",
      "description": "Threads with a contact on one channel: start, read, assign, close, reopen."
    },
    {
      "name": "Messages",
      "description": "Read and send messages, and follow each send."
    },
    {
      "name": "Catalogs",
      "description": "Channels, members, tags and templates to reference by ID."
    },
    {
      "name": "Webhooks",
      "description": "Subscriptions Ricky posts events to, and their deliveries."
    }
  ],
  "paths": {
    "/contacts": {
      "get": {
        "operationId": "listContacts",
        "tags": [
          "Contacts"
        ],
        "summary": "List contacts",
        "description": "Most recently updated first. Filters combine.\n\nScope: `contacts:read`.",
        "parameters": [
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "description": "Items per page.",
            "schema": {
              "default": 50,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "`next_cursor` from the previous page. Use it unchanged.",
            "schema": {
              "type": "string",
              "maxLength": 2048
            }
          },
          {
            "name": "query",
            "in": "query",
            "required": false,
            "description": "Text contained in the name, phone, email or company.",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          },
          {
            "name": "tag_id",
            "in": "query",
            "required": false,
            "description": "Only contacts with this tag.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "owner_user_id",
            "in": "query",
            "required": false,
            "description": "Only contacts this member owns.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "lifecycle_stage",
            "in": "query",
            "required": false,
            "description": "Only contacts at this stage.",
            "schema": {
              "type": "string",
              "enum": [
                "subscriber",
                "lead",
                "marketing_qualified",
                "sales_qualified",
                "opportunity",
                "customer",
                "evangelist",
                "other"
              ]
            }
          },
          {
            "name": "channel",
            "in": "query",
            "required": false,
            "description": "Only contacts reachable on this channel.",
            "schema": {
              "type": "string",
              "enum": [
                "whatsapp",
                "instagram",
                "messenger"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "next_cursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Contact"
                      }
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Pass as `cursor` for the next page; null on the last page."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid_input`: A parameter or body field is invalid; `param` names it when known.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: The `Authorization` header is missing, malformed, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: The key lacks the scope this operation requires.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: More than 120 requests this minute with this key; see `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Ricky failed. Retry a read. Before retrying a write, read the resource: the same `Idempotency-Key` answers `request_processing`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createContact",
        "tags": [
          "Contacts"
        ],
        "summary": "Create a contact",
        "description": "Creates a CRM contact. It does not message anyone; to reach a phone, start a conversation.\n\nScope: `contacts:write`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateContact"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Contact"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid_json`: The body is not valid JSON.\n\n`invalid_input`: A parameter or body field is invalid; `param` names it when known.\n\n`missing_idempotency_key`: A write without an `Idempotency-Key` header of 8 to 200 characters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: The `Authorization` header is missing, malformed, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: The key lacks the scope this operation requires.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_conflict`: The `Idempotency-Key` was used for a different request.\n\n`request_processing`: A request with this `Idempotency-Key` is still processing or ended in an unknown state.\n\n`conflict`: The resource changed in a way that prevents the operation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "`body_too_large`: The JSON body exceeds 64 KiB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "`unsupported_media_type`: The body must be `application/json`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: More than 120 requests this minute with this key; see `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Ricky failed. Retry a read. Before retrying a write, read the resource: the same `Idempotency-Key` answers `request_processing`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/contacts/{contact_id}": {
      "get": {
        "operationId": "getContact",
        "tags": [
          "Contacts"
        ],
        "summary": "Get a contact",
        "description": "One contact with its tags, identities and custom values.\n\nScope: `contacts:read`.",
        "parameters": [
          {
            "name": "contact_id",
            "in": "path",
            "required": true,
            "description": "Contact ID.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Contact"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid_input`: A parameter or body field is invalid; `param` names it when known.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: The `Authorization` header is missing, malformed, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: The key lacks the scope this operation requires.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: The resource does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: More than 120 requests this minute with this key; see `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Ricky failed. Retry a read. Before retrying a write, read the resource: the same `Idempotency-Key` answers `request_processing`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateContact",
        "tags": [
          "Contacts"
        ],
        "summary": "Update a contact",
        "description": "Changes only the fields in the body. `tag_ids` replaces the whole tag set; `custom_values` merges by key.\n\nScope: `contacts:write`.",
        "parameters": [
          {
            "name": "contact_id",
            "in": "path",
            "required": true,
            "description": "Contact ID.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateContact"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Contact"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid_json`: The body is not valid JSON.\n\n`invalid_input`: A parameter or body field is invalid; `param` names it when known.\n\n`missing_idempotency_key`: A write without an `Idempotency-Key` header of 8 to 200 characters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: The `Authorization` header is missing, malformed, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: The key lacks the scope this operation requires.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: The resource does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_conflict`: The `Idempotency-Key` was used for a different request.\n\n`request_processing`: A request with this `Idempotency-Key` is still processing or ended in an unknown state.\n\n`conflict`: The resource changed in a way that prevents the operation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "`body_too_large`: The JSON body exceeds 64 KiB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "`unsupported_media_type`: The body must be `application/json`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: More than 120 requests this minute with this key; see `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Ricky failed. Retry a read. Before retrying a write, read the resource: the same `Idempotency-Key` answers `request_processing`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/contact-fields": {
      "get": {
        "operationId": "listContactFields",
        "tags": [
          "Contacts"
        ],
        "summary": "List contact fields",
        "description": "The custom fields whose IDs key `custom_values`.\n\nScope: `contacts:read`.",
        "responses": {
          "200": {
            "description": "Success.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "next_cursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ContactField"
                      }
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Pass as `cursor` for the next page; null on the last page."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: The `Authorization` header is missing, malformed, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: The key lacks the scope this operation requires.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: More than 120 requests this minute with this key; see `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Ricky failed. Retry a read. Before retrying a write, read the resource: the same `Idempotency-Key` answers `request_processing`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/conversations": {
      "get": {
        "operationId": "listConversations",
        "tags": [
          "Conversations"
        ],
        "summary": "List conversations",
        "description": "Latest activity first.\n\nScope: `conversations:read`.",
        "parameters": [
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "description": "Items per page.",
            "schema": {
              "default": 50,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "`next_cursor` from the previous page. Use it unchanged.",
            "schema": {
              "type": "string",
              "maxLength": 2048
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "default": "all",
              "type": "string",
              "enum": [
                "all",
                "open",
                "closed"
              ]
            }
          },
          {
            "name": "assigned_user_id",
            "in": "query",
            "required": false,
            "description": "Only conversations assigned to this member.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "next_cursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Conversation"
                      }
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Pass as `cursor` for the next page; null on the last page."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid_input`: A parameter or body field is invalid; `param` names it when known.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: The `Authorization` header is missing, malformed, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: The key lacks the scope this operation requires.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: More than 120 requests this minute with this key; see `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Ricky failed. Retry a read. Before retrying a write, read the resource: the same `Idempotency-Key` answers `request_processing`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "startConversation",
        "tags": [
          "Conversations"
        ],
        "summary": "Start a conversation",
        "description": "Sends an approved WhatsApp template to a phone number. Ricky finds or creates the contact and reuses the number's conversation on that channel. Answers `202`: the send is queued; follow it with `GET /sends/{send_id}`.\n\nScope: `messages:send`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StartConversation"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Send"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid_json`: The body is not valid JSON.\n\n`invalid_input`: A parameter or body field is invalid; `param` names it when known.\n\n`missing_idempotency_key`: A write without an `Idempotency-Key` header of 8 to 200 characters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: The `Authorization` header is missing, malformed, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: The key lacks the scope this operation requires.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: The resource does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_conflict`: The `Idempotency-Key` was used for a different request.\n\n`request_processing`: A request with this `Idempotency-Key` is still processing or ended in an unknown state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "`body_too_large`: The JSON body exceeds 64 KiB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "`unsupported_media_type`: The body must be `application/json`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "`outside_messaging_window`: The channel only allows free-form text inside its reply window; send a template.\n\n`rule_violation`: The request breaks a business rule; `message` says which.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: More than 120 requests this minute with this key; see `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Ricky failed. Retry a read. Before retrying a write, read the resource: the same `Idempotency-Key` answers `request_processing`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "`upstream_error`: The messaging provider failed. Retry later.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable`: A dependency is temporarily unavailable. Retry later.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/conversations/{conversation_id}": {
      "get": {
        "operationId": "getConversation",
        "tags": [
          "Conversations"
        ],
        "summary": "Get a conversation",
        "description": "One conversation.\n\nScope: `conversations:read`.",
        "parameters": [
          {
            "name": "conversation_id",
            "in": "path",
            "required": true,
            "description": "Conversation ID.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Conversation"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid_input`: A parameter or body field is invalid; `param` names it when known.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: The `Authorization` header is missing, malformed, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: The key lacks the scope this operation requires.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: The resource does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: More than 120 requests this minute with this key; see `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Ricky failed. Retry a read. Before retrying a write, read the resource: the same `Idempotency-Key` answers `request_processing`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/conversations/{conversation_id}/assignment": {
      "patch": {
        "operationId": "assignConversation",
        "tags": [
          "Conversations"
        ],
        "summary": "Assign a conversation",
        "description": "Makes a member responsible for the conversation, or unassigns it.\n\nScope: `conversations:write`.",
        "parameters": [
          {
            "name": "conversation_id",
            "in": "path",
            "required": true,
            "description": "Conversation ID.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AssignConversation"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Conversation"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid_json`: The body is not valid JSON.\n\n`invalid_input`: A parameter or body field is invalid; `param` names it when known.\n\n`missing_idempotency_key`: A write without an `Idempotency-Key` header of 8 to 200 characters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: The `Authorization` header is missing, malformed, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: The key lacks the scope this operation requires.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: The resource does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_conflict`: The `Idempotency-Key` was used for a different request.\n\n`request_processing`: A request with this `Idempotency-Key` is still processing or ended in an unknown state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "`body_too_large`: The JSON body exceeds 64 KiB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "`unsupported_media_type`: The body must be `application/json`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "`rule_violation`: The request breaks a business rule; `message` says which.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: More than 120 requests this minute with this key; see `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Ricky failed. Retry a read. Before retrying a write, read the resource: the same `Idempotency-Key` answers `request_processing`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/conversations/{conversation_id}/close": {
      "post": {
        "operationId": "closeConversation",
        "tags": [
          "Conversations"
        ],
        "summary": "Close a conversation",
        "description": "Closing an already closed conversation changes nothing.\n\nScope: `conversations:write`.",
        "parameters": [
          {
            "name": "conversation_id",
            "in": "path",
            "required": true,
            "description": "Conversation ID.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CloseConversation"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Conversation"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid_json`: The body is not valid JSON.\n\n`invalid_input`: A parameter or body field is invalid; `param` names it when known.\n\n`missing_idempotency_key`: A write without an `Idempotency-Key` header of 8 to 200 characters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: The `Authorization` header is missing, malformed, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: The key lacks the scope this operation requires.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: The resource does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_conflict`: The `Idempotency-Key` was used for a different request.\n\n`request_processing`: A request with this `Idempotency-Key` is still processing or ended in an unknown state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "`body_too_large`: The JSON body exceeds 64 KiB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "`unsupported_media_type`: The body must be `application/json`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: More than 120 requests this minute with this key; see `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Ricky failed. Retry a read. Before retrying a write, read the resource: the same `Idempotency-Key` answers `request_processing`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/conversations/{conversation_id}/reopen": {
      "post": {
        "operationId": "reopenConversation",
        "tags": [
          "Conversations"
        ],
        "summary": "Reopen a conversation",
        "description": "Reopening an open conversation changes nothing. Send no body.\n\nScope: `conversations:write`.",
        "parameters": [
          {
            "name": "conversation_id",
            "in": "path",
            "required": true,
            "description": "Conversation ID.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Conversation"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`missing_idempotency_key`: A write without an `Idempotency-Key` header of 8 to 200 characters.\n\n`invalid_input`: A parameter or body field is invalid; `param` names it when known.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: The `Authorization` header is missing, malformed, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: The key lacks the scope this operation requires.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: The resource does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_conflict`: The `Idempotency-Key` was used for a different request.\n\n`request_processing`: A request with this `Idempotency-Key` is still processing or ended in an unknown state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: More than 120 requests this minute with this key; see `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Ricky failed. Retry a read. Before retrying a write, read the resource: the same `Idempotency-Key` answers `request_processing`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/conversations/{conversation_id}/messages": {
      "get": {
        "operationId": "listMessages",
        "tags": [
          "Messages"
        ],
        "summary": "List messages",
        "description": "Newest first.\n\nScope: `conversations:read`.",
        "parameters": [
          {
            "name": "conversation_id",
            "in": "path",
            "required": true,
            "description": "Conversation ID.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "`next_cursor` from the previous page. Use it unchanged.",
            "schema": {
              "type": "string",
              "maxLength": 2048
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "next_cursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Message"
                      }
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Pass as `cursor` for the next page; null on the last page."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid_input`: A parameter or body field is invalid; `param` names it when known.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: The `Authorization` header is missing, malformed, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: The key lacks the scope this operation requires.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: The resource does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: More than 120 requests this minute with this key; see `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Ricky failed. Retry a read. Before retrying a write, read the resource: the same `Idempotency-Key` answers `request_processing`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "sendMessage",
        "tags": [
          "Messages"
        ],
        "summary": "Send a message",
        "description": "Sends text, or a template on WhatsApp. Answers `202`: the send is queued; follow it with `GET /sends/{send_id}`. A `message.sent` webhook fires once the provider accepts it.\n\nScope: `messages:send`.",
        "parameters": [
          {
            "name": "conversation_id",
            "in": "path",
            "required": true,
            "description": "Conversation ID.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendMessage"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Send"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid_json`: The body is not valid JSON.\n\n`invalid_input`: A parameter or body field is invalid; `param` names it when known.\n\n`missing_idempotency_key`: A write without an `Idempotency-Key` header of 8 to 200 characters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: The `Authorization` header is missing, malformed, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: The key lacks the scope this operation requires.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: The resource does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_conflict`: The `Idempotency-Key` was used for a different request.\n\n`request_processing`: A request with this `Idempotency-Key` is still processing or ended in an unknown state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "`body_too_large`: The JSON body exceeds 64 KiB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "`unsupported_media_type`: The body must be `application/json`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "`outside_messaging_window`: The channel only allows free-form text inside its reply window; send a template.\n\n`rule_violation`: The request breaks a business rule; `message` says which.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: More than 120 requests this minute with this key; see `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Ricky failed. Retry a read. Before retrying a write, read the resource: the same `Idempotency-Key` answers `request_processing`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "`upstream_error`: The messaging provider failed. Retry later.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "`unavailable`: A dependency is temporarily unavailable. Retry later.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/sends/{send_id}": {
      "get": {
        "operationId": "getSend",
        "tags": [
          "Messages"
        ],
        "summary": "Get a send",
        "description": "Whether the provider accepted a message, and why not if it failed.\n\nScope: `messages:send`.",
        "parameters": [
          {
            "name": "send_id",
            "in": "path",
            "required": true,
            "description": "Send ID.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Send"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid_input`: A parameter or body field is invalid; `param` names it when known.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: The `Authorization` header is missing, malformed, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: The key lacks the scope this operation requires.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: The resource does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: More than 120 requests this minute with this key; see `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Ricky failed. Retry a read. Before retrying a write, read the resource: the same `Idempotency-Key` answers `request_processing`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/channels": {
      "get": {
        "operationId": "listChannels",
        "tags": [
          "Catalogs"
        ],
        "summary": "List channels",
        "description": "WhatsApp numbers, Instagram accounts and Facebook pages.\n\nScope: `conversations:read`.",
        "responses": {
          "200": {
            "description": "Success.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "next_cursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Channel"
                      }
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Pass as `cursor` for the next page; null on the last page."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: The `Authorization` header is missing, malformed, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: The key lacks the scope this operation requires.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: More than 120 requests this minute with this key; see `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Ricky failed. Retry a read. Before retrying a write, read the resource: the same `Idempotency-Key` answers `request_processing`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/members": {
      "get": {
        "operationId": "listMembers",
        "tags": [
          "Catalogs"
        ],
        "summary": "List members",
        "description": "People in the organization; their IDs assign conversations and own contacts.\n\nScope: `members:read`.",
        "responses": {
          "200": {
            "description": "Success.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "next_cursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Member"
                      }
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Pass as `cursor` for the next page; null on the last page."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: The `Authorization` header is missing, malformed, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: The key lacks the scope this operation requires.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: More than 120 requests this minute with this key; see `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Ricky failed. Retry a read. Before retrying a write, read the resource: the same `Idempotency-Key` answers `request_processing`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/tags": {
      "get": {
        "operationId": "listTags",
        "tags": [
          "Catalogs"
        ],
        "summary": "List tags",
        "description": "Contact tags.\n\nScope: `tags:read`.",
        "responses": {
          "200": {
            "description": "Success.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "next_cursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Tag"
                      }
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Pass as `cursor` for the next page; null on the last page."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: The `Authorization` header is missing, malformed, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: The key lacks the scope this operation requires.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: More than 120 requests this minute with this key; see `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Ricky failed. Retry a read. Before retrying a write, read the resource: the same `Idempotency-Key` answers `request_processing`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/templates": {
      "get": {
        "operationId": "listTemplates",
        "tags": [
          "Catalogs"
        ],
        "summary": "List templates",
        "description": "WhatsApp templates of every connected business account, read live from Meta.\n\nScope: `templates:read`.",
        "responses": {
          "200": {
            "description": "Success.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "next_cursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Template"
                      }
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Pass as `cursor` for the next page; null on the last page."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: The `Authorization` header is missing, malformed, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: The key lacks the scope this operation requires.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: More than 120 requests this minute with this key; see `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Ricky failed. Retry a read. Before retrying a write, read the resource: the same `Idempotency-Key` answers `request_processing`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "`upstream_error`: The messaging provider failed. Retry later.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks": {
      "get": {
        "operationId": "listWebhooks",
        "tags": [
          "Webhooks"
        ],
        "summary": "List webhooks",
        "description": "Newest first, at most 100.\n\nScope: `webhooks:manage`.",
        "responses": {
          "200": {
            "description": "Success.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "next_cursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Webhook"
                      }
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Pass as `cursor` for the next page; null on the last page."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: The `Authorization` header is missing, malformed, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: The key lacks the scope this operation requires.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: More than 120 requests this minute with this key; see `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Ricky failed. Retry a read. Before retrying a write, read the resource: the same `Idempotency-Key` answers `request_processing`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createWebhook",
        "tags": [
          "Webhooks"
        ],
        "summary": "Create a webhook",
        "description": "The response carries `signing_secret`, the only time Ricky shows it.\n\nScope: `webhooks:manage`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateWebhook"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/CreatedWebhook"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid_json`: The body is not valid JSON.\n\n`invalid_input`: A parameter or body field is invalid; `param` names it when known.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: The `Authorization` header is missing, malformed, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: The key lacks the scope this operation requires.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "`body_too_large`: The JSON body exceeds 64 KiB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "`unsupported_media_type`: The body must be `application/json`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: More than 120 requests this minute with this key; see `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Ricky failed. Retry a read. Before retrying a write, read the resource: the same `Idempotency-Key` answers `request_processing`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/{webhook_id}": {
      "delete": {
        "operationId": "disableWebhook",
        "tags": [
          "Webhooks"
        ],
        "summary": "Disable a webhook",
        "description": "Stops new and pending deliveries. Disabling twice answers `404`.\n\nScope: `webhooks:manage`.",
        "parameters": [
          {
            "name": "webhook_id",
            "in": "path",
            "required": true,
            "description": "Webhook ID.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Webhook"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid_input`: A parameter or body field is invalid; `param` names it when known.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: The `Authorization` header is missing, malformed, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: The key lacks the scope this operation requires.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: The resource does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: More than 120 requests this minute with this key; see `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Ricky failed. Retry a read. Before retrying a write, read the resource: the same `Idempotency-Key` answers `request_processing`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/{webhook_id}/deliveries": {
      "get": {
        "operationId": "listWebhookDeliveries",
        "tags": [
          "Webhooks"
        ],
        "summary": "List deliveries",
        "description": "The 100 most recent deliveries of a webhook.\n\nScope: `webhooks:manage`.",
        "parameters": [
          {
            "name": "webhook_id",
            "in": "path",
            "required": true,
            "description": "Webhook ID.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "next_cursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WebhookDelivery"
                      }
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Pass as `cursor` for the next page; null on the last page."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid_input`: A parameter or body field is invalid; `param` names it when known.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: The `Authorization` header is missing, malformed, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: The key lacks the scope this operation requires.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: The resource does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: More than 120 requests this minute with this key; see `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Ricky failed. Retry a read. Before retrying a write, read the resource: the same `Idempotency-Key` answers `request_processing`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/{webhook_id}/deliveries/{delivery_id}/retry": {
      "post": {
        "operationId": "retryWebhookDelivery",
        "tags": [
          "Webhooks"
        ],
        "summary": "Retry a delivery",
        "description": "Queues a failed delivery again with a fresh attempt budget. Ricky sends it within 15 minutes.\n\nScope: `webhooks:manage`.",
        "parameters": [
          {
            "name": "webhook_id",
            "in": "path",
            "required": true,
            "description": "Webhook ID.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "delivery_id",
            "in": "path",
            "required": true,
            "description": "Delivery ID.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/WebhookDelivery"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid_input`: A parameter or body field is invalid; `param` names it when known.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: The `Authorization` header is missing, malformed, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: The key lacks the scope this operation requires.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: The resource does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: More than 120 requests this minute with this key; see `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Ricky failed. Retry a read. Before retrying a write, read the resource: the same `Idempotency-Key` answers `request_processing`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "webhooks": {
    "message.received": {
      "post": {
        "operationId": "webhook_message_received",
        "summary": "message.received",
        "description": "A contact sent a message.\n\nRicky signs every delivery: `X-Ricky-Signature: v1=<hex>` is the HMAC-SHA256 of `<X-Ricky-Timestamp>.<raw body>` keyed with the webhook `signing_secret`. Answer any 2xx within 10 seconds; Ricky makes up to ten attempts with growing waits and may deliver an event twice, so deduplicate by `id`.",
        "parameters": [
          {
            "name": "X-Ricky-Delivery-Id",
            "in": "header",
            "required": true,
            "description": "Delivery ID; equals the body `id`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Ricky-Timestamp",
            "in": "header",
            "required": true,
            "description": "Unix time of the attempt.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Ricky-Signature",
            "in": "header",
            "required": true,
            "description": "`v1=` and the hex HMAC-SHA256.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Received."
          }
        }
      }
    },
    "message.sent": {
      "post": {
        "operationId": "webhook_message_sent",
        "summary": "message.sent",
        "description": "The provider accepted a message from the organization.\n\nRicky signs every delivery: `X-Ricky-Signature: v1=<hex>` is the HMAC-SHA256 of `<X-Ricky-Timestamp>.<raw body>` keyed with the webhook `signing_secret`. Answer any 2xx within 10 seconds; Ricky makes up to ten attempts with growing waits and may deliver an event twice, so deduplicate by `id`.",
        "parameters": [
          {
            "name": "X-Ricky-Delivery-Id",
            "in": "header",
            "required": true,
            "description": "Delivery ID; equals the body `id`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Ricky-Timestamp",
            "in": "header",
            "required": true,
            "description": "Unix time of the attempt.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Ricky-Signature",
            "in": "header",
            "required": true,
            "description": "`v1=` and the hex HMAC-SHA256.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Received."
          }
        }
      }
    },
    "conversation.opened": {
      "post": {
        "operationId": "webhook_conversation_opened",
        "summary": "conversation.opened",
        "description": "A conversation was created or reopened.\n\nRicky signs every delivery: `X-Ricky-Signature: v1=<hex>` is the HMAC-SHA256 of `<X-Ricky-Timestamp>.<raw body>` keyed with the webhook `signing_secret`. Answer any 2xx within 10 seconds; Ricky makes up to ten attempts with growing waits and may deliver an event twice, so deduplicate by `id`.",
        "parameters": [
          {
            "name": "X-Ricky-Delivery-Id",
            "in": "header",
            "required": true,
            "description": "Delivery ID; equals the body `id`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Ricky-Timestamp",
            "in": "header",
            "required": true,
            "description": "Unix time of the attempt.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Ricky-Signature",
            "in": "header",
            "required": true,
            "description": "`v1=` and the hex HMAC-SHA256.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Received."
          }
        }
      }
    },
    "conversation.closed": {
      "post": {
        "operationId": "webhook_conversation_closed",
        "summary": "conversation.closed",
        "description": "A conversation was closed.\n\nRicky signs every delivery: `X-Ricky-Signature: v1=<hex>` is the HMAC-SHA256 of `<X-Ricky-Timestamp>.<raw body>` keyed with the webhook `signing_secret`. Answer any 2xx within 10 seconds; Ricky makes up to ten attempts with growing waits and may deliver an event twice, so deduplicate by `id`.",
        "parameters": [
          {
            "name": "X-Ricky-Delivery-Id",
            "in": "header",
            "required": true,
            "description": "Delivery ID; equals the body `id`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Ricky-Timestamp",
            "in": "header",
            "required": true,
            "description": "Unix time of the attempt.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Ricky-Signature",
            "in": "header",
            "required": true,
            "description": "`v1=` and the hex HMAC-SHA256.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Received."
          }
        }
      }
    },
    "conversation.assignment_changed": {
      "post": {
        "operationId": "webhook_conversation_assignment_changed",
        "summary": "conversation.assignment_changed",
        "description": "A conversation was assigned, reassigned or unassigned.\n\nRicky signs every delivery: `X-Ricky-Signature: v1=<hex>` is the HMAC-SHA256 of `<X-Ricky-Timestamp>.<raw body>` keyed with the webhook `signing_secret`. Answer any 2xx within 10 seconds; Ricky makes up to ten attempts with growing waits and may deliver an event twice, so deduplicate by `id`.",
        "parameters": [
          {
            "name": "X-Ricky-Delivery-Id",
            "in": "header",
            "required": true,
            "description": "Delivery ID; equals the body `id`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Ricky-Timestamp",
            "in": "header",
            "required": true,
            "description": "Unix time of the attempt.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Ricky-Signature",
            "in": "header",
            "required": true,
            "description": "`v1=` and the hex HMAC-SHA256.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Received."
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "invalid_input",
                  "invalid_json",
                  "missing_idempotency_key",
                  "unauthorized",
                  "insufficient_scope",
                  "forbidden",
                  "not_found",
                  "conflict",
                  "idempotency_conflict",
                  "request_processing",
                  "body_too_large",
                  "unsupported_media_type",
                  "outside_messaging_window",
                  "rule_violation",
                  "rate_limited",
                  "internal_error",
                  "upstream_error",
                  "unavailable"
                ],
                "description": "Stable, machine-readable error code."
              },
              "message": {
                "type": "string",
                "description": "Human-readable explanation. Do not parse it."
              },
              "param": {
                "description": "The request field or parameter that caused it.",
                "type": "string"
              },
              "request_id": {
                "type": "string",
                "description": "Quote it to support. Also in the `X-Request-Id` header."
              }
            },
            "required": [
              "code",
              "message",
              "request_id"
            ]
          }
        },
        "required": [
          "error"
        ],
        "description": "Every non-2xx response."
      },
      "Tag": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Tag ID.",
            "examples": [
              "5c6d7e8f-9a0b-4c1d-8e2f-3a4b5c6d7e8f"
            ]
          },
          "name": {
            "type": "string",
            "description": "Display name.",
            "examples": [
              "Cliente frecuente"
            ]
          },
          "color": {
            "type": "string",
            "enum": [
              "gray",
              "red",
              "orange",
              "amber",
              "green",
              "teal",
              "blue",
              "indigo",
              "purple",
              "pink"
            ],
            "description": "Display color."
          }
        },
        "required": [
          "id",
          "name",
          "color"
        ],
        "description": "A label applied to contacts."
      },
      "ContactIdentity": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Identity ID.",
            "examples": [
              "4b5c6d7e-8f9a-4b0c-9d1e-2f3a4b5c6d7e"
            ]
          },
          "channel_type": {
            "type": "string",
            "enum": [
              "whatsapp",
              "instagram",
              "messenger"
            ],
            "description": "Channel this identity belongs to."
          },
          "external_id": {
            "type": "string",
            "description": "Address on that channel: phone digits for WhatsApp, account ID otherwise.",
            "examples": [
              "50760001234"
            ]
          },
          "display_name": {
            "description": "Name the channel reports.",
            "examples": [
              "Ana Pérez"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "username": {
            "description": "Handle on the channel, when it has one.",
            "examples": [
              null
            ],
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "channel_type",
          "external_id",
          "display_name",
          "username"
        ],
        "description": "How a contact is reached on one channel."
      },
      "Contact": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Contact ID.",
            "examples": [
              "3f6c2b1e-8d4a-4b7e-9a51-2c7d8e9f0a1b"
            ]
          },
          "first_name": {
            "description": "First name.",
            "examples": [
              "Ana"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "last_name": {
            "description": "Last name.",
            "examples": [
              "Pérez"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "primary_email": {
            "description": "Email, lowercased.",
            "examples": [
              "ana.perez@example.com"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "primary_phone": {
            "description": "Phone in E.164.",
            "examples": [
              "+50760001234"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "company": {
            "description": "Company.",
            "examples": [
              "Casa Nativa"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "job_title": {
            "description": "Job title.",
            "examples": [
              "Gerente de compras"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "birthday": {
            "description": "Birthday as `YYYY-MM-DD`.",
            "examples": [
              "1990-08-13"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "city": {
            "description": "City.",
            "examples": [
              "Panamá"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "region": {
            "description": "State, province or region.",
            "examples": [
              "Panamá"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "country": {
            "description": "Country.",
            "examples": [
              "Panamá"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "street_address": {
            "description": "Street address.",
            "examples": [
              "Calle 50, Edificio Global, piso 3"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "postal_code": {
            "description": "Postal code.",
            "examples": [
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "website_url": {
            "description": "Website URL.",
            "examples": [
              "https://example.com"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "linkedin_url": {
            "description": "LinkedIn profile URL.",
            "examples": [
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "source": {
            "description": "Where the contact came from.",
            "examples": [
              "WhatsApp"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "notes": {
            "description": "Free-form notes.",
            "examples": [
              "Prefiere que la contacten por la tarde."
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "owner_user_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid",
                "description": "Member who owns the contact.",
                "examples": [
                  "2d4f6a8c-1b3d-4e5f-8a7b-9c0d1e2f3a4b"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "lead_status": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "new",
                  "open",
                  "in_progress",
                  "attempted",
                  "connected",
                  "unqualified",
                  "bad_timing"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Sales lead status."
          },
          "lifecycle_stage": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "subscriber",
                  "lead",
                  "marketing_qualified",
                  "sales_qualified",
                  "opportunity",
                  "customer",
                  "evangelist",
                  "other"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Lifecycle stage.",
            "examples": [
              "customer"
            ]
          },
          "custom_values": {
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "number"
                },
                {
                  "type": "boolean"
                },
                {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                {
                  "type": "null"
                }
              ]
            },
            "description": "Custom field values keyed by contact field ID. See `GET /contact-fields`.",
            "examples": [
              {
                "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d": "Albrook Mall"
              }
            ]
          },
          "identities": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ContactIdentity"
            },
            "description": "Channel identities."
          },
          "tags": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Tag"
            },
            "description": "Tags applied to the contact."
          },
          "last_activity_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
              },
              {
                "type": "null"
              }
            ],
            "description": "Latest message in any of its conversations.",
            "examples": [
              "2026-10-14T15:30:00.000Z"
            ]
          },
          "last_activity_preview": {
            "description": "Text of that latest message.",
            "examples": [
              "¿Ya están mis lentes?"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "last_conversation_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid",
                "description": "Conversation of that latest message.",
                "examples": [
                  "9b2e4c61-7a3f-4d18-b5c2-6e0f1a2b3c4d"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
            "description": "Last change to the contact.",
            "examples": [
              "2026-10-14T15:30:00.000Z"
            ]
          }
        },
        "required": [
          "id",
          "first_name",
          "last_name",
          "primary_email",
          "primary_phone",
          "company",
          "job_title",
          "birthday",
          "city",
          "region",
          "country",
          "street_address",
          "postal_code",
          "website_url",
          "linkedin_url",
          "source",
          "notes",
          "owner_user_id",
          "lead_status",
          "lifecycle_stage",
          "custom_values",
          "identities",
          "tags",
          "last_activity_at",
          "last_activity_preview",
          "last_conversation_id",
          "updated_at"
        ],
        "description": "A person in the CRM."
      },
      "ContactField": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Field ID; the key in `custom_values`.",
            "examples": [
              "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d"
            ]
          },
          "name": {
            "type": "string",
            "description": "Display name.",
            "examples": [
              "Sucursal"
            ]
          },
          "type": {
            "type": "string",
            "enum": [
              "text",
              "long_text",
              "number",
              "boolean",
              "date",
              "select",
              "multi_select"
            ],
            "description": "Value type: `number` takes a number, `boolean` a boolean, `date` `YYYY-MM-DD`, `select` one option, `multi_select` an array of options, the rest a string."
          },
          "options": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Allowed values for `select` and `multi_select`.",
            "examples": [
              [
                "Albrook Mall",
                "Multiplaza"
              ]
            ]
          }
        },
        "required": [
          "id",
          "name",
          "type",
          "options"
        ],
        "description": "A custom contact field defined by the organization."
      },
      "Channel": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Channel ID.",
            "examples": [
              "8f3c2a5e-6b1d-4c7a-9e2f-1a2b3c4d5e6f"
            ]
          },
          "type": {
            "type": "string",
            "enum": [
              "whatsapp",
              "instagram",
              "messenger"
            ],
            "description": "Messaging channel."
          },
          "name": {
            "type": "string",
            "description": "Name shown in Ricky.",
            "examples": [
              "Casa Nativa"
            ]
          },
          "address": {
            "description": "Phone in E.164 for WhatsApp, account or page name otherwise.",
            "examples": [
              "+50760000000"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "whatsapp_business_account_id": {
            "description": "WhatsApp Business Account that owns the number; templates must belong to it.",
            "examples": [
              "102030405060708"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "connected_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
              },
              {
                "type": "null"
              }
            ],
            "description": "When it was connected.",
            "examples": [
              "2026-10-14T15:30:00.000Z"
            ]
          }
        },
        "required": [
          "id",
          "type",
          "name",
          "address",
          "whatsapp_business_account_id",
          "connected_at"
        ],
        "description": "A connected messaging channel."
      },
      "Conversation": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Conversation ID.",
            "examples": [
              "9b2e4c61-7a3f-4d18-b5c2-6e0f1a2b3c4d"
            ]
          },
          "channel": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "description": "Channel ID.",
                "examples": [
                  "8f3c2a5e-6b1d-4c7a-9e2f-1a2b3c4d5e6f"
                ]
              },
              "type": {
                "type": "string",
                "enum": [
                  "whatsapp",
                  "instagram",
                  "messenger"
                ]
              }
            },
            "required": [
              "id",
              "type"
            ]
          },
          "contact": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "id": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "description": "Contact ID.",
                        "examples": [
                          "3f6c2b1e-8d4a-4b7e-9a51-2c7d8e9f0a1b"
                        ]
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "display_name": {
                    "description": "Name on the channel.",
                    "examples": [
                      "Ana Pérez"
                    ],
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "external_id": {
                    "type": "string",
                    "description": "Address on the channel.",
                    "examples": [
                      "50760001234"
                    ]
                  },
                  "username": {
                    "description": "Handle, when the channel has one.",
                    "examples": [
                      null
                    ],
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                },
                "required": [
                  "id",
                  "display_name",
                  "external_id",
                  "username"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "open",
              "closed"
            ]
          },
          "close_category": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "resolved",
                  "sale",
                  "no_response",
                  "spam",
                  "other"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Why it was closed; null while open or when closed without one."
          },
          "assigned_user_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid",
                "description": "Member responsible for it.",
                "examples": [
                  "2d4f6a8c-1b3d-4e5f-8a7b-9c0d1e2f3a4b"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "agent_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid",
                "description": "AI agent answering it.",
                "examples": [
                  "7e8f9a0b-1c2d-4e3f-a4b5-c6d7e8f9a0b1"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
            "description": "When it was created.",
            "examples": [
              "2026-10-14T15:30:00.000Z"
            ]
          },
          "opened_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
            "description": "Start of the current open span.",
            "examples": [
              "2026-10-14T15:30:00.000Z"
            ]
          },
          "closed_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
              },
              {
                "type": "null"
              }
            ],
            "description": "When it was closed; null while open.",
            "examples": [
              "2026-10-14T15:30:00.000Z"
            ]
          },
          "last_activity_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
              },
              {
                "type": "null"
              }
            ],
            "description": "Latest message.",
            "examples": [
              "2026-10-14T15:30:00.000Z"
            ]
          },
          "last_activity_preview": {
            "description": "Text of the latest message.",
            "examples": [
              "¿Ya están mis lentes?"
            ],
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "channel",
          "contact",
          "status",
          "close_category",
          "assigned_user_id",
          "agent_id",
          "created_at",
          "opened_at",
          "closed_at",
          "last_activity_at",
          "last_activity_preview"
        ],
        "description": "One contact talking to the organization on one channel."
      },
      "Message": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Message ID.",
            "examples": [
              "c41d7e2a-5b6f-4a89-8c3d-0e1f2a3b4c5d"
            ]
          },
          "conversation_id": {
            "type": "string",
            "format": "uuid",
            "description": "Conversation ID.",
            "examples": [
              "9b2e4c61-7a3f-4d18-b5c2-6e0f1a2b3c4d"
            ]
          },
          "direction": {
            "type": "string",
            "enum": [
              "inbound",
              "outbound"
            ]
          },
          "type": {
            "type": "string",
            "description": "Message type: `text`, `image`, `audio`, `video`, `document`, `template`, …",
            "examples": [
              "text"
            ]
          },
          "text": {
            "description": "Text, caption or rendered template body.",
            "examples": [
              "¿Ya están mis lentes?"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "sender": {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "contact",
                  "member",
                  "agent",
                  "automation",
                  "channel_app"
                ],
                "description": "`contact`; a `member` in Ricky; an AI `agent`; an `automation`; or `channel_app`, sent from the channel's own app outside Ricky."
              },
              "name": {
                "description": "Member, agent or workflow name; null for the contact and `channel_app`.",
                "examples": [
                  null
                ],
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "type",
              "name"
            ]
          },
          "status": {
            "type": "string",
            "description": "Provider delivery status: `sent`, `delivered`, `read`, `failed`, …",
            "examples": [
              "read"
            ]
          },
          "media": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "kind": {
                    "type": "string",
                    "description": "`image`, `audio`, `video`, `document` or `sticker`.",
                    "examples": [
                      "image"
                    ]
                  },
                  "mime_type": {
                    "description": "MIME type.",
                    "examples": [
                      "image/jpeg"
                    ],
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "filename": {
                    "description": "File name, for documents.",
                    "examples": [
                      null
                    ],
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "byte_size": {
                    "anyOf": [
                      {
                        "type": "integer",
                        "minimum": -9007199254740991,
                        "maximum": 9007199254740991
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "transcript": {
                    "description": "Transcript of a voice note.",
                    "examples": [
                      null
                    ],
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "url": {
                    "description": "Signed download URL, valid for one hour; null until downloaded.",
                    "examples": [
                      null
                    ],
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                },
                "required": [
                  "kind",
                  "mime_type",
                  "filename",
                  "byte_size",
                  "transcript",
                  "url"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "provider_message_id": {
            "description": "Message ID at the provider.",
            "examples": [
              "wamid.HBgLNTA3NjAwMDEyMzQV"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
            "description": "When Ricky recorded it.",
            "examples": [
              "2026-10-14T15:30:00.000Z"
            ]
          },
          "sent_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
              },
              {
                "type": "null"
              }
            ],
            "description": "When the provider accepted it.",
            "examples": [
              "2026-10-14T15:30:00.000Z"
            ]
          },
          "delivered_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
              },
              {
                "type": "null"
              }
            ],
            "description": "When it reached the device.",
            "examples": [
              "2026-10-14T15:30:00.000Z"
            ]
          },
          "read_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
              },
              {
                "type": "null"
              }
            ],
            "description": "When the recipient read it.",
            "examples": [
              "2026-10-14T15:30:00.000Z"
            ]
          },
          "failed_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
              },
              {
                "type": "null"
              }
            ],
            "description": "When delivery failed.",
            "examples": [
              "2026-10-14T15:30:00.000Z"
            ]
          },
          "edited_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
              },
              {
                "type": "null"
              }
            ],
            "description": "When the sender edited it.",
            "examples": [
              "2026-10-14T15:30:00.000Z"
            ]
          },
          "deleted_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
              },
              {
                "type": "null"
              }
            ],
            "description": "When the sender deleted it.",
            "examples": [
              "2026-10-14T15:30:00.000Z"
            ]
          }
        },
        "required": [
          "id",
          "conversation_id",
          "direction",
          "type",
          "text",
          "sender",
          "status",
          "media",
          "provider_message_id",
          "created_at",
          "sent_at",
          "delivered_at",
          "read_at",
          "failed_at",
          "edited_at",
          "deleted_at"
        ],
        "description": "One message in a conversation."
      },
      "Send": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Send ID. Poll `GET /sends/{send_id}` with it.",
            "examples": [
              "6a7b8c9d-0e1f-4a2b-9c3d-4e5f6a7b8c9d"
            ]
          },
          "conversation_id": {
            "type": "string",
            "format": "uuid",
            "description": "Conversation the message goes to.",
            "examples": [
              "9b2e4c61-7a3f-4d18-b5c2-6e0f1a2b3c4d"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "sent",
              "failed"
            ],
            "description": "`sent` once the provider accepted the message; `failed` for good, with the reason; `queued` otherwise, while Ricky retries."
          },
          "message_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid",
                "description": "The message in the conversation, once the provider accepted it; null before.",
                "examples": [
                  "c41d7e2a-5b6f-4a89-8c3d-0e1f2a3b4c5d"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "failure_reason": {
            "description": "Why it failed; null unless `failed`.",
            "examples": [
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
            "description": "When Ricky accepted it.",
            "examples": [
              "2026-10-14T15:30:00.000Z"
            ]
          }
        },
        "required": [
          "id",
          "conversation_id",
          "status",
          "message_id",
          "failure_reason",
          "created_at"
        ],
        "description": "An outbound message Ricky accepted and is delivering.",
        "examples": [
          {
            "id": "6a7b8c9d-0e1f-4a2b-9c3d-4e5f6a7b8c9d",
            "conversation_id": "9b2e4c61-7a3f-4d18-b5c2-6e0f1a2b3c4d",
            "status": "sent",
            "message_id": "c41d7e2a-5b6f-4a89-8c3d-0e1f2a3b4c5d",
            "failure_reason": null,
            "created_at": "2026-10-14T15:30:00.000Z"
          }
        ]
      },
      "Member": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "User ID.",
            "examples": [
              "2d4f6a8c-1b3d-4e5f-8a7b-9c0d1e2f3a4b"
            ]
          },
          "name": {
            "description": "Full name.",
            "examples": [
              "Valeria Ruiz"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "email": {
            "type": "string",
            "description": "Email.",
            "examples": [
              "valeria@example.com"
            ]
          },
          "role": {
            "type": "string",
            "enum": [
              "owner",
              "admin",
              "member"
            ]
          }
        },
        "required": [
          "id",
          "name",
          "email",
          "role"
        ],
        "description": "A person in the organization."
      },
      "Template": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Template ID at Meta.",
            "examples": [
              "1234567890123456"
            ]
          },
          "name": {
            "type": "string",
            "description": "Template name.",
            "examples": [
              "pedido_listo"
            ]
          },
          "language": {
            "type": "string",
            "description": "Language code, for example `es` or `en_US`.",
            "examples": [
              "es"
            ]
          },
          "category": {
            "type": "string",
            "description": "`MARKETING`, `UTILITY` or `AUTHENTICATION`.",
            "examples": [
              "UTILITY"
            ]
          },
          "status": {
            "type": "string",
            "description": "Meta review status. Only `APPROVED` templates can be sent.",
            "examples": [
              "APPROVED"
            ]
          },
          "whatsapp_business_account_id": {
            "type": "string",
            "description": "Account that owns it.",
            "examples": [
              "102030405060708"
            ]
          },
          "parameter_format": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "POSITIONAL",
                  "NAMED"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "How variables are named: `{{1}}` or `{{name}}`."
          },
          "components": {
            "type": "array",
            "items": {
              "type": "object",
              "propertyNames": {
                "type": "string"
              },
              "additionalProperties": {}
            },
            "description": "Header, body, footer and buttons, in the WhatsApp Cloud API format.",
            "examples": [
              [
                {
                  "type": "BODY",
                  "text": "Hola {{1}}, tu pedido {{2}} está listo para retirar."
                }
              ]
            ]
          }
        },
        "required": [
          "id",
          "name",
          "language",
          "category",
          "status",
          "whatsapp_business_account_id",
          "parameter_format",
          "components"
        ],
        "description": "A WhatsApp message template."
      },
      "Webhook": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Webhook ID.",
            "examples": [
              "e1f2a3b4-c5d6-4e7f-8a9b-0c1d2e3f4a5b"
            ]
          },
          "url": {
            "type": "string",
            "description": "HTTPS endpoint Ricky posts to.",
            "examples": [
              "https://example.com/ricky/webhooks"
            ]
          },
          "event_types": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "message.received",
                "message.sent",
                "conversation.opened",
                "conversation.closed",
                "conversation.assignment_changed"
              ]
            }
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "disabled"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
            "description": "When it was created.",
            "examples": [
              "2026-10-14T15:30:00.000Z"
            ]
          },
          "disabled_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
              },
              {
                "type": "null"
              }
            ],
            "description": "When it was disabled.",
            "examples": [
              "2026-10-14T15:30:00.000Z"
            ]
          }
        },
        "required": [
          "id",
          "url",
          "event_types",
          "status",
          "created_at",
          "disabled_at"
        ],
        "description": "A webhook subscription."
      },
      "CreatedWebhook": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Webhook ID.",
            "examples": [
              "e1f2a3b4-c5d6-4e7f-8a9b-0c1d2e3f4a5b"
            ]
          },
          "url": {
            "type": "string",
            "description": "HTTPS endpoint Ricky posts to.",
            "examples": [
              "https://example.com/ricky/webhooks"
            ]
          },
          "event_types": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "message.received",
                "message.sent",
                "conversation.opened",
                "conversation.closed",
                "conversation.assignment_changed"
              ]
            }
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "disabled"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
            "description": "When it was created.",
            "examples": [
              "2026-10-14T15:30:00.000Z"
            ]
          },
          "disabled_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
              },
              {
                "type": "null"
              }
            ],
            "description": "When it was disabled.",
            "examples": [
              "2026-10-14T15:30:00.000Z"
            ]
          },
          "signing_secret": {
            "type": "string",
            "description": "HMAC key for `X-Ricky-Signature`. Returned only here, once.",
            "examples": [
              "whsec_7Yb2kQ9…"
            ]
          }
        },
        "required": [
          "id",
          "url",
          "event_types",
          "status",
          "created_at",
          "disabled_at",
          "signing_secret"
        ],
        "description": "A new webhook subscription with its signing secret."
      },
      "WebhookDelivery": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Delivery ID; equals the event `id` and `X-Ricky-Delivery-Id`.",
            "examples": [
              "b5c6d7e8-f9a0-4b1c-9d2e-3f4a5b6c7d8e"
            ]
          },
          "event_type": {
            "type": "string",
            "enum": [
              "message.received",
              "message.sent",
              "conversation.opened",
              "conversation.closed",
              "conversation.assignment_changed"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "processing",
              "delivered",
              "failed"
            ]
          },
          "attempts": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991,
            "description": "Delivery attempts so far; Ricky makes at most ten."
          },
          "last_response_status": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              {
                "type": "null"
              }
            ],
            "description": "HTTP status of the last attempt.",
            "examples": [
              200
            ]
          },
          "last_error": {
            "description": "Why the last attempt failed.",
            "examples": [
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
            "description": "When the event happened.",
            "examples": [
              "2026-10-14T15:30:00.000Z"
            ]
          },
          "next_attempt_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
            "description": "When Ricky tries next, while pending.",
            "examples": [
              "2026-10-14T15:30:00.000Z"
            ]
          },
          "delivered_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
              },
              {
                "type": "null"
              }
            ],
            "description": "When the endpoint answered 2xx.",
            "examples": [
              "2026-10-14T15:30:00.000Z"
            ]
          }
        },
        "required": [
          "id",
          "event_type",
          "status",
          "attempts",
          "last_response_status",
          "last_error",
          "created_at",
          "next_attempt_at",
          "delivered_at"
        ],
        "description": "One webhook delivery."
      },
      "WebhookEvent": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Delivery ID. Deduplicate by it.",
            "examples": [
              "b5c6d7e8-f9a0-4b1c-9d2e-3f4a5b6c7d8e"
            ]
          },
          "type": {
            "type": "string",
            "enum": [
              "message.received",
              "message.sent",
              "conversation.opened",
              "conversation.closed",
              "conversation.assignment_changed"
            ]
          },
          "occurred_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
            "description": "When it happened.",
            "examples": [
              "2026-10-14T15:30:00.000Z"
            ]
          },
          "organization_id": {
            "type": "string",
            "format": "uuid",
            "description": "Organization.",
            "examples": [
              "d9e0f1a2-b3c4-4d5e-8f6a-7b8c9d0e1f2a"
            ]
          },
          "data": {
            "type": "object",
            "properties": {
              "conversation_id": {
                "type": "string",
                "format": "uuid",
                "description": "Conversation.",
                "examples": [
                  "9b2e4c61-7a3f-4d18-b5c2-6e0f1a2b3c4d"
                ]
              },
              "message_id": {
                "type": "string",
                "format": "uuid",
                "description": "Message, for `message.*` events.",
                "examples": [
                  "c41d7e2a-5b6f-4a89-8c3d-0e1f2a3b4c5d"
                ]
              }
            },
            "required": [
              "conversation_id"
            ]
          }
        },
        "required": [
          "id",
          "type",
          "occurred_at",
          "organization_id",
          "data"
        ],
        "description": "The JSON body Ricky posts to a webhook endpoint."
      },
      "CreateContact": {
        "type": "object",
        "properties": {
          "first_name": {
            "description": "First name.",
            "anyOf": [
              {
                "type": "string",
                "maxLength": 5000
              },
              {
                "type": "null"
              }
            ]
          },
          "last_name": {
            "description": "Last name.",
            "anyOf": [
              {
                "type": "string",
                "maxLength": 5000
              },
              {
                "type": "null"
              }
            ]
          },
          "primary_email": {
            "description": "Email.",
            "anyOf": [
              {
                "type": "string",
                "format": "email",
                "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
              },
              {
                "type": "null"
              }
            ]
          },
          "primary_phone": {
            "description": "Phone with country code, for example `+507 6000-1234`.",
            "anyOf": [
              {
                "type": "string",
                "maxLength": 5000
              },
              {
                "type": "null"
              }
            ]
          },
          "company": {
            "description": "Company.",
            "anyOf": [
              {
                "type": "string",
                "maxLength": 5000
              },
              {
                "type": "null"
              }
            ]
          },
          "job_title": {
            "description": "Job title.",
            "anyOf": [
              {
                "type": "string",
                "maxLength": 5000
              },
              {
                "type": "null"
              }
            ]
          },
          "birthday": {
            "description": "Birthday as `YYYY-MM-DD`.",
            "anyOf": [
              {
                "type": "string",
                "maxLength": 5000
              },
              {
                "type": "null"
              }
            ]
          },
          "city": {
            "description": "City.",
            "anyOf": [
              {
                "type": "string",
                "maxLength": 5000
              },
              {
                "type": "null"
              }
            ]
          },
          "region": {
            "description": "State, province or region.",
            "anyOf": [
              {
                "type": "string",
                "maxLength": 5000
              },
              {
                "type": "null"
              }
            ]
          },
          "country": {
            "description": "Country.",
            "anyOf": [
              {
                "type": "string",
                "maxLength": 5000
              },
              {
                "type": "null"
              }
            ]
          },
          "street_address": {
            "description": "Street address.",
            "anyOf": [
              {
                "type": "string",
                "maxLength": 5000
              },
              {
                "type": "null"
              }
            ]
          },
          "postal_code": {
            "description": "Postal code.",
            "anyOf": [
              {
                "type": "string",
                "maxLength": 5000
              },
              {
                "type": "null"
              }
            ]
          },
          "website_url": {
            "description": "Website URL.",
            "anyOf": [
              {
                "type": "string",
                "maxLength": 5000
              },
              {
                "type": "null"
              }
            ]
          },
          "linkedin_url": {
            "description": "LinkedIn profile URL.",
            "anyOf": [
              {
                "type": "string",
                "maxLength": 5000
              },
              {
                "type": "null"
              }
            ]
          },
          "source": {
            "description": "Where the contact came from.",
            "anyOf": [
              {
                "type": "string",
                "maxLength": 5000
              },
              {
                "type": "null"
              }
            ]
          },
          "notes": {
            "description": "Free-form notes.",
            "anyOf": [
              {
                "type": "string",
                "maxLength": 5000
              },
              {
                "type": "null"
              }
            ]
          },
          "owner_user_id": {
            "description": "Member who owns the contact.",
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ]
          },
          "lead_status": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "new",
                  "open",
                  "in_progress",
                  "attempted",
                  "connected",
                  "unqualified",
                  "bad_timing"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "lifecycle_stage": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "subscriber",
                  "lead",
                  "marketing_qualified",
                  "sales_qualified",
                  "opportunity",
                  "customer",
                  "evangelist",
                  "other"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "custom_values": {
            "description": "Values keyed by contact field ID. Keys you omit keep their value.",
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "number"
                },
                {
                  "type": "boolean"
                },
                {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                {
                  "type": "null"
                }
              ]
            }
          },
          "tag_ids": {
            "description": "The complete set of tag IDs. Replaces the current tags.",
            "maxItems": 30,
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          }
        },
        "additionalProperties": false,
        "description": "A contact needs at least a name, a phone or an email.",
        "examples": [
          {
            "first_name": "Ana",
            "last_name": "Pérez",
            "primary_phone": "+50760001234",
            "primary_email": "ana.perez@example.com",
            "lifecycle_stage": "customer",
            "custom_values": {
              "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d": "Albrook Mall"
            },
            "tag_ids": [
              "5c6d7e8f-9a0b-4c1d-8e2f-3a4b5c6d7e8f"
            ]
          }
        ]
      },
      "UpdateContact": {
        "type": "object",
        "properties": {
          "first_name": {
            "description": "First name.",
            "anyOf": [
              {
                "type": "string",
                "maxLength": 5000
              },
              {
                "type": "null"
              }
            ]
          },
          "last_name": {
            "description": "Last name.",
            "anyOf": [
              {
                "type": "string",
                "maxLength": 5000
              },
              {
                "type": "null"
              }
            ]
          },
          "primary_email": {
            "description": "Email.",
            "anyOf": [
              {
                "type": "string",
                "format": "email",
                "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
              },
              {
                "type": "null"
              }
            ]
          },
          "primary_phone": {
            "description": "Phone with country code, for example `+507 6000-1234`.",
            "anyOf": [
              {
                "type": "string",
                "maxLength": 5000
              },
              {
                "type": "null"
              }
            ]
          },
          "company": {
            "description": "Company.",
            "anyOf": [
              {
                "type": "string",
                "maxLength": 5000
              },
              {
                "type": "null"
              }
            ]
          },
          "job_title": {
            "description": "Job title.",
            "anyOf": [
              {
                "type": "string",
                "maxLength": 5000
              },
              {
                "type": "null"
              }
            ]
          },
          "birthday": {
            "description": "Birthday as `YYYY-MM-DD`.",
            "anyOf": [
              {
                "type": "string",
                "maxLength": 5000
              },
              {
                "type": "null"
              }
            ]
          },
          "city": {
            "description": "City.",
            "anyOf": [
              {
                "type": "string",
                "maxLength": 5000
              },
              {
                "type": "null"
              }
            ]
          },
          "region": {
            "description": "State, province or region.",
            "anyOf": [
              {
                "type": "string",
                "maxLength": 5000
              },
              {
                "type": "null"
              }
            ]
          },
          "country": {
            "description": "Country.",
            "anyOf": [
              {
                "type": "string",
                "maxLength": 5000
              },
              {
                "type": "null"
              }
            ]
          },
          "street_address": {
            "description": "Street address.",
            "anyOf": [
              {
                "type": "string",
                "maxLength": 5000
              },
              {
                "type": "null"
              }
            ]
          },
          "postal_code": {
            "description": "Postal code.",
            "anyOf": [
              {
                "type": "string",
                "maxLength": 5000
              },
              {
                "type": "null"
              }
            ]
          },
          "website_url": {
            "description": "Website URL.",
            "anyOf": [
              {
                "type": "string",
                "maxLength": 5000
              },
              {
                "type": "null"
              }
            ]
          },
          "linkedin_url": {
            "description": "LinkedIn profile URL.",
            "anyOf": [
              {
                "type": "string",
                "maxLength": 5000
              },
              {
                "type": "null"
              }
            ]
          },
          "source": {
            "description": "Where the contact came from.",
            "anyOf": [
              {
                "type": "string",
                "maxLength": 5000
              },
              {
                "type": "null"
              }
            ]
          },
          "notes": {
            "description": "Free-form notes.",
            "anyOf": [
              {
                "type": "string",
                "maxLength": 5000
              },
              {
                "type": "null"
              }
            ]
          },
          "owner_user_id": {
            "description": "Member who owns the contact.",
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ]
          },
          "lead_status": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "new",
                  "open",
                  "in_progress",
                  "attempted",
                  "connected",
                  "unqualified",
                  "bad_timing"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "lifecycle_stage": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "subscriber",
                  "lead",
                  "marketing_qualified",
                  "sales_qualified",
                  "opportunity",
                  "customer",
                  "evangelist",
                  "other"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "custom_values": {
            "description": "Values keyed by contact field ID. Keys you omit keep their value.",
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "number"
                },
                {
                  "type": "boolean"
                },
                {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                {
                  "type": "null"
                }
              ]
            }
          },
          "tag_ids": {
            "description": "The complete set of tag IDs. Replaces the current tags.",
            "maxItems": 30,
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          }
        },
        "additionalProperties": false,
        "description": "Only the fields you send change. Send `null` to clear one.",
        "examples": [
          {
            "job_title": "Gerente de compras",
            "notes": null,
            "tag_ids": [
              "5c6d7e8f-9a0b-4c1d-8e2f-3a4b5c6d7e8f"
            ]
          }
        ]
      },
      "TemplateMessage": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64,
            "description": "Approved template ID from `GET /templates`."
          },
          "components": {
            "default": [],
            "description": "Variable values, in the WhatsApp Cloud API format.",
            "maxItems": 10,
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "type": {
                  "type": "string",
                  "enum": [
                    "header",
                    "body",
                    "button"
                  ]
                },
                "sub_type": {
                  "type": "string",
                  "enum": [
                    "url",
                    "quick_reply"
                  ]
                },
                "index": {
                  "description": "Button position, from `\"0\"`.",
                  "type": "string",
                  "maxLength": 2
                },
                "parameters": {
                  "maxItems": 20,
                  "type": "array",
                  "items": {
                    "oneOf": [
                      {
                        "type": "object",
                        "properties": {
                          "type": {
                            "type": "string",
                            "const": "text"
                          },
                          "text": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 1024
                          },
                          "parameter_name": {
                            "description": "For `NAMED` templates.",
                            "type": "string"
                          }
                        },
                        "required": [
                          "type",
                          "text"
                        ],
                        "additionalProperties": false
                      },
                      {
                        "type": "object",
                        "properties": {
                          "type": {
                            "type": "string",
                            "const": "payload"
                          },
                          "payload": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 128
                          }
                        },
                        "required": [
                          "type",
                          "payload"
                        ],
                        "additionalProperties": false
                      },
                      {
                        "type": "object",
                        "properties": {
                          "type": {
                            "type": "string",
                            "const": "image"
                          },
                          "image": {
                            "type": "object",
                            "properties": {
                              "link": {
                                "type": "string",
                                "format": "uri",
                                "description": "Public HTTPS URL of the file."
                              }
                            },
                            "required": [
                              "link"
                            ],
                            "additionalProperties": false,
                            "description": "Media file."
                          }
                        },
                        "required": [
                          "type",
                          "image"
                        ],
                        "additionalProperties": false
                      },
                      {
                        "type": "object",
                        "properties": {
                          "type": {
                            "type": "string",
                            "const": "video"
                          },
                          "video": {
                            "type": "object",
                            "properties": {
                              "link": {
                                "type": "string",
                                "format": "uri",
                                "description": "Public HTTPS URL of the file."
                              }
                            },
                            "required": [
                              "link"
                            ],
                            "additionalProperties": false,
                            "description": "Media file."
                          }
                        },
                        "required": [
                          "type",
                          "video"
                        ],
                        "additionalProperties": false
                      },
                      {
                        "type": "object",
                        "properties": {
                          "type": {
                            "type": "string",
                            "const": "document"
                          },
                          "document": {
                            "type": "object",
                            "properties": {
                              "link": {
                                "type": "string",
                                "format": "uri",
                                "description": "Public HTTPS URL of the file."
                              },
                              "filename": {
                                "type": "string",
                                "maxLength": 240
                              }
                            },
                            "required": [
                              "link"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "required": [
                          "type",
                          "document"
                        ],
                        "additionalProperties": false
                      },
                      {
                        "type": "object",
                        "properties": {
                          "type": {
                            "type": "string",
                            "const": "currency"
                          },
                          "currency": {
                            "type": "object",
                            "properties": {
                              "amount_1000": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              },
                              "code": {
                                "type": "string",
                                "minLength": 3,
                                "maxLength": 3
                              },
                              "fallback_value": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "amount_1000",
                              "code",
                              "fallback_value"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "required": [
                          "type",
                          "currency"
                        ],
                        "additionalProperties": false
                      },
                      {
                        "type": "object",
                        "properties": {
                          "type": {
                            "type": "string",
                            "const": "date_time"
                          },
                          "date_time": {
                            "type": "object",
                            "properties": {
                              "fallback_value": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "fallback_value"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "required": [
                          "type",
                          "date_time"
                        ],
                        "additionalProperties": false
                      }
                    ]
                  }
                }
              },
              "required": [
                "type",
                "parameters"
              ],
              "additionalProperties": false
            }
          }
        },
        "required": [
          "id"
        ],
        "additionalProperties": false,
        "description": "An approved WhatsApp template and the values of its variables.",
        "examples": [
          {
            "id": "1234567890123456",
            "components": [
              {
                "type": "body",
                "parameters": [
                  {
                    "type": "text",
                    "text": "Ana"
                  },
                  {
                    "type": "text",
                    "text": "10482"
                  }
                ]
              }
            ]
          }
        ]
      },
      "SendMessage": {
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "const": "text"
              },
              "text": {
                "type": "string",
                "minLength": 1,
                "maxLength": 4096,
                "description": "Message text."
              }
            },
            "required": [
              "type",
              "text"
            ],
            "additionalProperties": false
          },
          {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "const": "template"
              },
              "template": {
                "$ref": "#/components/schemas/TemplateMessage"
              }
            },
            "required": [
              "type",
              "template"
            ],
            "additionalProperties": false
          }
        ],
        "description": "Text works inside the channel reply window; a template (WhatsApp only) works any time.",
        "examples": [
          {
            "type": "text",
            "text": "Sí, ya están listos. Puede pasar hoy."
          }
        ]
      },
      "StartConversation": {
        "type": "object",
        "properties": {
          "channel_id": {
            "type": "string",
            "format": "uuid",
            "description": "WhatsApp channel to send from. See `GET /channels`."
          },
          "phone": {
            "type": "string",
            "minLength": 6,
            "maxLength": 32,
            "description": "Recipient phone with country code, for example `+50760001234`."
          },
          "template": {
            "$ref": "#/components/schemas/TemplateMessage"
          }
        },
        "required": [
          "channel_id",
          "phone",
          "template"
        ],
        "additionalProperties": false,
        "description": "Sends a template to a phone number.",
        "examples": [
          {
            "channel_id": "8f3c2a5e-6b1d-4c7a-9e2f-1a2b3c4d5e6f",
            "phone": "+50760001234",
            "template": {
              "id": "1234567890123456",
              "components": [
                {
                  "type": "body",
                  "parameters": [
                    {
                      "type": "text",
                      "text": "Ana"
                    },
                    {
                      "type": "text",
                      "text": "10482"
                    }
                  ]
                }
              ]
            }
          }
        ]
      },
      "AssignConversation": {
        "type": "object",
        "properties": {
          "assigned_user_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "description": "Member to assign; null unassigns."
          },
          "sync_contact_owner": {
            "default": true,
            "description": "Also make that member the contact owner.",
            "type": "boolean"
          }
        },
        "required": [
          "assigned_user_id"
        ],
        "additionalProperties": false,
        "examples": [
          {
            "assigned_user_id": "2d4f6a8c-1b3d-4e5f-8a7b-9c0d1e2f3a4b",
            "sync_contact_owner": true
          }
        ]
      },
      "CloseConversation": {
        "type": "object",
        "properties": {
          "category": {
            "default": null,
            "description": "Why it is closed.",
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "resolved",
                  "sale",
                  "no_response",
                  "spam",
                  "other"
                ]
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "additionalProperties": false,
        "examples": [
          {
            "category": "sale"
          }
        ]
      },
      "CreateWebhook": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "maxLength": 2048,
            "format": "uri",
            "description": "Public HTTPS endpoint."
          },
          "event_types": {
            "minItems": 1,
            "maxItems": 5,
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "message.received",
                "message.sent",
                "conversation.opened",
                "conversation.closed",
                "conversation.assignment_changed"
              ]
            }
          }
        },
        "required": [
          "url",
          "event_types"
        ],
        "additionalProperties": false,
        "examples": [
          {
            "url": "https://example.com/ricky/webhooks",
            "event_types": [
              "message.received",
              "conversation.closed"
            ]
          }
        ]
      }
    },
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "An organization API key, `rky_live_…`, created in Settings → API. Send it only from a server."
      }
    },
    "parameters": {
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": true,
        "description": "Unique per logical write, 8–200 characters. Retrying with the same key and body replays the first response.",
        "schema": {
          "type": "string",
          "minLength": 8,
          "maxLength": 200
        },
        "example": "order-10482-ready"
      }
    },
    "headers": {
      "X-Request-Id": {
        "description": "Request ID. Quote it to support.",
        "schema": {
          "type": "string"
        }
      },
      "X-RateLimit-Limit": {
        "description": "Requests allowed per minute.",
        "schema": {
          "type": "integer"
        }
      },
      "X-RateLimit-Remaining": {
        "description": "Requests left this minute.",
        "schema": {
          "type": "integer"
        }
      },
      "X-RateLimit-Reset": {
        "description": "Unix time when the minute window resets.",
        "schema": {
          "type": "integer"
        }
      }
    }
  }
}
