Appearance
Portal do Cliente
O portal é onde o cliente se serve sozinho: cria acesso, navega pelo catálogo, escolhe um horário livre e agenda — sem ligar para a unidade. Ele também consulta e cancela os próprios agendamentos, dentro do prazo definido pela unidade.
Todo o fluxo exige cliente autenticado. O cliente que a recepcionista cadastrou por telefone não fica de fora: o registro assume o cadastro existente em vez de criar um duplicado.
Headers obrigatórios
Todas as requisições devem incluir o header X-Booking-Id (UUID) com o identificador da instância. Endpoints privados exigem também Authorization: Bearer {token} com o token do cliente (guard bookingCustomer). Os únicos endpoints públicos são o registro e o login. Cliente bloqueado recebe 403 em qualquer rota privada.
Conta
Criar Conta
Registra o cliente no portal. O comportamento depende do que já existe para o e-mail na instância:
| Situação | Resultado |
|---|---|
| E-mail inexistente | Cria o cadastro com senha (exige name). |
| Cadastro existe sem senha (criado pelo staff) | Assume o cadastro: define a senha e completa os dados enviados. |
| Cadastro existe com senha | 422 orientando o login. |
Por que "assumir" em vez de duplicar?
A recepcionista cadastra clientes por telefone o dia inteiro — sem senha. Quando esse cliente resolve usar o portal, o histórico dele (agendamentos, contadores, notas) já existe. O registro reconhece o e-mail e entrega o acesso sobre o mesmo cadastro: nada de cliente duplicado, nada de histórico órfão.
http
POST /v1/booking/customer/customers/registerPayload (Body)
| Atributo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
email | string | Sim | E-mail do cliente (válido, máx. 250 caracteres). |
password | string | Sim | Senha de acesso (8 a 32 caracteres). |
name | string | Condicional | Nome completo (máx. 150 caracteres) — obrigatório apenas para cadastro novo. |
phone | string | Não | Telefone (máx. 50 caracteres). |
document | string | Não | Documento (máx. 30 caracteres). |
birthDate | string | Não | Data de nascimento (YYYY-MM-DD). |
isMarketingOptIn | boolean | Não | Aceite de marketing. |
Exemplo de Requisição
bash
curl -X POST "https://api.us.basis.tavares.in/v1/booking/customer/customers/register" \
-H "X-Booking-Id: 3fa85f64-5717-4562-b3fc-2c963f66afa6" \
-H "Content-Type: application/json" \
-d '{
"name": "Maria Silva",
"email": "maria.silva@email.com",
"password": "password123"
}'Respostas
201 Created
Retorna o ID do cadastro (novo ou assumido). Em seguida, faça login para obter o token.
json
{
"id": 1
}422 Unprocessable Entity
Ocorre quando o e-mail já possui acesso ("Este e-mail já possui acesso. Faça login.") ou falta o nome para um cadastro novo.
json
{
"errors": [{ "message": "Este e-mail já possui acesso. Faça login." }]
}Login
Autentica o cliente e retorna o token de acesso (30 dias).
http
POST /v1/booking/customer/customers/loginPayload (Body)
| Atributo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
email | string | Sim | E-mail do cliente. |
password | string | Sim | Senha do cliente. |
Respostas
200 OK
Retorna o token Bearer da sessão.
json
{
"type": "bearer",
"token": "oat_MQ.aXJjMFNEbFc1V3AxTzVydFctQi0xQXU5NXVKNkhuYzZaaDA5bks2bTYzNjg1MDMwNA",
"abilities": ["*"],
"lastUsedAt": null,
"expiresAt": "2026-10-13T01:16:25.436Z"
}422 Unprocessable Entity
Credenciais erradas, cadastro inexistente, cadastro sem senha ("crie seu acesso no registro") ou cliente bloqueado.
json
{
"errors": [{ "message": "Este cadastro ainda não possui acesso. Crie seu acesso no registro." }]
}Perfil, Atualização, Senha e Logout
Espelham os endpoints do staff, no contexto do cliente:
| Endpoint | Descrição |
|---|---|
GET /v1/booking/customer/customers/me | Dados do próprio cadastro (incluindo contadores e aceite de marketing). |
PUT /v1/booking/customer/customers/me | Atualiza nome, telefone, documento, nascimento e isMarketingOptIn. |
PATCH /v1/booking/customer/customers/change-password | Troca a senha (8 a 32 caracteres). |
POST /v1/booking/customer/customers/logout | Invalida o token atual. |
Sucesso em 204 No Content para as escritas; 200 OK com o cadastro no me.
Catálogo
O menu público da unidade — apenas o que está ativo e agendável online.
Categorias com Serviços
Retorna as categorias ativas com os serviços agendáveis aninhados, prontos para montar a tela de agendamento em uma única chamada. Serviços sem categoria vêm em uncategorizedServices.
http
GET /v1/booking/customer/catalog/categoriesExemplo de Requisição
bash
curl -X GET "https://api.us.basis.tavares.in/v1/booking/customer/catalog/categories" \
-H "X-Booking-Id: 3fa85f64-5717-4562-b3fc-2c963f66afa6" \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"Respostas
200 OK
Retorna as categorias com seus serviços e os serviços sem categoria.
json
{
"categories": [
{
"id": 1,
"name": "Cabelo",
"slug": "cabelo",
"sortOrder": 0,
"services": [
{
"id": 1,
"bookingServiceCategoryId": 1,
"name": "Corte Masculino",
"slug": "corte-masculino",
"price": "80.00",
"durationMinutes": 45,
"isBookableOnline": true,
"isActive": true,
"bookingServiceCategory": { "id": 1, "name": "Cabelo" }
}
]
}
],
"uncategorizedServices": []
}Detalhe do Serviço
http
GET /v1/booking/customer/catalog/services/:idRetorna o serviço completo (descrição, duração, preço). Responde 404 quando o serviço não existe, está inativo ou não é agendável online — o portal não vaza serviços internos.
Profissionais do Serviço
Retorna os profissionais ativos e agendáveis online que executam o serviço — para a etapa "com quem?" do fluxo.
http
GET /v1/booking/customer/catalog/professionalsParâmetros de Query
| Nome | Tipo | Obrigatório | Descrição |
|---|---|---|---|
bookingServiceId | number | Sim | Serviço (deve existir na instância). |
Respostas
200 OK
Retorna o array de profissionais.
json
[
{
"id": 1,
"name": "Ana Souza",
"slug": "ana-souza",
"avatarUrl": null,
"colorCode": "#EC4899"
}
]Horários Disponíveis (Slots)
Os slots são os horários livres calculados em tempo real: a escala do profissional no dia da semana, menos as exceções da data, menos o que já está ocupado (incluindo buffers), na grade de slotIntervalMinutes onde cabe a duração do serviço. Também respeitam a antecedência mínima (minAdvanceMinutes) e máxima (maxAdvanceDays) da instância.
http
GET /v1/booking/customer/slotsParâmetros de Query
| Nome | Tipo | Obrigatório | Descrição |
|---|---|---|---|
bookingServiceId | number | Sim | Serviço (deve existir, estar ativo e ser agendável online — senão 404). |
date | string | Sim | O dia desejado (YYYY-MM-DD). |
bookingProfessionalId | number | Não | Restringe a um profissional; omitindo, agrega todos os que executam o serviço. |
Campos da Resposta
| Campo | Tipo | Descrição |
|---|---|---|
startAt | String | Início do slot, ISO 8601 com o fuso da instância. |
endAt | String | Fim do slot (início + duração do serviço). |
bookingProfessionalId | Number | O profissional dono do slot. |
professionalName | String | Nome do profissional — pronto para exibição no seletor de horários. |
Exemplo de Requisição
bash
curl -X GET "https://api.us.basis.tavares.in/v1/booking/customer/slots?bookingServiceId=1&date=2026-09-20&bookingProfessionalId=1" \
-H "X-Booking-Id: 3fa85f64-5717-4562-b3fc-2c963f66afa6" \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"Respostas
200 OK
Retorna o array de slots livres. Um dia bloqueado (exceção, feriado) retorna um array vazio.
json
[
{
"startAt": "2026-09-20T09:00:00.000-03:00",
"endAt": "2026-09-20T09:45:00.000-03:00",
"bookingProfessionalId": 1,
"professionalName": "João Silva"
},
{
"startAt": "2026-09-20T09:15:00.000-03:00",
"endAt": "2026-09-20T10:00:00.000-03:00",
"bookingProfessionalId": 1,
"professionalName": "João Silva"
}
]Agendamentos do Cliente
Meus Agendamentos
Lista apenas os agendamentos do cliente autenticado, com filtros de período e status.
http
GET /v1/booking/customer/appointmentsParâmetros de Query
| Nome | Tipo | Obrigatório | Descrição |
|---|---|---|---|
page / perPage | number | Não | Paginação (máx. 100 por página). |
from | string | Não | Início do período (YYYY-MM-DD). |
to | string | Não | Fim do período (YYYY-MM-DD). |
status | enum | Não | pending, confirmed, canceled, completed ou no_show. |
Criar Agendamento
Agenda um ou mais serviços em uma única chamada — a identidade é sempre a do cliente autenticado (não há bookingCustomerId no payload). Somente serviços ativos e agendáveis online são aceitos; o horário é validado contra conflitos como no fluxo do staff.
http
POST /v1/booking/customer/appointmentsPayload (Body)
| Atributo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
items | array | Sim | Pelo menos um item (ver abaixo). |
items[].bookingServiceId | number | Sim | Serviço (deve existir e ser agendável online). |
items[].bookingProfessionalId | number | Sim | Profissional (deve executar o serviço). |
items[].startAt | string | Sim | Início, ISO 8601 com fuso (2026-09-20T14:00:00.000-03:00). |
notes | string | Não | Observações para a unidade. |
Exemplo de Requisição
bash
curl -X POST "https://api.us.basis.tavares.in/v1/booking/customer/appointments" \
-H "X-Booking-Id: 3fa85f64-5717-4562-b3fc-2c963f66afa6" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"items": [
{
"bookingServiceId": 1,
"bookingProfessionalId": 1,
"startAt": "2026-09-20T14:00:00.000-03:00"
}
]
}'Respostas
201 Created
Retorna o ID e o código legível do agendamento.
json
{
"id": 3,
"code": "M4T8QW"
}422 Unprocessable Entity
Horário em conflito (SLOT_UNAVAILABLE), serviço indisponível online ou cliente bloqueado (CUSTOMER_BLOCKED).
Detalhe do Agendamento
http
GET /v1/booking/customer/appointments/:idRetorna o agendamento completo (itens, eventos). Responde 404 quando o agendamento não existe ou pertence a outro cliente — o portal não vaza a existência de agendamentos alheios.
Cancelar Agendamento
Cancela o próprio agendamento, respeitando o prazo cancellationDeadlineMinutes da instância.
http
PATCH /v1/booking/customer/appointments/:id/cancelPayload (Body)
| Atributo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
reason | string | Não | Motivo do cancelamento (máx. 255 caracteres). |
Exemplo de Requisição
bash
curl -X PATCH "https://api.us.basis.tavares.in/v1/booking/customer/appointments/3/cancel" \
-H "X-Booking-Id: 3fa85f64-5717-4562-b3fc-2c963f66afa6" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{ "reason": "Imprevisto, não poderei comparecer" }'Respostas
204 No Content
Cancelamento concluído — a agenda e os recursos são liberados e a unidade é notificada.
422 Unprocessable Entity
Ocorre quando o prazo de cancelamento já encerrou (code: CANCELLATION_DEADLINE_EXCEEDED) — a partir daí, só o staff cancela.
json
{
"message": "O prazo para cancelamento deste agendamento já encerrou",
"code": "CANCELLATION_DEADLINE_EXCEEDED"
}