Enviar seus dados empresariais
A Kaleidr pode responder perguntas usando os próprios dados da sua organização — suas propriedades, listagens, quartos, tarifas, horários de funcionamento e documentos — juntamente com seu conhecimento básico do mundo.
Duas coisas merecem ser declaradas antes de qualquer outra, porque moldam todas as decisões abaixo.
Seus dados são fornecidos apenas de volta à sua organização. Eles ficam isolados no nível do banco de dados, não pela lógica da aplicação, e nunca chegam a uma resposta no Kaleidr Map para consumidores. Eles ficam disponíveis apenas nas suas próprias superfícies B2B.
Um modelo de linguagem nunca escreve seus dados. Ele lê o header da sua exportação e algumas sample rows e propõe um column mapping; depois, código determinístico aplica esse mapping a cada row. Um mapping incorreto é uma correção que você faz em um formulário. Fazer um modelo transcrever 500 linhas criaria 500 chances de inventar um preço que mais tarde poderia ser citado com um timestamp convincente, e um preço inventado seria indistinguível de um real.
Disponibilidade
O upload de vendor data é um recurso do Enterprise-tier. A UI de upload e a
API verificam VENDOR_UPLOAD_TIERS = {"enterprise"} — um owner ou admin Pro-tier
recebe 403 vendor_data_requires_enterprise em qualquer chamada de upload.
A vendor-data UI está atualmente desativada em production (vendorDataEnabled
config flag). Entre em contato com o suporte da Kaleidr se você
estiver no Enterprise e precisar ativá-la para sua organização.
Além disso, é necessário um papel de owner ou admin no Enterprise — estes são dados em nível de organização, não por projeto.
Duas formas de entrada
A página de upload. Entre em kaleidr.com e abra
Your Data na área da sua conta (nav path /vendor-data, ao lado de Billing
e API keys). Ela percorre os mesmos quatro passos da API: escolher um arquivo, revisar
o mapping proposto, visualizar o que foi entendido e publicar. Esse é o
caminho adequado para uma planilha.
A API, documentada abaixo. Use-a quando seus dados já estiverem em um sistema capaz de fazer push ou quando você quiser agendar uploads.
Autenticação
Todas as chamadas recebem um access token Cognito como bearer, o mesmo que sua session já mantém:
Authorization: Bearer <access token>
Não uma platform API key. Platform keys identificam uma integração; enviar dados
é uma ação de administração da organização, portanto a autenticação ocorre como uma pessoa com
um papel. Todos os paths abaixo estão em https://api.kaleidr.com.
Estrutura de um upload
Um upload produz um ingest (o job) e um release (o resultado
versionado). Um release permanece draft até ser publicado, e a publicação substitui
atomicamente o anterior — os leitores nunca veem uma atualização parcialmente aplicada e não existe
nenhum período em que sua organização fique sem dados.
1. Propor um mapping
Envie o início do seu arquivo — a linha do header e algumas linhas de dados, não toda a exportação.
| Method | Path | Body | Returns |
|---|---|---|---|
| POST | /inference-api/vendor/mapping/propose | { csv_head } | { mapping_spec, columns, sample_result, notes, errors[] } |
csv_head é limitado a 16 KB e o sample é recortado server-side — enviar
um arquivo maior não amplia o que o modelo vê.
sample_result é a parte que deve ser lida. O mapping proposto passa por um dry-run nas suas
próprias sample rows antes mesmo de ser exibido, e sample_result relata o que ele
produziu em cada seção. Um mapping que parece plausível e não produz nada
seria algo que você talvez descobrisse somente depois do upload.
Se a proposta não puder ser aplicada, você ainda recebe 200 com errors preenchido,
não um 5xx. O mapping é editável e corrigir uma coluna é toda a
interação. errors também relata tudo o que pode ser identificado de uma vez — um campo
obrigatório ausente e um nome de coluna inexistente na sua planilha chegam juntos,
em vez de um por round trip.
O que é detectado antes do upload: uma seção sem um campo necessário em todas as linhas
(stay_date, price_amount, units_available, o name ou
timezone de um lugar), uma timezone {"const": …} que não é uma zona IANA real, uma currency
const que não possui três letras e qualquer regra de objeto que não seja um container const.
Caso contrário, cada um desses casos falharia uma vez por linha depois do upload.
Limitado a 30 propostas por usuário por hora.
2. Preparar uma preview
| Method | Path | Body | Returns |
|---|---|---|---|
| POST | /shared-api/vendor-data/ingests | { filename, artifact, source, mapping_spec?, preview?, org_id? } | { ingest_id, release_id, status, status_url, dispatched } |
filenamedeve terminar em.jsonou.csv.artifacté o texto bruto do arquivo.sourceécsv,jsonoumanual.mapping_specé o retorno da etapa 1, opcionalmente editado. Omita-o se estiver enviando um bundle JSON já normalizado ou um CSV somente de places.preview: trueprepara sem publicar — altamente recomendado para um primeiro upload e para qualquer mudança no mapping.org_idé opcional; o padrão é a organização que você administra.
Idempotency-Key é obrigatório nesta chamada (8–128 caracteres) e seu escopo
é por organização. Repetir com a mesma chave retorna o ingest existente
em vez de criar um segundo. Use uma chave nova quando deliberadamente
preparar novamente após editar um mapping — é realmente uma solicitação diferente, e uma
chave derivada do arquivo devolveria o ingest construído com o mapping antigo.
3. Acompanhar
| Method | Path | Returns |
|---|---|---|
| GET | /shared-api/vendor-data/ingests/{ingest_id} | { status, attempts, row_counts, error_report, created_at, started_at, finished_at } |
status muda de pending → running → succeeded ou failed. Em caso de sucesso,
row_counts contém o que foi entendido — "47 places, 312 rates" — e
error_report contém as linhas que não puderam ser lidas, com o motivo de cada uma.
4. Publicar
| Method | Path | Returns |
|---|---|---|
| POST | /shared-api/vendor-data/ingests/{ingest_id}/publish | { ingest_id, release_id, status, status_url, dispatched } |
Somente para um ingest preparado com preview: true que tenha sido concluído com sucesso.
Publicar executa o job novamente em vez de apenas alterar um flag. Ele relê o mesmo artifact e reaplica o mesmo mapping, de modo que counts e identifiers correspondem por construção — mas geocoding é uma chamada live, então uma coordinate pode ser diferente se o provider a corrigiu desde sua preview.
Não envie um Idempotency-Key aqui. Este endpoint não aceita um,
e não precisa: uma segunda publicação do mesmo ingest não pode acontecer. Se
sua primeira solicitação expirou do seu lado mas foi concluída no nosso, a nova tentativa
retorna 409 — ingest_is_not_a_preview, ou publish_already_in_progress se
duas tentativas se sobrepuserem exatamente. Ambos significam que sua publicação já está em andamento.
Trate-os como sucesso, não como um erro a ser repetido.
Listar releases
| Method | Path | Returns |
|---|---|---|
| GET | /shared-api/vendor-data/releases | [{ id, status, published_at, superseded_at, created_at }] |
Opcionalmente filtrado por ?status=. Exatamente um release por organização fica
published por vez.
Previews expiram
Uma preview nunca aprovada é retirada após 14 dias, contados a partir de quando
terminou o staging. Ela é marcada como superseded em vez de excluída, portanto o upload
permanece no histórico — mas não pode mais ser publicado e você precisaria fazer o upload
novamente. Publicar uma preview expirada retorna 409 no_previewed_release_to_publish.
Observações sobre campos
timezone é obrigatório em todos os places e é importante. Respostas de rate e availability
são calculadas no calendário local da propriedade — "tonight" em um hotel em Sydney
pode ser um dia diferente de "tonight" no server. Se sua exportação realmente
não tiver uma coluna timezone, mapeie explicitamente uma constante:
{ "timezone": { "const": "UTC" } }
Faça isso deliberadamente, em vez de deixar como default. UTC é uma resposta correta para uma propriedade que opera em horário UTC e sutilmente errada para uma propriedade que não opera; o erro só aparece nas bordas de uma stay window.
Omitir timezone ou indicar uma zone inexistente é rejeitado já na etapa
propose, e não depois do upload.
Forneça coordinates quando as tiver. Um place com lat/lng é utilizado exatamente
como fornecido — suas coordinates são autoritativas e não serão recalculadas. Um
place que tenha apenas address é geocodificado, e uma correspondência em que não confiamos é
recusada em vez de adivinhada: posicionar uma propriedade incorretamente em um mapa é pior do que
informá-la como não resolvível. Metade de uma coordinate é tratada como erro de digitação, não como ausência.
Reenviar é barato e seguro. Os identifiers são derivados das colunas que seu mapping define como identificadoras, portanto a mesma exportação gera as mesmas referências — reenviar atualiza em vez de duplicar.
Erros
| Status | Meaning |
|---|---|
| 401 | Access token ausente ou expirado |
403 vendor_data_requires_enterprise | A organização não está no Enterprise tier |
| 403 | Sua organização não está habilitada para upload de dados |
| 404 | Não existe esse ingest para sua organização |
| 409 | O ingest não está em um estado que permite esta chamada — consulte as observações de publicação acima |
| 413 | O arquivo excede o limite de upload |
| 422 | O arquivo ou mapping não pôde ser lido; o body informa as linhas e os motivos |
| 429 | Rate limited — tente novamente após uma pausa |
O que vem a seguir
Atualmente a API aceita um bundle completo. Quando um mapping se tornar um objeto armazenado e reutilizável,
também aceitará sua própria exportação mais um mapping id, permitindo que uma
integração envie o arquivo que já produz sem remodelá-lo primeiro.
Uma delta API — upsert e delete por natural key, com cursor since — seguirá
o mesmo caminho.