Venda Perfeita · Desenvolvedores
API de agendamento pelo site
Ligue o agendamento do seu site na agenda do Venda Perfeita. O cliente marca pelo site, com o visual dele, e o horário cai direto na agenda. A confirmação, o lembrete e o pedido de avaliação saem pelo WhatsApp da empresa.
Funciona com qualquer site: feito em IA (Lovable, Bolt, v0, Replit, Cursor) ou por um programador. Se o seu site foi feito em IA, o jeito mais fácil é copiar as instruções prontas em Ajustes › Agendamento online › Agendar pelo seu site e colar no chat dela.
Começar em 3 passos
- No Venda Perfeita, em Ajustes › Agendamento online › Agendar pelo seu site, gere a chave do site. Ela começa com
vpag_e só aparece uma vez. - Guarde a chave como segredo do servidor (secret ou variável de ambiente) com o nome
VP_AGENDA_KEY. - Crie uma função de servidor (Edge Function no Lovable/Supabase, rota de API no Vercel/Next.js, ou no servidor que o site já usa, como uma hospedagem na Hostinger) que chama as 4 rotas abaixo. O navegador chama a sua função; a sua função chama o Venda Perfeita. Você não precisa hospedar a API: ela já está no ar.
Autenticação e segurança
- Toda chamada leva o header
Authorization: Bearer vpag_.... - Sempre de servidor pra servidor. A API não libera chamada do navegador (sem CORS), e a chave nunca pode ir no código da página, em resposta ou em log.
- A sua função deve aceitar só as 4 ações fixas e montar a URL sozinha. Nunca use caminho, endereço ou host vindo do navegador.
- Em
marcarecancelar, mande o headerx-visitante-ipcom o IP de quem está no site (o primeiro dex-forwarded-for). É o que limita robôs por visitante. - Não guarde nome, telefone ou id de marcação de cliente em tabela do site. Pra o cliente cancelar depois, guarde o id só no navegador dele (localStorage).
Formato das respostas
Toda resposta é JSON neste envelope:
{ "success": true, "data": { ... } }
{ "success": false, "error": "Frase pronta pra mostrar ao cliente", "code": "slot_gone", "detalhe": "Motivo técnico (opcional)" }error é sempre uma frase de cliente: mostre como veio. detalhe é pro dono ou pro programador: nunca mostre ao cliente.
Rotas
Base: https://vendaperfeita.com/api/site/agenda
/api/site/agenda· CatálogoO nome da empresa, os serviços e, se a empresa deixa escolher, quem atende cada um. Busque de novo sempre que o cliente abrir o agendamento.
curl https://vendaperfeita.com/api/site/agenda \ -H "Authorization: Bearer $VP_AGENDA_KEY"
{
"success": true,
"data": {
"empresa": "Barbearia do JP",
"fuso": "America/Sao_Paulo",
"diasParaFrente": 30,
"escolheProfissional": true,
"servicos": [
{ "id": "corte", "nome": "Corte", "duracaoMin": 30, "preco": 45, "precoAPartirDe": false, "categoria": null, "profissionais": ["p_3f9c1a2b7d4e"] }
],
"profissionais": [
{ "id": "p_3f9c1a2b7d4e", "nome": "Nathan", "diasQueAtende": [2, 3, 4, 5, 6] }
]
}
}preco: null= sem preço definido (mostre “a combinar”).precoAPartirDe: true= “a partir de”.profissionaisvazio no serviço: não peça profissional (a agenda escolhe quem estiver livre).escolheProfissional: false: não mostre a escolha de profissional.diasQueAtende: 0 = domingo, 6 = sábado.
/api/site/agenda/horarios· Horários livres do diaParâmetros: data (AAAA-MM-DD), servico (id) e profissional (id, opcional). Respeita funcionamento, folga, ausência, antecedência mínima e o Google Agenda de quem conectou.
curl "https://vendaperfeita.com/api/site/agenda/horarios?data=2026-10-23&servico=corte&profissional=p_3f9c1a2b7d4e" \ -H "Authorization: Bearer $VP_AGENDA_KEY"
{ "success": true, "data": { "horarios": [ { "hora": "19:00", "inicio": "2026-10-23T22:00:00.000Z" } ] } }Mostre hora (já no horário da empresa). inicio é só pra mandar de volta na marcação. Lista vazia = sem horário livre nesse dia.
/api/site/agenda/marcar· MarcarJSON, com o header x-visitante-ip. O inicio tem que ser exatamente um dos que /horarios devolveu.
curl -X POST https://vendaperfeita.com/api/site/agenda/marcar \
-H "Authorization: Bearer $VP_AGENDA_KEY" \
-H "x-visitante-ip: 200.150.10.20" \
-H "Content-Type: application/json" \
-d '{
"servico": "corte",
"profissional": "p_3f9c1a2b7d4e",
"inicio": "2026-10-23T22:00:00.000Z",
"nome": "Lucas Prado",
"telefone": "(41) 99999-1111",
"observacao": "Prefiro máquina 2",
"origem": { "utm_source": "instagram", "utm_campaign": "outubro", "referrer": "https://l.instagram.com/" }
}'{
"success": true,
"data": {
"id": "8d1f...", "data": "2026-10-23", "hora": "19:00",
"inicio": "2026-10-23T22:00:00.000Z", "fim": "2026-10-23T22:30:00.000Z",
"servico": "Corte", "profissional": "Nathan", "local": null,
"preco": 45, "precoAPartirDe": false
}
}- Na confirmação, mostre
dataehora. Guarde oidno navegador do cliente pra ele poder cancelar. jaMarcado: true= clique duplo: é a mesma marcação, mostre a confirmação normal.origem(opcional): os parâmetrosutm_*,gclidefbclidda primeira página que a pessoa abriu e odocument.referrer. O Venda Perfeita mostra se o cliente veio do Google, do Instagram, de anúncio ou direto.- Desabilite o botão enquanto o pedido estiver em andamento.
/api/site/agenda/cancelar· CancelarSó horário marcado pelo site, com o mesmo WhatsApp. Fica no histórico como “o cliente cancelou”. Pra remarcar: marque o novo e, se der certo, cancele o antigo. Mande também o header x-visitante-ip.
curl -X POST https://vendaperfeita.com/api/site/agenda/cancelar \
-H "Authorization: Bearer $VP_AGENDA_KEY" \
-H "x-visitante-ip: 200.150.10.20" \
-H "Content-Type: application/json" \
-d '{ "id": "8d1f...", "telefone": "41 99999-1111" }'{ "success": true, "data": { "id": "8d1f...", "cancelado": true } }Códigos de erro
| code | HTTP | Quando |
|---|---|---|
| invalid_key | 401 | Chave ausente, errada ou trocada. Gere outra em Ajustes › Agendamento online e atualize o segredo. |
| agenda_off | 409 | O agendamento online está desligado, ou não há serviço/profissional disponível. |
| visitor_ip_required | 400 | A marcação veio sem o header x-visitante-ip. |
| invalid_body | 400 | Corpo fora do formato (campo a mais, tipo errado). O motivo vem em detalhe. |
| date_invalid | 400 | data fora do formato AAAA-MM-DD. |
| service_gone | 409 | O serviço não existe mais ou não marca pelo site. Recarregue o catálogo. |
| member_gone | 409 | O profissional saiu da equipe. Recarregue o catálogo. |
| member_invalid | 409 | Esse profissional não faz esse serviço. |
| slot_gone | 409 | O horário não está mais livre. Recarregue os horários do dia. |
| name_invalid | 400 | O nome tem número, link ou formato que não é de nome. |
| phone_invalid | 400 | WhatsApp inválido. Só números do Brasil, com DDD. |
| notes_link | 400 | A observação tem link. |
| phone_limit | 429 | Esse WhatsApp já marcou 3 vezes nas últimas 24 h. |
| daily_full | 429 | A empresa chegou ao teto de marcações online do dia. |
| month_full | 409 | O plano da empresa chegou ao limite de horários do mês. |
| too_many | 429 | Muitas chamadas em pouco tempo. Espere um minuto. |
| not_found | 404 | Cancelar: o horário não existe, não é do site ou o WhatsApp não bate. |
| not_open | 409 | Cancelar: o horário já foi atendido. |
| past | 409 | Cancelar: o horário já passou. |
slot_gone: recarregue os horários. service_gone ou member_gone: recarregue o catálogo. invalid_key, agenda_off e visitor_ip_required são de configuração: registre o detalhe e avise o dono.
Testar em paralelo com o sistema atual
Dá pra testar antes de trocar: o sistema atual (Trinks ou outro) continua confirmando as reservas, e o site manda uma cópia de cada uma pro Venda Perfeita.
- No Venda Perfeita, cadastre os mesmos profissionais (com o mesmo nome) e o mesmo horário de funcionamento do sistema atual.
- Depois que o sistema atual confirmar, a sua função chama
catalogo(acha serviço e profissional pelo nome),horarios(acha oinicioda mesma hora) emarcar. Cancelou lá, chamecancelaraqui. - Se o Venda Perfeita recusar uma cópia, só registre o
codeno log: é onde as duas agendas não batem. - Não ligue as mensagens de WhatsApp do Venda Perfeita durante o teste, senão o cliente recebe a confirmação em dobro.
Quando decidir trocar, tire o sistema antigo e deixe o site usar só as rotas do Venda Perfeita.
Limites
- 300 leituras e 30 escritas por minuto, por empresa.
- 10 marcações por hora por visitante (pelo x-visitante-ip).
- 3 marcações por WhatsApp a cada 24 h, e 80 por empresa por dia (somando o link e o site).
- O limite de horários do plano da empresa.