Mini-loja
Configura a aparência da mini-loja aberta pelo WhatsApp, envia imagens para ela e manda o link a um cliente pelo melhor caminho disponível.
A mini-loja é a página web leve que o cliente abre por um link dentro do WhatsApp: vitrine, carrinho e pedido, com o cliente já reconhecido pelo telefone. A aparência dela (logo, cores, faixa de destaque, rodapé) é definida aqui.
Ler a aparência
/api/v1/vendor/whatsapp/web-preview/settingsSellerLê a aparência da mini-loja
Campos que o seller não preencheu aparecem vazios; nesse caso a mini-loja herda logo e cores do tema da loja. Os campos brand_* mostram o que seria herdado, só para você exibir de referência.
Exemplo de requisição
curl "$BASE_URL/api/v1/vendor/whatsapp/web-preview/settings" \
-H "Authorization: Bearer $TOKEN"Resposta
{
"store_name": "Loja Centro",
"brand_logo_url": "https://minhaloja.io.venddor.com.br/uploads/logo.png",
"brand_header_color": "#0F172A",
"brand_accent_color": "#16A34A",
"logo_media_id": "",
"header_color": "",
"accent_color": "#16A34A",
"hero_media_id": "5d0c1a44-8f0e-4d6b-9a4e-0b8f7c1e2a33",
"hero_title": "Frete grátis acima de R$ 200",
"hero_subtitle": "Só até domingo",
"greeting_template": "Oi, {{customer_name}}! Veja as novidades.",
"card_style": "C",
"footer_info": { "hours_summary": "Seg a sáb, 9h às 18h" },
"hours_summary": "Seg a sáb, 9h às 18h",
"updated_at": "2026-10-10T18:00:00Z"
}Campos da resposta
store_namestringbrand_logo_urlstringbrand_header_colorstringbrand_accent_colorstringlogo_media_idstringweb-preview/media. Vazio herda o do tema.header_colorstring#RGB ou #RRGGBB. Vazio herda a do tema.accent_colorstring#RGB ou #RRGGBB. Vazio herda a do tema.hero_media_idstringhero_titlestringhero_subtitlestringgreeting_templatestring{{customer_name}}.card_stylestringC.pinned_collectionsarrayfooter_infoobjecthours_summarystringfooter_info.updated_atstringErros
| Status | Quando | Corpo |
|---|---|---|
| 401 | Sem token | {"error":"authentication required"} |
| 403 | Token que não é de seller; módulo desligado; falta o privilégio | {"error":"insufficient permissions"} e demais |
| 404 | Usuário sem cadastro de seller | {"error":"vendor profile not found","code":"vendor_profile_not_found"} |
| 500 | Falha ao ler | {"error":"..."} |
Gravar a aparência
/api/v1/vendor/whatsapp/web-preview/settingsSellerGrava a aparência da mini-loja
Devolve a aparência já atualizada, no formato da leitura. Cuidado com as duas regras diferentes:
- Os campos simples (
logo_media_id, cores, faixa, saudação,card_style) são substituídos: o que você não enviar volta para vazio e passa a herdar o tema.card_stylevazio viraC. pinned_collectionsefooter_infosão mesclados com o que já existe: quem não enviar mantém o valor atual.
Por isso, o jeito seguro é ler, alterar o necessário e devolver o objeto inteiro.
Corpo da requisição
logo_media_idstringheader_colorstring#RGB e #RRGGBB; um # repetido (##004590) é corrigido. Vazio herda do tema.accent_colorstringhero_media_idstringhero_titlestringhero_subtitlestringgreeting_templatestringcard_stylestringpadrão: Cpinned_collectionsarrayfooter_infoobjecttext). Mesclado chave a chave.hours_summarystringfooter_info. Enviar "" apaga.Exemplo de requisição
curl -X PUT "$BASE_URL/api/v1/vendor/whatsapp/web-preview/settings" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"accent_color": "#16A34A",
"hero_title": "Frete grátis acima de R$ 200",
"hero_subtitle": "Só até domingo",
"greeting_template": "Oi, {{customer_name}}! Veja as novidades.",
"card_style": "C",
"hours_summary": "Seg a sáb, 9h às 18h"
}'Resposta
{
"store_name": "Loja Centro",
"accent_color": "#16A34A",
"hero_title": "Frete grátis acima de R$ 200",
"hero_subtitle": "Só até domingo",
"greeting_template": "Oi, {{customer_name}}! Veja as novidades.",
"card_style": "C",
"footer_info": { "hours_summary": "Seg a sáb, 9h às 18h" },
"hours_summary": "Seg a sáb, 9h às 18h",
"updated_at": "2026-10-11T16:00:00Z"
}Erros
| Status | Quando | Corpo |
|---|---|---|
| 400 | JSON inválido | {"error":"invalid body"} |
| 400 | Cor que não é #RGB/#RRGGBB | {"error":"invalid_color"} |
| 401 / 403 | Autenticação, módulo ou privilégio | veja acima |
| 500 | Falha ao gravar | {"error":"..."} |
Enviar uma imagem
/api/v1/vendor/whatsapp/web-preview/mediaSellerEnvia uma imagem de logo ou de faixa para a mini-loja
Corpo multipart/form-data. O destino é fixo (a aparência da mini-loja): você não escolhe dono. Só aceita imagens raster, para que o ajuste da mini-loja não vire uma porta para o envio de arquivos genéricos.
Corpo da requisição
filefileobrigatórioExemplo de requisição
curl -X POST "$BASE_URL/api/v1/vendor/whatsapp/web-preview/media" \
-H "Authorization: Bearer $TOKEN" \
-F "file=@faixa-promocao.jpg"Resposta
{
"id": "5d0c1a44-8f0e-4d6b-9a4e-0b8f7c1e2a33",
"owner_id": "appearance",
"owner_type": "whatsapp_minishop",
"filename": "faixa-promocao.jpg",
"content_type": "image/jpeg",
"size": 120344,
"url": "/uploads/dfe2555e/whatsapp_minishop/faixa-promocao.jpg",
"position": 0,
"created_at": "2026-10-11T15:55:00Z"
}Campos da resposta
iduuidlogo_media_id ou hero_media_id.urlstring/uploads/...).filenamestringcontent_typestringsizeintegerowner_typestringwhatsapp_minishop.owner_idstringappearance.created_atstringErros
| Status | Quando | Corpo |
|---|---|---|
| 400 | Corpo que não é multipart ou grande demais | {"error":"failed to parse multipart form","detail":"..."} |
| 400 | Falta file | {"error":"file is required","detail":"..."} |
| 400 | Não é imagem raster (SVG, PDF e MP4 são recusados aqui) | {"error":"unsupported file type","detail":"Mini-shop assets accept JPEG, PNG, GIF, WebP, or AVIF images only. Detected: application/pdf"} |
| 401 / 403 | Autenticação, módulo ou privilégio | veja acima |
| 500 | Falha ao gravar | {"error":"failed to upload file","detail":"..."} |
Enviar a mini-loja a um telefone
/api/v1/vendor/whatsapp/web-preview/sendSellerEnvia o link da mini-loja a um telefone pelo melhor caminho disponível
Cria um link personalizado para o telefone e escolhe o caminho de entrega sozinha:
- Se os fluxos nativos da Meta estão ligados na loja, abre o formulário nativo no lugar do link (
mode: "native_flow"). - Se o cliente escreveu nas últimas 24 horas, envia um botão com link (
cta_url). Se o botão falhar, tenta texto com pré-visualização do link. - Fora da janela de 24 horas, envia um modelo aprovado com botão de link. Sem modelo, falha.
É a única rota deste conjunto que pode iniciar a conversa com um número que não escreveu antes. O seller responde pelo consentimento do cliente.
Corpo da requisição
phonestringobrigatóriopurposestringpadrão: storestorecartcheckoutbodystring{{vendor_name}} e {{customer_name}}. Se omitido, usa o texto do modelo gerenciado ou uma frase padrão.cta_labelstringpadrão: Ver lojamanaged_template_iduuidtemplate_namestringmanaged_template_id.template_paramsarrayforce_templatebooleanpadrão: falseprefer_text_previewbooleanpadrão: falsevendor_iduuidExemplo de requisição
curl -X POST "$BASE_URL/api/v1/vendor/whatsapp/web-preview/send" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"phone": "5511999990000",
"purpose": "store",
"body": "Oi! Veja as ofertas da semana na {{vendor_name}}.",
"cta_label": "Ver ofertas"
}'Resposta
{
"result": {
"mode": "cta_url",
"url": "https://minhaloja.io.venddor.com.br/wa/eyJ0IjoicyJ9",
"message_id": 48240,
"window_open": true
},
"message": {
"id": 48240,
"phone_number": "5511999990000",
"message_type": "interactive",
"status": "sent",
"created_at": "2026-10-11T16:05:00Z"
}
}Campos da resposta
result.modestringcta_urltext_previewtemplatenative_flowresult.urlstringnative_flow.result.message_idintegerresult.window_openbooleantrue se o cliente escreveu nas últimas 24 horas.result.warningstringmessageobjectid, phone_number, message_type, status e created_at.Erros
| Status | Quando | Corpo |
|---|---|---|
| 400 | JSON inválido | {"error":"invalid json"} |
| 401 / 403 | Autenticação, módulo ou privilégio | veja acima |
| 502 | Falha no envio. Inclui janela fechada sem modelo configurado | {"error":"whatsapp: janela de 24h fechada e nenhum template configurado ... crie/aprove um template com botão URL /wa/{{1}}","result":{...}} |