Skip to content

Clientes (CRM) ​

O CRM concentra tudo que o estabelecimento sabe sobre quem compra: o cliente em si (pessoa ou empresa), suas preferências e alergias (com severidade que salta na tela do garçom), seus documentos cifrados (passaporte, identidade), as tags que classificam ou bloqueiam e as regras de segmento que aplicam tags automaticamente por job.

O cliente aceita os tipos person e company, telefone em formato E.164 (+5511987654321), nacionalidade e país de residência em ISO 3166-1 alpha-2 e consentimento de marketing (marketingOptIn / marketingOptInAt). O e-mail é único por estabelecimento enquanto o cliente não estiver anonimizado — o campo anonymizedAt marca a anonimização LGPD, que libera o e-mail para reutilização e exclui o registro das buscas por padrão.

Headers obrigatórios

Todas as requisições devem incluir o header X-Tour-Id (UUID) com o identificador da instância e Authorization: Bearer {token} com o token de um usuário staff (guard toursUser).

Permissões

As mutações desta página exigem a permissão customer.write — a API responde 403 com code: FORBIDDEN quando ela falta. A leitura de documentos (index e show de customer-documents) exige customer.document.read, pois o conteúdo é sensível (cifrado com chave do KMS).


Clientes ​

Listar Clientes ​

Lista os clientes do estabelecimento, com paginação, busca e filtros.

http
GET /v1/tours/user/customers

Parâmetros de Query ​

NomeTipoObrigatórioDescrição
pagenumberNãoO número da página (mínimo: 1).
perPagenumberNãoItens por página (entre 1 e 100).
searchstringNãoBusca por nome (máx. 150 caracteres).
kindenumNãoFiltra por tipo: person ou company.
marketingOptInbooleanNãoFiltra por consentimento de marketing.
anonymizedbooleanNãotrue lista só anonimizados; false só não anonimizados.
orderByenumNãoid, fullName ou createdAt (padrão: id).
orderDirectionenumNãoasc ou desc.

Exemplo de Requisição ​

bash
curl -X GET "https://api.us.basis.tavares.in/v1/tours/user/customers?kind=person&marketingOptIn=true" \
  -H "X-Tour-Id: 123e4567-e89b-12d3-a456-426614174000" \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"

Respostas ​

200 OK

Retorna a página de clientes no formato meta/data.

json
{
  "meta": {
    "currentPage": 1,
    "perPage": 10
  },
  "data": [
    {
      "id": 1,
      "tourId": 1,
      "kind": "person",
      "fullName": "Mr. Rogelio Cummerata III",
      "legalName": null,
      "email": "Vada.Corkery93@yahoo.com",
      "phoneE164": null,
      "birthDate": null,
      "nationality": null,
      "residenceCountry": null,
      "preferredLocale": null,
      "marketingOptIn": false,
      "marketingOptInAt": null,
      "notes": null,
      "anonymizedAt": null,
      "createdAt": "2026-10-07T11:56:14.487-03:00",
      "updatedAt": "2026-10-07T11:56:14.487-03:00"
    }
  ]
}

Criar Cliente ​

Cadastra um cliente (pessoa ou empresa). Exige customer.write.

http
POST /v1/tours/user/customers

Payload (Body) ​

AtributoTipoObrigatórioDescrição
kindenumNãoperson ou company (padrão: person).
fullNamestringSimNome completo / nome fantasia (máx. 200 caracteres).
legalNamestringNãoRazão social (máx. 200 caracteres).
emailstringNãoE-mail único no estabelecimento (máx. 250 caracteres).
phoneE164stringNãoTelefone em E.164: + seguido de 8 a 15 dígitos.
birthDatedateNãoData de nascimento (YYYY-MM-DD).
nationalitystringNãoNacionalidade, ISO alpha-2 (2 letras, ex.: BR).
residenceCountrystringNãoPaís de residência, ISO alpha-2.
preferredLocalestringNãoLocale preferido (máx. 10 caracteres, ex.: pt-BR).
marketingOptInbooleanNãoConsentimento de marketing (padrão: false).
marketingOptInAtdateNãoData/hora do consentimento (ISO 8601).
notesstringNãoObservações internas.

Exemplo de Requisição ​

bash
curl -X POST "https://api.us.basis.tavares.in/v1/tours/user/customers" \
  -H "X-Tour-Id: 123e4567-e89b-12d3-a456-426614174000" \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{
    "kind": "person",
    "fullName": "Cliente Doc",
    "email": "doc.cliente@tours.dev",
    "phoneE164": "+5511987654321",
    "birthDate": "1990-05-15",
    "nationality": "BR",
    "residenceCountry": "BR",
    "preferredLocale": "pt-BR",
    "marketingOptIn": true,
    "notes": "Cliente criado pela documentação"
  }'

Respostas ​

201 Created

Retorna o ID do cliente criado.

json
{
  "id": 4
}

422 Unprocessable Entity

Ocorre quando o e-mail já existe no estabelecimento (em cliente não anonimizado) ou o payload é inválido.

json
{
  "errors": [
    {
      "message": "The email has already been taken",
      "rule": "database.unique",
      "field": "email"
    }
  ]
}

403 Forbidden

Ocorre quando o usuário não possui a permissão customer.write (code: FORBIDDEN).

Listar para Dropdown ​

Retorna os clientes em formato simplificado (value/label), ideal para selects — como o vínculo de cliente a uma reserva.

http
GET /v1/tours/user/customers/list

Aceita search (máx. 150 caracteres) e limit (1 a 500) como parâmetros opcionais de query.

Exemplo de Requisição ​

bash
curl -X GET "https://api.us.basis.tavares.in/v1/tours/user/customers/list" \
  -H "X-Tour-Id: 123e4567-e89b-12d3-a456-426614174000" \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"

Respostas ​

200 OK

Retorna um array com os clientes.

json
[
  {
    "value": 4,
    "label": "Cliente Doc"
  }
]

Obter Cliente por ID ​

Recupera os detalhes do cliente, já com preferências, documentos e tags relacionados.

http
GET /v1/tours/user/customers/:id

Parâmetros de Rota ​

NomeTipoObrigatórioDescrição
idnumberSimO ID do cliente.

Respostas ​

200 OK

Retorna o cliente com toursCustomerPreferences, toursCustomerDocuments e toursTags.

json
{
  "id": 4,
  "tourId": 1,
  "kind": "person",
  "fullName": "Cliente Doc",
  "legalName": null,
  "email": "doc.cliente@tours.dev",
  "phoneE164": "+5511987654321",
  "birthDate": "1990-05-15",
  "nationality": "BR",
  "residenceCountry": "BR",
  "preferredLocale": "pt-BR",
  "marketingOptIn": true,
  "marketingOptInAt": null,
  "notes": "Cliente criado pela documentação",
  "anonymizedAt": null,
  "createdAt": "2026-10-07T15:10:44.190-03:00",
  "updatedAt": "2026-10-07T15:10:44.190-03:00",
  "toursCustomerPreferences": [],
  "toursCustomerDocuments": [],
  "toursTags": []
}

404 Not Found

Ocorre quando o cliente não existe no estabelecimento.

Atualizar Cliente ​

Atualiza os dados do cliente. Exige customer.write.

http
PUT /v1/tours/user/customers/:id

Payload (Body) ​

Aceita os mesmos campos da criação, todos opcionais — envie apenas o que deve mudar. O e-mail continua único por estabelecimento, ignorando o próprio cliente.

Exemplo de Requisição ​

bash
curl -X PUT "https://api.us.basis.tavares.in/v1/tours/user/customers/4" \
  -H "X-Tour-Id: 123e4567-e89b-12d3-a456-426614174000" \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{
    "fullName": "Cliente Doc Editado",
    "notes": "Cliente editado pela documentação"
  }'

Respostas ​

204 No Content

Atualização concluída com sucesso.

422 Unprocessable Entity

Ocorre quando o e-mail informado já pertence a outro cliente do estabelecimento.

Sincronizar Tags ​

Substitui o conjunto de tags do cliente (sync N:N): as tags enviadas passam a ser exatamente as vinculadas. Exige customer.write.

http
PUT /v1/tours/user/customers/:id/tags

Payload (Body) ​

AtributoTipoObrigatórioDescrição
tagIdsnumber[]SimIDs das tags do estabelecimento (devem existir).

Exemplo de Requisição ​

bash
curl -X PUT "https://api.us.basis.tavares.in/v1/tours/user/customers/4/tags" \
  -H "X-Tour-Id: 123e4567-e89b-12d3-a456-426614174000" \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{ "tagIds": [1] }'

Respostas ​

204 No Content

Sincronização concluída com sucesso.

422 Unprocessable Entity

Ocorre quando algum tagId não existe no estabelecimento.

Remover Cliente ​

Remove um cliente via soft delete. Exige customer.write.

http
DELETE /v1/tours/user/customers/:id

Respostas ​

204 No Content

Remoção concluída com sucesso.

404 Not Found

Ocorre quando o cliente não existe no estabelecimento.


Preferências do Cliente ​

Preferências e restrições livres por cliente — alergia, dieta, quarto, serviço — classificadas por severidade. Uma alergia critical salta na tela do garçom no POS; warning e info aparecem como alertas discretos. O kind é texto livre (máx. 30 caracteres): convenções comuns são allergy, diet, room e service.

Listar Preferências ​

http
GET /v1/tours/user/customer-preferences

Parâmetros de Query ​

NomeTipoObrigatórioDescrição
pagenumberNãoO número da página (mínimo: 1).
perPagenumberNãoItens por página (entre 1 e 100).
tourCustomerIdnumberNãoFiltra por cliente.
kindstringNãoFiltra por tipo (máx. 30 caracteres).
severityenumNãoinfo, warning ou critical.
orderByenumNãoid, kind, severity ou createdAt.
orderDirectionenumNãoasc ou desc.

Respostas ​

200 OK

Retorna a página de preferências no formato meta/data.

json
{
  "meta": {
    "currentPage": 1,
    "perPage": 10
  },
  "data": [
    {
      "id": 1,
      "tourId": 1,
      "tourCustomerId": 1,
      "kind": "general",
      "value": "amita summisse ustilo",
      "severity": "info",
      "createdAt": "2026-10-07T11:56:14.538-03:00",
      "updatedAt": "2026-10-07T11:56:14.538-03:00"
    }
  ]
}

Criar Preferência ​

Exige customer.write.

http
POST /v1/tours/user/customer-preferences

Payload (Body) ​

AtributoTipoObrigatórioDescrição
tourCustomerIdnumberSimID do cliente (deve existir no estabelecimento).
kindstringSimTipo da preferência (máx. 30 caracteres).
valuestringSimDescrição (máx. 255 caracteres).
severityenumNãoinfo, warning ou critical (padrão: info).

Exemplo de Requisição ​

bash
curl -X POST "https://api.us.basis.tavares.in/v1/tours/user/customer-preferences" \
  -H "X-Tour-Id: 123e4567-e89b-12d3-a456-426614174000" \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{
    "tourCustomerId": 1,
    "kind": "allergy",
    "value": "frutos do mar",
    "severity": "critical"
  }'

Respostas ​

201 Created

Retorna o ID da preferência criada.

json
{
  "id": 4
}

Obter Preferência por ID ​

http
GET /v1/tours/user/customer-preferences/:id

Respostas ​

200 OK

Retorna a preferência.

json
{
  "id": 4,
  "tourId": 1,
  "tourCustomerId": 1,
  "kind": "allergy",
  "value": "frutos do mar",
  "severity": "critical",
  "createdAt": "2026-10-07T15:10:43.507-03:00",
  "updatedAt": "2026-10-07T15:10:43.508-03:00"
}

404 Not Found

Ocorre quando a preferência não existe no estabelecimento.

Atualizar Preferência ​

http
PUT /v1/tours/user/customer-preferences/:id

Aceita os mesmos campos da criação, todos opcionais. Exige customer.write.

Respostas ​

204 No Content

Atualização concluída com sucesso.

Remover Preferência ​

http
DELETE /v1/tours/user/customer-preferences/:id

Remove via soft delete. Exige customer.write. Responde 204 No Content.


Documentos do Cliente ​

Documentos de identificação (passaporte, RG, CNH) com número cifrado: numberCiphertext e numberFingerprint são enviados em base64 e gravados como binário — a API nunca trafega o número em claro. O encryptionKeyId referencia a chave do KMS usada na cifragem, permitindo rotação de chaves. O retainUntil marca a data limite de retenção para expurgo (LGPD).

Listar Documentos ​

Exige customer.document.read. A listagem omite o ciphertext/fingerprint — apenas metadados.

http
GET /v1/tours/user/customer-documents

Parâmetros de Query ​

NomeTipoObrigatórioDescrição
pagenumberNãoO número da página (mínimo: 1).
perPagenumberNãoItens por página (entre 1 e 100).
tourCustomerIdnumberNãoFiltra por cliente.
docTypestringNãoFiltra por tipo (máx. 30 caracteres).
orderByenumNãoid, docType ou createdAt.
orderDirectionenumNãoasc ou desc.

Respostas ​

200 OK

Retorna a página de documentos no formato meta/data.

json
{
  "meta": {
    "currentPage": 1,
    "perPage": 10
  },
  "data": [
    {
      "id": 1,
      "tourId": 1,
      "tourCustomerId": 1,
      "docType": "passport",
      "issuingCountry": "BR",
      "encryptionKeyId": "key-WbvhTgeo",
      "holderName": "Tyrel Barrows",
      "issuedOn": null,
      "expiresOn": null,
      "scanObjectKey": null,
      "retainUntil": null,
      "createdAt": "2026-10-07T11:56:14.585-03:00",
      "updatedAt": "2026-10-07T11:56:14.585-03:00"
    }
  ]
}

Criar Documento ​

Exige customer.write.

http
POST /v1/tours/user/customer-documents

Payload (Body) ​

AtributoTipoObrigatórioDescrição
tourCustomerIdnumberSimID do cliente (deve existir no estabelecimento).
docTypestringSimTipo do documento (máx. 30 caracteres, ex.: passport).
issuingCountrystringNãoPaís emissor, ISO alpha-2.
numberCiphertextstringSimNúmero cifrado, em base64.
numberFingerprintstringSimFingerprint do número, em base64 (para busca sem decifrar).
encryptionKeyIdstringSimID da chave do KMS (máx. 100 caracteres).
holderNamestringNãoNome do titular (máx. 150 caracteres).
issuedOndateNãoData de emissão (YYYY-MM-DD).
expiresOndateNãoData de validade (YYYY-MM-DD).
retainUntildateNãoRetenção até (YYYY-MM-DD) — referência para expurgo.
scanObjectKeystringNãoChave do objeto com o scan do documento (máx. 500).

Exemplo de Requisição ​

bash
curl -X POST "https://api.us.basis.tavares.in/v1/tours/user/customer-documents" \
  -H "X-Tour-Id: 123e4567-e89b-12d3-a456-426614174000" \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{
    "tourCustomerId": 1,
    "docType": "passport",
    "issuingCountry": "BR",
    "numberCiphertext": "dGVzdGU=",
    "numberFingerprint": "dGVzdGU=",
    "encryptionKeyId": "kms-demo-1",
    "holderName": "Cliente Doc",
    "issuedOn": "2020-01-10",
    "expiresOn": "2030-01-09"
  }'

Respostas ​

201 Created

Retorna o ID do documento criado.

json
{
  "id": 4
}

Obter Documento por ID ​

Exige customer.document.read. Retorna também o ciphertext e o fingerprint (serializados como buffer binário).

http
GET /v1/tours/user/customer-documents/:id

Respostas ​

200 OK

Retorna o documento completo.

json
{
  "id": 4,
  "tourId": 1,
  "tourCustomerId": 1,
  "docType": "passport",
  "issuingCountry": "BR",
  "numberCiphertext": { "type": "Buffer", "data": [116, 101, 115, 116, 101] },
  "numberFingerprint": { "type": "Buffer", "data": [116, 101, 115, 116, 101] },
  "encryptionKeyId": "kms-demo-1",
  "holderName": "Cliente Doc",
  "issuedOn": "2020-01-10",
  "expiresOn": "2030-01-09",
  "scanObjectKey": null,
  "retainUntil": null,
  "createdAt": "2026-10-07T15:10:42.549-03:00",
  "updatedAt": "2026-10-07T15:10:42.549-03:00"
}

404 Not Found

Ocorre quando o documento não existe no estabelecimento.

Atualizar Documento ​

http
PUT /v1/tours/user/customer-documents/:id

Aceita os mesmos campos da criação, todos opcionais. Exige customer.write. Responde 204 No Content.

Remover Documento ​

http
DELETE /v1/tours/user/customer-documents/:id

Remove via soft delete. Exige customer.write. Responde 204 No Content.


Tags ​

Tags classificam os clientes — vip, blacklist, corporate — e podem bloquear novas reservas (blocksBooking). Tags com isAutomatic são aplicadas pelo job de segmentação (ver Regras de Segmento) e não devem ser gerenciadas manualmente. O code é único por estabelecimento.

Listar Tags ​

http
GET /v1/tours/user/tags

Parâmetros de Query ​

NomeTipoObrigatórioDescrição
pagenumberNãoO número da página (mínimo: 1).
perPagenumberNãoItens por página (entre 1 e 100).
searchstringNãoBusca por código ou nome.
blocksBookingbooleanNãoFiltra por tags que bloqueiam reserva.
isAutomaticbooleanNãoFiltra por tags automáticas.
orderByenumNãoid, code, name ou createdAt.
orderDirectionenumNãoasc ou desc.

Respostas ​

200 OK

Retorna a página de tags no formato meta/data.

json
{
  "meta": {
    "currentPage": 1,
    "perPage": 10
  },
  "data": [
    {
      "id": 1,
      "tourId": 1,
      "code": "2sxn3bgqzt",
      "name": "Movies",
      "color": "#3B82F6",
      "blocksBooking": false,
      "isAutomatic": false,
      "createdAt": "2026-10-07T11:56:14.602-03:00",
      "updatedAt": "2026-10-07T11:56:14.602-03:00"
    }
  ]
}

Criar Tag ​

Exige customer.write.

http
POST /v1/tours/user/tags

Payload (Body) ​

AtributoTipoObrigatórioDescrição
codestringSimCódigo único no estabelecimento (máx. 50).
namestringSimNome de exibição (máx. 150 caracteres).
colorstringNãoCor em hexadecimal (máx. 20 caracteres).
blocksBookingbooleanNãoBloqueia novas reservas do cliente (padrão: false).
isAutomaticbooleanNãoGerenciada pelo job de segmentação (padrão: false).

Exemplo de Requisição ​

bash
curl -X POST "https://api.us.basis.tavares.in/v1/tours/user/tags" \
  -H "X-Tour-Id: 123e4567-e89b-12d3-a456-426614174000" \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{
    "code": "DOC-VIP",
    "name": "VIP Doc",
    "color": "#FFD700",
    "blocksBooking": false,
    "isAutomatic": false
  }'

Respostas ​

201 Created

Retorna o ID da tag criada.

json
{
  "id": 4
}

422 Unprocessable Entity

Ocorre quando o code já existe no estabelecimento ou o payload é inválido.

Listar para Dropdown ​

http
GET /v1/tours/user/tags/list

Aceita search e limit (1 a 500) como parâmetros opcionais de query.

Respostas ​

200 OK

Retorna um array value/label.

json
[
  {
    "value": 1,
    "label": "Movies"
  },
  {
    "value": 4,
    "label": "VIP Doc"
  }
]

Obter Tag por ID ​

http
GET /v1/tours/user/tags/:id

Respostas ​

200 OK

Retorna a tag com suas regras de segmento (toursSegmentRules).

json
{
  "id": 4,
  "tourId": 1,
  "code": "DOC-VIP",
  "name": "VIP Doc",
  "color": "#FFD700",
  "blocksBooking": false,
  "isAutomatic": false,
  "createdAt": "2026-10-07T15:11:15.527-03:00",
  "updatedAt": "2026-10-07T15:11:15.527-03:00",
  "toursSegmentRules": []
}

404 Not Found

Ocorre quando a tag não existe no estabelecimento.

Atualizar Tag ​

http
PUT /v1/tours/user/tags/:id

Aceita os mesmos campos da criação, todos opcionais. Exige customer.write. Responde 204 No Content.

Remover Tag ​

http
DELETE /v1/tours/user/tags/:id

Remove via soft delete. Exige customer.write. Responde 204 No Content.


Regras de Segmento ​

A segmentação é declarativa: cada regra vincula uma tag (tourTagId) a uma definition de forma livre (objeto JSON com propriedades desconhecidas permitidas — ex.: { "lifetime_value_min": 5000 } ou { "field": "email", "operator": "contains", "value": "@test.com" }). Um job executa as regras ativas periodicamente, aplicando/removendo a tag nos clientes que atendem à definição e registrando lastRunAt.

Listar Regras de Segmento ​

http
GET /v1/tours/user/segment-rules

Parâmetros de Query ​

NomeTipoObrigatórioDescrição
pagenumberNãoO número da página (mínimo: 1).
perPagenumberNãoItens por página (entre 1 e 100).
searchstringNãoBusca por nome.
tourTagIdnumberNãoFiltra por tag.
isActivebooleanNãoFiltra por regras ativas/inativas.
orderByenumNãoid, name ou createdAt.
orderDirectionenumNãoasc ou desc.

Respostas ​

200 OK

Retorna a página de regras no formato meta/data.

json
{
  "meta": {
    "currentPage": 1,
    "perPage": 10
  },
  "data": [
    {
      "id": 1,
      "tourId": 1,
      "tourTagId": 1,
      "name": "Sports",
      "definition": {
        "field": "email",
        "value": "@test.com",
        "operator": "contains"
      },
      "isActive": true,
      "lastRunAt": null,
      "createdAt": "2026-10-07T11:56:14.614-03:00",
      "updatedAt": "2026-10-07T11:56:14.614-03:00"
    }
  ]
}

Criar Regra de Segmento ​

Exige customer.write.

http
POST /v1/tours/user/segment-rules

Payload (Body) ​

AtributoTipoObrigatórioDescrição
tourTagIdnumberSimID da tag aplicada pela regra (deve existir).
namestringSimNome da regra (máx. 150 caracteres).
definitionobjectSimDefinição declarativa (propriedades livres).
isActivebooleanNãoIndica se a regra roda no job (padrão: true).

Exemplo de Requisição ​

bash
curl -X POST "https://api.us.basis.tavares.in/v1/tours/user/segment-rules" \
  -H "X-Tour-Id: 123e4567-e89b-12d3-a456-426614174000" \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{
    "tourTagId": 1,
    "name": "Alto valor Doc",
    "definition": {
      "lifetime_value_min": 5000
    },
    "isActive": true
  }'

Respostas ​

201 Created

Retorna o ID da regra criada.

json
{
  "id": 4
}

Obter Regra por ID ​

http
GET /v1/tours/user/segment-rules/:id

Respostas ​

200 OK

Retorna a regra com a tag vinculada (toursTag).

json
{
  "id": 4,
  "tourId": 1,
  "tourTagId": 1,
  "name": "Alto valor Doc",
  "definition": {
    "lifetime_value_min": 5000
  },
  "isActive": true,
  "lastRunAt": null,
  "createdAt": "2026-10-07T15:11:08.004-03:00",
  "updatedAt": "2026-10-07T15:11:08.004-03:00",
  "toursTag": {
    "id": 1,
    "code": "2sxn3bgqzt",
    "name": "Movies"
  }
}

404 Not Found

Ocorre quando a regra não existe no estabelecimento.

Atualizar Regra de Segmento ​

http
PUT /v1/tours/user/segment-rules/:id

Aceita os mesmos campos da criação, todos opcionais. Exige customer.write. Responde 204 No Content.

Remover Regra de Segmento ​

http
DELETE /v1/tours/user/segment-rules/:id

Remove via soft delete. Exige customer.write. Responde 204 No Content.