Criar produto
POST /catalog/products
Cria um produto no catálogo da inbox. Precisa de name e de uma foto (image_data, image_url ou image_urls). A revisão do WhatsApp vem em status_info.
Autenticação
[
{
"token": []
}
]
{
"token": {
"name": "token",
"type": "apiKey",
"in": "header"
}
}
Corpo da requisição
{
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/BusinessProductCreate"
},
"example": {
"name": "Camisa azul",
"price": "89900",
"currency": "BRL",
"retailer_id": "CAMISA-01",
"image_urls": [
"https://loja.com/camisa.jpg"
]
}
}
}
}
Respostas
{
"201": {
"description": "Criado.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/BusinessProduct"
},
"example": {
"id": "8123456789012345",
"retailer_id": "CAMISA-01",
"name": "Camisa azul",
"description": "Algodão, tamanhos P a GG.",
"price": "89900",
"currency": "BRL",
"is_hidden": false,
"is_sanctioned": false,
"media": {
"images": [
{
"id": "1",
"original_image_url": "https://loja.com/camisa.jpg"
}
]
},
"status_info": {
"status": "APPROVED",
"can_appeal": false
}
}
}
}
},
"400": {
"description": "Pedido inválido.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OrkesioError"
},
"example": {
"error": "invalid_request",
"message": "price é obrigatório."
}
}
}
},
"401": {
"description": "Token inválido ou ausente.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OrkesioError"
},
"example": {
"error": "unauthorized",
"message": "Token inválido."
}
}
}
},
"403": {
"description": "`not_admin`: o WhatsApp recusou por falta de permissão (a conta precisa ser comercial e dona do catálogo).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OrkesioError"
},
"example": {
"error": "not_admin",
"message": "O WhatsApp recusou por falta de permissão."
}
}
}
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
},
"501": {
"$ref": "#/components/responses/CloudUnsupported"
},
"503": {
"description": "`disconnected`: a inbox está desconectada do WhatsApp. `unavailable`: o WhatsApp não respondeu agora (conexão caindo ou sem resposta); tente de novo.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OrkesioError"
},
"example": {
"error": "unavailable",
"message": "O WhatsApp não respondeu agora; tente de novo."
}
}
}
}
}
Estado: Disponível
Compatibilidade de canais
| Canal | Compatível | Observação |
|---|---|---|
| WhatsApp (Web) | Sim | |
| WhatsApp (API oficial) | Não | Na API oficial, perfil e catálogo ficam no Gerenciador do WhatsApp da Meta. |
| Não | ||
| Messenger | Não | |
| Telegram | Não |
Eventos que esta rota gera
Nenhum. Esta rota não gera evento no webhook (nem em GET /events): o resultado vem só na resposta.
Antes e depois (uazapi → Orkesio)
Na uazapi: POST /business/catalog/save.
- Criar é
POST(antes osavesemid); os campos são os mesmos da uazapi; responde o produto sem o enveloperesponse.
#/components/schemas/BusinessProductCreate
{
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "string",
"maxLength": 256,
"description": "Nome do produto."
},
"description": {
"type": "string",
"maxLength": 4096,
"description": "Descrição do produto."
},
"currency": {
"type": "string",
"pattern": "^[A-Z]{3}quot;,
"example": "BRL",
"description": "Moeda do preço, em código ISO 4217 (ex.: `BRL`). Obrigatória com `price`."
},
"price": {
"type": "string",
"pattern": "^\\d{1,18}quot;,
"description": "Preço em milésimos da moeda, só dígitos (19990 = R$ 19,99). Exige `currency`.",
"example": "19990"
},
"sale_price": {
"type": "string",
"pattern": "^\\d{1,18}quot;,
"description": "Preço promocional em milésimos da moeda. Exige `price`."
},
"url": {
"type": "string",
"format": "uri",
"maxLength": 2048,
"description": "Link HTTPS do produto no seu site."
},
"retailer_id": {
"type": "string",
"maxLength": 256,
"description": "Código do produto no seu sistema (SKU)."
},
"is_hidden": {
"type": "boolean",
"default": false,
"description": "`true` cria o produto escondido do catálogo."
},
"image_urls": {
"type": "array",
"minItems": 1,
"maxItems": 10,
"items": {
"type": "string",
"format": "uri"
},
"description": "Fotos já hospedadas no WhatsApp (os links de `media.images` de um produto), de 1 a 10. Outros endereços são recusados; para foto nova, use `image_data` ou `image_url`."
},
"video_urls": {
"type": "array",
"maxItems": 10,
"items": {
"type": "string",
"format": "uri"
},
"description": "Vídeos já hospedados no WhatsApp (os links de `media.videos`), até 10."
},
"image_data": {
"type": "string",
"description": "Foto nova: JPEG ou PNG em base64 ou Data URL, até 16 MB. Troca as fotos do produto por esta e vale mais que `image_url`."
},
"image_url": {
"type": "string",
"format": "uri",
"maxLength": 2048,
"description": "Foto nova por link público HTTPS (JPEG ou PNG, até 16 MB). A api baixa e envia ao WhatsApp; troca as fotos do produto por esta."
},
"compliance_category": {
"type": "string",
"maxLength": 128,
"description": "Categoria de conformidade, exigida pelo WhatsApp em alguns países."
},
"compliance_info": {
"$ref": "#/components/schemas/BusinessComplianceInfo"
},
"width": {
"type": "integer",
"minimum": 1,
"maximum": 1024,
"description": "Largura, em pixels, da foto em `media.images[].request_image_url` na resposta (padrão 100)."
},
"height": {
"type": "integer",
"minimum": 1,
"maximum": 1024,
"description": "Altura, em pixels, da foto em `media.images[].request_image_url` na resposta (padrão 100)."
}
},
"additionalProperties": false,
"description": "Produto novo. Precisa de `name` e de uma foto (`image_data`, `image_url` ou `image_urls`)."
}
#/components/schemas/BusinessComplianceInfo
{
"type": "object",
"properties": {
"country_code_origin": {
"type": "string",
"description": "País de origem (código de 2 ou 3 letras)."
},
"importer_name": {
"type": "string",
"description": "Nome do importador."
},
"importer_address": {
"$ref": "#/components/schemas/BusinessAddress"
}
}
}
#/components/schemas/BusinessAddress
{
"type": "object",
"properties": {
"street1": {
"type": "string",
"description": "Endereço (linha 1)."
},
"street2": {
"type": "string",
"description": "Complemento."
},
"city": {
"type": "string",
"description": "Cidade."
},
"region": {
"type": "string",
"description": "Estado ou região."
},
"postal_code": {
"type": "string",
"description": "CEP ou código postal."
},
"country_code": {
"type": "string",
"description": "País (código de 2 ou 3 letras)."
}
}
}
#/components/schemas/BusinessProduct
{
"type": "object",
"required": [
"id",
"name",
"price",
"currency",
"is_hidden",
"is_sanctioned",
"media",
"status_info"
],
"properties": {
"id": {
"type": "string",
"description": "Id do produto no catálogo do WhatsApp."
},
"retailer_id": {
"type": "string",
"description": "Código do produto no seu sistema (SKU), quando informado."
},
"belongs_to": {
"type": "string"
},
"name": {
"type": "string",
"description": "Nome do produto."
},
"description": {
"type": "string",
"description": "Descrição do produto."
},
"price": {
"type": "string",
"description": "Valor em milésimos da moeda (19990 = R$ 19,99)."
},
"currency": {
"type": "string",
"description": "Moeda do preço, em código ISO 4217 (ex.: `BRL`)."
},
"url": {
"type": "string",
"description": "Link do produto no seu site."
},
"shimmed_url": {
"type": "string",
"description": "O `url` passado pelo redirecionador do WhatsApp, como aparece no app."
},
"is_hidden": {
"type": "boolean",
"description": "Escondido do catálogo para os clientes."
},
"is_sanctioned": {
"type": "boolean"
},
"max_available": {
"type": "integer"
},
"product_availability": {
"type": "string"
},
"compliance_category": {
"type": "string",
"description": "Categoria de conformidade, exigida pelo WhatsApp em alguns países."
},
"compliance_info": {
"type": "object",
"properties": {
"country_code_origin": {
"type": "string",
"description": "País de origem (código de 2 ou 3 letras)."
},
"importer_name": {
"type": "string",
"description": "Nome do importador."
},
"importer_address": {
"type": "object",
"properties": {
"street1": {
"type": "string",
"description": "Endereço (linha 1)."
},
"street2": {
"type": "string",
"description": "Complemento."
},
"city": {
"type": "string",
"description": "Cidade."
},
"region": {
"type": "string",
"description": "Estado ou região."
},
"postal_code": {
"type": "string",
"description": "CEP ou código postal."
},
"country_code": {
"type": "string",
"description": "País (código de 2 ou 3 letras)."
}
},
"description": "Endereço do importador."
}
},
"description": "Dados de conformidade: país de origem e importador."
},
"media": {
"type": "object",
"properties": {
"images": {
"type": "array",
"items": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "Id da foto no WhatsApp."
},
"original_image_url": {
"type": "string",
"description": "Link da foto no tamanho original."
},
"request_image_url": {
"type": "string",
"description": "Link da foto redimensionada (100×100, ou o `width`/`height` da criação e da edição)."
}
}
},
"description": "Fotos."
},
"videos": {
"type": "array",
"items": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "Id do vídeo no WhatsApp."
},
"original_video_url": {
"type": "string",
"description": "Link do vídeo."
},
"thumbnail_url": {
"type": "string",
"description": "Link da miniatura do vídeo."
}
}
},
"description": "Vídeos."
}
},
"description": "Fotos e vídeos do produto."
},
"sale_price": {
"type": "object",
"required": [
"price"
],
"properties": {
"price": {
"type": "string",
"description": "Valor promocional em milésimos da moeda, como `price`."
},
"start_date": {
"type": "string",
"description": "Início da promoção, como o WhatsApp manda."
},
"end_date": {
"type": "string",
"description": "Fim da promoção, como o WhatsApp manda."
}
},
"description": "Preço promocional, quando há."
},
"status_info": {
"type": "object",
"properties": {
"status": {
"type": "string",
"description": "Estado da revisão, como o WhatsApp manda."
},
"can_appeal": {
"type": "boolean",
"description": "Dá para recorrer da recusa."
}
},
"description": "Revisão do produto pelo WhatsApp."
},
"variant_info": {
"type": "object",
"properties": {
"listing_details": {
"type": "object",
"properties": {
"description": {
"type": "string",
"description": "Descrição das variações."
},
"lowest_price": {
"type": "string",
"description": "Menor preço entre as variações."
},
"multi_price": {
"type": "string",
"description": "Faixa de preço das variações, como o WhatsApp manda."
}
},
"description": "Resumo das variações."
},
"availability": {
"type": "object",
"additionalProperties": true,
"description": "Disponibilidade de cada variação."
},
"types": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": true
},
"description": "Tipos de variação (ex.: tamanho) e as opções de cada um."
},
"variant_properties": {
"type": "array",
"items": {
"type": "object",
"required": [
"name",
"value"
],
"properties": {
"name": {
"type": "string",
"description": "Tipo da variação (ex.: `Cor`)."
},
"value": {
"type": "string",
"description": "Opção deste produto (ex.: `Azul`)."
}
}
},
"description": "As opções deste produto (ex.: cor azul)."
}
},
"description": "Variações do produto (tamanho, cor...), quando há."
}
},
"description": "Produto do catálogo do WhatsApp Business."
}
#/components/schemas/OrkesioError
{
"type": "object",
"properties": {
"error": {
"type": "string",
"description": "Código estável do erro, em inglês e `snake_case`. Os de uso geral: `invalid_request` (400): pedido inválido: JSON malformado, campo desconhecido ou valor fora do permitido (o detalhe em `message`; o campo em `field`, quando é um só); `unauthorized` (401): `token` ou `admintoken` ausente ou inválido; `forbidden` (403): o token não pode fazer isso (no servidor de demonstração, por exemplo); `not_admin` (403): o WhatsApp recusou por falta de permissão no grupo ou na newsletter; `account_restricted` (403): o WhatsApp restringiu a conta de iniciar conversas novas (mandar para quem já conversa continua valendo; até quando, em `GET /inbox/limits`); `new_chat_limit` (403): a conta atingiu a cota do WhatsApp de conversas novas neste ciclo (veja `GET /inbox/limits`); os dois também no `error` de `OrkesioMessage` e de `message.status`, e não adianta repetir o envio; `payment_required` (403): na API oficial, a Meta recusou o envio por um problema no pagamento da conta do WhatsApp Business (erro 131042 da Meta); acerte a forma de pagamento no gerenciador da Meta, porque repetir não adianta; também no `error` de `OrkesioMessage` e de `message.status`; `whatsapp_rejected` (400): o WhatsApp recusou a mudança pedida (o campo, em `field`, quando é um só); `not_found` (404): o recurso não existe nesta inbox; `conflict` (409): o recurso já existe ou mudou (id em uso, inbox de outro canal); `inbox_not_paired` (409): a inbox ainda não conectou um número; `payload_too_large` (413): o corpo passou do limite; `canceled` e `expired`: só no `error` de `OrkesioMessage` e de `message.status` (envio cancelado antes de sair, ou que passou do prazo na fila); `rate_limited` (429): muitos pedidos; espere o `Retry-After`; `internal_error` (500): falha inesperada na api; tente de novo; `send_failed` (500): o envio falhou (o motivo em `message`); também no `error` de `OrkesioMessage` e de `message.status`; `unsupported_for_channel` (501): o canal da inbox não atende esta rota ou este tipo de mensagem; `meta_error` (502): a Meta recusou ou não respondeu; `disconnected` (503): a inbox está desconectada (sem sessão do WhatsApp, ou token do canal oficial vencido); `unavailable` (503 ou 504): o WhatsApp não respondeu a tempo, ou algo em andamento impede agora; tente de novo. Cada rota lista os códigos próprios dela (`outside_window`, `number_invalid`, `flow_invalid`...). A lista pode crescer: trate código desconhecido pelo status HTTP."
},
"message": {
"type": "string",
"description": "Descrição para pessoas (às vezes o texto do WhatsApp ou da Meta). Não compare o texto: use `error`."
},
"field": {
"type": "string",
"description": "O campo do pedido que causou o erro, quando é um só (por exemplo, o campo que o WhatsApp recusou num `PATCH`)."
}
},
"required": [
"error",
"message"
],
"additionalProperties": true,
"description": "O objeto de erro da Orkesio, o mesmo em todo lugar: o corpo das respostas de erro e o `error` de `OrkesioMessage`, `message.status` e `message.failed`. Algumas rotas juntam campos próprios (`request_id`, `errors`...)."
}
#/components/responses/RateLimited
{
"description": "`rate_limited`: passou do limite de chamadas desta inbox (ou do admin); espere o tempo do header `Retry-After` e tente de novo.",
"headers": {
"Retry-After": {
"description": "Segundos até poder chamar de novo.",
"schema": {
"type": "integer",
"minimum": 1
}
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OrkesioError"
},
"example": {
"error": "rate_limited",
"message": "Muitas requisições."
}
}
}
}
#/components/responses/InternalError
{
"description": "`internal_error`: falha inesperada na api (no banco, por exemplo); tente de novo.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OrkesioError"
},
"example": {
"error": "internal_error",
"message": "Falha inesperada."
}
}
}
}
#/components/responses/CloudUnsupported
{
"description": "`unsupported_for_channel`: o canal da inbox não atende esta rota (rota só do WhatsApp Web numa inbox oficial, ou rota da API oficial numa inbox do WhatsApp Web). O canal está em `Inbox.channel`.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OrkesioError"
},
"example": {
"error": "unsupported_for_channel",
"message": "Esta rota não está disponível no canal da inbox."
}
}
}
}
Guias relacionados
Visão geral · O que funciona em cada canal · O que muda da uazapi