Your AI Connector Docs

Marcações

A API de Marcações permite-lhe marcar reuniões para os seus contactos nos seus tipos de evento, e depois obtê-las, listá-las, atualizá-las, cancelá-las ou eliminá-las. Também responde à pergunta que surge primeiro na maioria dos fluxos de marcação — que horários estão realmente livres — e cobre a parte do calendário: listar os Google Calendars que tem ligados e importar eventos que já existem neles. Quando uma ligação ao Google Calendar está ativa, o evento de calendário correspondente é criado e mantido sincronizado automaticamente em segundo plano. Os restaurantes que utilizam Zenchef, Formitable, OpenTable ou TheFork para o seu próprio sistema de reservas também podem ser verificados e ligados aqui, para que o Agente de IA reserve mesas reais em vez de marcações internas — e as empresas de marcações que gerem a sua agenda no Trafft podem ligar-se da mesma forma.

Todos os caminhos nesta página são relativos ao URL base https://api.youraiconnector.com/v1. Cada pedido necessita da sua chave de API — consulte Autenticação para obter a lista completa de formas de a enviar. Os exemplos abaixo utilizam o cabeçalho X-API-Key, com um exemplo cURL que mostra também o formulário de consulta ?apiKey=.

Eventos vs. marcações: Um tipo de evento é uma definição de espaço reservável (o tipo de reunião, a sua duração, as suas salas). Uma marcação é uma instância reservada de um tipo de evento para um contacto específico. Reserva uma marcação referenciando o contacto e o tipo de evento.


O objeto de marcação

Cada endpoint que devolve uma marcação utiliza a mesma estrutura:

Campo Descrição
id ID único do agendamento.
contact_id ID do contacto com quem o agendamento foi marcado.
event_id ID do tipo de evento no qual o agendamento foi marcado. null para agendamentos externos — agendamentos registados sem um tipo de evento.
status Confirmed ou Canceled.
start_time Início do agendamento, ISO 8601 em UTC.
end_time Fim do agendamento, ISO 8601 em UTC.
created_at Quando o agendamento foi criado.
last_modified_at Quando o agendamento foi alterado pela última vez.
room_name Sala ou recurso onde o agendamento foi marcado, quando o tipo de evento utiliza salas.
description Descrição livre do agendamento.
summary Resumo ou título curto. Para um agendamento externo, este é o title com o qual foi registado.
external_reference O seu próprio ID para este agendamento (do seu CRM ou sistema de reservas), conforme o enviou, ou null.
cancelation_reason Motivo fornecido quando o agendamento foi cancelado, se existir.
google_calendar_event_id ID do evento do Google Calendar associado. Definido assim que a sincronização do calendário for concluída; null quando nenhum calendário está ligado ou enquanto a sincronização ainda está em curso.
calendar_synced true assim que o agendamento estiver associado a um evento de calendário.
imported true quando o agendamento foi importado de um calendário externo em vez de marcado diretamente.
is_recurring true quando o agendamento faz parte de uma série recorrente.
recurrence_frequency Com que frequência o agendamento se repete, quando recorrente.
recurring_event_id ID da série recorrente a que este agendamento pertence.
recurring_interval Intervalo entre repetições, quando recorrente.
recurring_sequence Posição deste agendamento dentro da sua série recorrente.
end_after_x_occurrences Número de ocorrências após as quais a série recorrente termina.
booking_provider Sistema de origem de onde veio a reserva, quando marcada através de um fornecedor de reservas ligado.

Sobre a sincronização de calendário: Logo após reservar ou alterar uma marcação, o google_calendar_event_id pode ainda ser null e o calendar_synced pode ser false porque a sincronização é executada em segundo plano um momento depois. Obtenha a marcação novamente pouco depois para ver os campos de calendário preenchidos.


Encontrar horários disponíveis

GET /appointments/available-slots

Devolve os horários que estão genuinamente livres num tipo de evento entre dois momentos. Esta é normalmente a primeira chamada num fluxo de marcação: mostre estes horários, deixe a pessoa escolher um e, em seguida, envie a hora escolhida para Marcar um compromisso.

A resposta já tem em conta o horário de funcionamento e a duração dos intervalos do próprio tipo de evento, as suas salas, as marcações que já efetuou nele e tudo o que está bloqueado nos Google Calendars ligados — por isso, um horário que aparece aqui é um horário que pode marcar.

Parâmetro de consulta Obrigatório Descrição
event_id Sim O tipo de evento a verificar. Deve pertencer à sua conta. Encontre-o na aplicação abrindo o tipo de evento na página Agendamentos (separador Tipos de Evento): a janela de edição mostra o respetivo ID do tipo de evento com um botão de cópia.
start_time Sim Início da janela para a qual pretende horários, data e hora em formato ISO 8601.
end_time Sim Fim da janela, data e hora em formato ISO 8601. O dia final completo está incluído.

Os resultados são devolvidos agrupados por dia — e, quando o tipo de evento utiliza salas, um grupo por sala por dia:

Campo Descrição
date O dia que o grupo cobre, escrito DD/MM/YYYY.
day Nome do dia da semana em minúsculas, por exemplo monday.
room_name A sala ou recurso a que este grupo pertence, quando o tipo de evento utiliza salas.
available_slots Os blocos marcáveis nesse dia, do mais cedo para o mais tarde.

Cada entrada em available_slots tem:

Campo Descrição
start_time Início do bloco como HH:mm.
end_time Fim do bloco como HH:mm.
available true — apenas é devolvido tempo livre.
spots_left Quantas marcações ainda cabem neste bloco. Apenas presente em tipos de evento que aceitam mais do que uma marcação por intervalo.

Os horários são locais ao tipo de evento, não UTC. date, start_time e end_time são valores de relógio de parede no fuso horário do próprio tipo de evento (a sua substituição, ou o fuso horário da sua conta quando não tem nenhum). Marcar um compromisso espera um instante UTC ISO 8601, por isso converta o horário que escolheu antes de o enviar.

cURL

curl "https://api.youraiconnector.com/v1/appointments/available-slots?event_id=event_xyz789&start_time=2026-06-15T00:00:00.000Z&end_time=2026-06-19T00:00:00.000Z" \
  -H "X-API-Key: YOUR_API_KEY"

JavaScript

const params = new URLSearchParams({
  event_id: "event_xyz789",
  start_time: "2026-06-15T00:00:00.000Z",
  end_time: "2026-06-19T00:00:00.000Z",
});
const res = await fetch(
  `https://api.youraiconnector.com/v1/appointments/available-slots?${params}`,
  { headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const data = await res.json();
console.log(data.data);

Python

import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/appointments/available-slots",
    headers={"X-API-Key": "YOUR_API_KEY"},
    params={
        "event_id": "event_xyz789",
        "start_time": "2026-06-15T00:00:00.000Z",
        "end_time": "2026-06-19T00:00:00.000Z",
    },
)
print(res.json()["data"])

Resposta (200 OK):

{
  "success": true,
  "data": [
    {
      "date": "15/06/2026",
      "day": "monday",
      "room_name": "Room A",
      "available_slots": [
        { "start_time": "10:00", "end_time": "10:30", "available": true },
        { "start_time": "10:30", "end_time": "11:00", "available": true }
      ]
    },
    {
      "date": "16/06/2026",
      "day": "tuesday",
      "room_name": "Room A",
      "available_slots": [
        { "start_time": "09:00", "end_time": "09:30", "available": true, "spots_left": 2 }
      ]
    }
  ]
}

Um dia sem nada livre simplesmente não aparece. A falta de event_id, start_time ou end_time devolve 400; um tipo de evento que não está na sua conta devolve 404.


Reservar uma marcação

POST /appointments

Cria um agendamento para um dos seus contactos. Existem duas formas de o utilizar:

  • Num dos seus tipos de evento — envie event_id, e a reserva funciona exatamente como sempre funcionou: a disponibilidade e a capacidade são respeitadas, a hora de fim é calculada a partir da duração do intervalo do tipo de evento e o agendamento é sincronizado com o seu Google Calendar quando um estiver ligado.
  • Como um agendamento externo — deixe event_id de fora e envie um title em vez disso. Isto regista uma reserva que foi feita noutro local (o seu próprio CRM, um horário de aulas, outra ferramenta de reservas) para que apareça na página de Agendamentos juntamente com os restantes.

Uma marcação num tipo de evento com salas deve ser feita para uma hora que Encontrar horários disponíveis ofereceria: dentro do horário da sala, fora do período de aviso prévio, dentro do limite de antecedência com que o tipo de evento pode ser marcado, na grelha de horários, não no passado e não bloqueada num calendário ligado. Qualquer outra hora é recusada com um 400 e nada é criado. O mesmo acontece com uma room_name que não corresponda a nenhuma das salas do tipo de evento (a mensagem lista os nomes válidos). Os tempos de intervalo definidos no tipo de evento (Intervalo antes e Intervalo depois no editor de tipos de evento, buffer_before e buffer_after em minutos) são mantidos livres em torno de cada marcação.

Uma marcação num tipo de evento também é verificada quanto a conflitos: se o horário já estiver ocupado, o pedido falha com um 409 e nada é criado. Uma marcação externa não tem um tipo de evento associado, por isso nada é verificado em relação à sua disponibilidade ou capacidade e nada é sincronizado com um calendário.

Tentar novamente é seguro. Se o mesmo contacto já tiver uma marcação confirmada no mesmo tipo de evento no mesmo início (na mesma sala, quando nomeia uma), por exemplo, porque o seu primeiro pedido expirou após ter sido processado, recebe essa marcação de volta com um 200 e "replayed": true em vez de uma segunda marcação ou um 409.

Um external_reference funciona como uma chave de idempotência. É único na sua conta: se um agendamento já tiver a referência que enviou, esse agendamento é devolvido com um 200 e "replayed": true e nada de novo é criado, mesmo quando a nova tentativa indica uma hora ou contacto diferente e independentemente do estado desse agendamento. Utilize-o para reservas pagas (envie o seu ID de pagamento ou de encomenda) e envie uma nova referência para uma reserva genuinamente nova.

Campo Obrigatório Descrição
contact_id Sim ID do contacto para o qual efetuar a reserva. Deve pertencer à sua conta.
start_time Sim Início pretendido como data-hora ISO 8601. Uma hora enviada sem desfasamento de fuso horário é lida no fuso horário da sua conta.
event_id Não ID do tipo de evento para o qual efetuar a reserva. Deve pertencer à sua conta. Deixe em branco para registar uma reserva externa.
title Apenas sem event_id O nome sob o qual o agendamento é apresentado na página de Agendamentos — o nome da aula, por exemplo. Até 200 caracteres. É devolvido como summary.
end_time Não Fim de uma reserva externa como data-hora ISO 8601, posterior a start_time. Não é necessário com um event_id: a hora de fim provém então da duração do intervalo do tipo de evento.
duration_minutes Não Duração de uma reserva externa, um número inteiro de minutos de 1 a 1440. Utilize este ou end_time, não ambos. Sem nenhum, uma reserva externa dura 60 minutos.
description Não Notas de formato livre para manter com o agendamento.
room_name Não Nome da sala ou recurso, quando o tipo de evento utiliza salas. Deve corresponder a uma das suas salas. Deixe em branco para reservar a primeira sala livre.
external_reference Não O seu próprio ID para esta reserva, para que possa associá-la ao registo no seu CRM ou sistema de reservas. Até 255 caracteres. É devolvido em cada leitura e nos webhooks de Agendamento Reservado, Cancelado e Reagendado. Único na sua conta: uma referência que já esteja a ser utilizada devolve esse agendamento em vez de reservar novamente (ver acima).

Envie event_id e title em conjunto, ou nenhum dos dois, e o pedido devolve um 400 — tal como o envio de ambos end_time e duration_minutes.

cURL (utilizando o formulário de consulta ?apiKey=)

curl -X POST "https://api.youraiconnector.com/v1/appointments?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "contact_id": "contact_abc123",
    "event_id": "event_xyz789",
    "start_time": "2026-06-15T10:00:00.000Z",
    "room_name": "Room A"
  }'

JavaScript

const res = await fetch("https://api.youraiconnector.com/v1/appointments", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    contact_id: "contact_abc123",
    event_id: "event_xyz789",
    start_time: "2026-06-15T10:00:00.000Z",
    room_name: "Room A",
  }),
});
const data = await res.json();
console.log(data.appointment_id);

Python

import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/appointments",
    headers={
        "X-API-Key": "YOUR_API_KEY",
        "Content-Type": "application/json",
    },
    json={
        "contact_id": "contact_abc123",
        "event_id": "event_xyz789",
        "start_time": "2026-06-15T10:00:00.000Z",
        "room_name": "Room A",
    },
)
print(res.json()["appointment_id"])

Resposta (201 Created):

{
  "success": true,
  "appointment_id": "aBcD1234eFgH5678",
  "appointment": {
    "id": "aBcD1234eFgH5678",
    "contact_id": "contact_abc123",
    "event_id": "event_xyz789",
    "status": "Confirmed",
    "start_time": "2026-06-15T10:00:00.000Z",
    "end_time": "2026-06-15T10:30:00.000Z",
    "created_at": "2026-06-10T09:00:00.000Z",
    "last_modified_at": "2026-06-10T09:00:00.000Z",
    "room_name": "Room A",
    "google_calendar_event_id": null,
    "calendar_synced": false
  }
}

Registar uma reserva feita noutro local

O mesmo endpoint, sem um tipo de evento: um title e um start_time são suficientes, e duration_minutes define quanto tempo dura.

cURL

curl -X POST "https://api.youraiconnector.com/v1/appointments" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "contact_id": "contact_abc123",
    "title": "Beginner guitar class",
    "start_time": "2026-06-15T10:00:00.000Z",
    "duration_minutes": 90,
    "external_reference": "class-slot-4812"
  }'

JavaScript

const res = await fetch("https://api.youraiconnector.com/v1/appointments", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    contact_id: "contact_abc123",
    title: "Beginner guitar class",
    start_time: "2026-06-15T10:00:00.000Z",
    duration_minutes: 90,
  }),
});
const data = await res.json();
console.log(data.appointment_id);

Python

import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/appointments",
    headers={
        "X-API-Key": "YOUR_API_KEY",
        "Content-Type": "application/json",
    },
    json={
        "contact_id": "contact_abc123",
        "title": "Beginner guitar class",
        "start_time": "2026-06-15T10:00:00.000Z",
        "duration_minutes": 90,
    },
)
print(res.json()["appointment_id"])

Resposta (201 Created):

{
  "success": true,
  "appointment_id": "eFgH5678aBcD1234",
  "appointment": {
    "id": "eFgH5678aBcD1234",
    "contact_id": "contact_abc123",
    "event_id": null,
    "status": "Confirmed",
    "start_time": "2026-06-15T10:00:00.000Z",
    "end_time": "2026-06-15T11:30:00.000Z",
    "created_at": "2026-06-10T09:00:00.000Z",
    "last_modified_at": "2026-06-10T09:00:00.000Z",
    "summary": "Beginner guitar class",
    "google_calendar_event_id": null,
    "calendar_synced": false
  }
}

Os agendamentos externos são agendamentos comuns a partir daí: aparecem na página de Agendamentos e em Listar agendamentos, podem ser reagendados, cancelados ou eliminados na aplicação ou através desta API, o e-mail de notificação de agendamento é enviado como habitualmente, e o acionador de automatização Agendamento marcado e o webhook são disparados para eles como para qualquer outra reserva feita através da API. As únicas diferenças são as mencionadas acima — sem verificação de disponibilidade ou capacidade, sem sincronização de calendário, e event_id permanece null.


Obter um agendamento

GET /appointments/{appointmentId}

Devolve um único agendamento pelo seu ID, incluindo o seu estado de sincronização de calendário.

cURL

curl "https://api.youraiconnector.com/v1/appointments/aBcD1234eFgH5678" \
  -H "X-API-Key: YOUR_API_KEY"

JavaScript

const res = await fetch(
  "https://api.youraiconnector.com/v1/appointments/aBcD1234eFgH5678",
  { headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const data = await res.json();
console.log(data.appointment);

Python

import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/appointments/aBcD1234eFgH5678",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
print(res.json()["appointment"])

Resposta (200 OK):

{
  "success": true,
  "appointment": {
    "id": "aBcD1234eFgH5678",
    "contact_id": "contact_abc123",
    "event_id": "event_xyz789",
    "status": "Confirmed",
    "start_time": "2026-06-15T10:00:00.000Z",
    "end_time": "2026-06-15T10:30:00.000Z",
    "room_name": "Room A",
    "google_calendar_event_id": "abc123googleevent",
    "calendar_synced": true
  }
}

Listar agendamentos

GET /appointments

Lista os agendamentos da sua conta, do mais recente para o mais antigo, com paginação baseada em cursor.

Parâmetro de consulta Obrigatório Descrição
contact_id Não Devolve apenas agendamentos para este contacto. As listagens filtradas por contacto incluem apenas agendamentos confirmados
date Não Devolve apenas agendamentos neste dia de calendário (YYYY-MM-DD). Requer contact_id.
status Não Filtrar por Confirmed ou Canceled. Disponível apenas sem contact_id.
limit Não Tamanho da página, um número inteiro entre 1 e 100. Predefinição 50.
cursor Não O valor next_cursor de uma resposta anterior.

Algumas regras a ter em conta:

  • Sem filtros, obtém todos os agendamentos da conta, página a página.
  • Por contacto — defina contact_id para ver os agendamentos confirmados de um contacto. Pode restringir a um único dia passando também date.
  • Por estado — defina status (sem contact_id) para listar apenas agendamentos Confirmed ou apenas Canceled em toda a conta.
  • O filtro date sem contact_id, ou status=Canceled juntamente com contact_id, devolve um 400.

cURL

curl "https://api.youraiconnector.com/v1/appointments?contact_id=contact_abc123&date=2026-06-15" \
  -H "X-API-Key: YOUR_API_KEY"

JavaScript

const params = new URLSearchParams({
  contact_id: "contact_abc123",
  date: "2026-06-15",
});
const res = await fetch(
  `https://api.youraiconnector.com/v1/appointments?${params}`,
  { headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const data = await res.json();
console.log(data.appointments, data.next_cursor);

Python

import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/appointments",
    headers={"X-API-Key": "YOUR_API_KEY"},
    params={"contact_id": "contact_abc123", "date": "2026-06-15"},
)
data = res.json()
print(data["appointments"], data["next_cursor"])

Resposta (200 OK):

{
  "success": true,
  "appointments": [
    {
      "id": "aBcD1234eFgH5678",
      "contact_id": "contact_abc123",
      "event_id": "event_xyz789",
      "status": "Confirmed",
      "start_time": "2026-06-15T10:00:00.000Z",
      "end_time": "2026-06-15T10:30:00.000Z",
      "calendar_synced": true
    }
  ],
  "next_cursor": null
}

Para navegar entre os resultados, passe o next_cursor de uma resposta como o cursor do pedido seguinte. Continue até que next_cursor seja null. Consulte Erros e Paginação para o padrão de paginação partilhado.


Atualizar um agendamento

PUT /appointments/{appointmentId}

Reagende um compromisso ou altere os seus detalhes. Envie apenas os campos que pretende alterar — é necessário pelo menos um. O início e o fim combinados devem manter-se por ordem cronológica (end_time deve ser posterior a start_time). As alterações são sincronizadas automaticamente com o evento do calendário associado.

Mover uma marcação confirmada num tipo de evento (um novo start_time ou room_name) é verificado quanto a conflitos tal como uma nova marcação: um horário que já esteja ocupado responde 409 e nada muda, e uma room_name que não corresponda a nenhuma das salas do tipo de evento responde 400. Envie apenas start_time e a marcação mantém a sua duração. O seu próprio horário de funcionamento e período de aviso prévio não são aplicados aqui, pelo que ainda pode mover uma marcação para qualquer hora livre.

Campo Descrição
start_time Novo início, data-hora ISO 8601. Uma hora enviada sem desfasamento de fuso horário é lida no fuso horário do tipo de evento (ou da sua conta), da mesma forma que ao reservar.
end_time Novo fim, data-hora ISO 8601, lido da mesma forma. Deve ser posterior à hora de início.
room_name Novo nome de sala ou recurso.
description Nova descrição, ou null para a limpar.
summary Novo resumo, ou null para o limpar.
external_reference Nova referência (até 255 caracteres), ou null para a limpar. Uma referência que outro agendamento já possua é recusada com um 409 e "code": "external_reference_taken".

cURL

curl -X PUT "https://api.youraiconnector.com/v1/appointments/aBcD1234eFgH5678" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "start_time": "2026-06-16T10:00:00.000Z",
    "end_time": "2026-06-16T10:30:00.000Z"
  }'

JavaScript

const res = await fetch(
  "https://api.youraiconnector.com/v1/appointments/aBcD1234eFgH5678",
  {
    method: "PUT",
    headers: {
      "X-API-Key": "YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      start_time: "2026-06-16T10:00:00.000Z",
      end_time: "2026-06-16T10:30:00.000Z",
    }),
  }
);
const data = await res.json();
console.log(data.appointment);

Python

import requests

res = requests.put(
    "https://api.youraiconnector.com/v1/appointments/aBcD1234eFgH5678",
    headers={
        "X-API-Key": "YOUR_API_KEY",
        "Content-Type": "application/json",
    },
    json={
        "start_time": "2026-06-16T10:00:00.000Z",
        "end_time": "2026-06-16T10:30:00.000Z",
    },
)
print(res.json()["appointment"])

Resposta (200 OK):

{
  "success": true,
  "appointment_id": "aBcD1234eFgH5678",
  "appointment": {
    "id": "aBcD1234eFgH5678",
    "contact_id": "contact_abc123",
    "event_id": "event_xyz789",
    "status": "Confirmed",
    "start_time": "2026-06-16T10:00:00.000Z",
    "end_time": "2026-06-16T10:30:00.000Z",
    "calendar_synced": true
  }
}

Cancelar um agendamento

POST /appointments/{appointmentId}/cancel

Cancela um agendamento confirmado, registando opcionalmente um motivo. O agendamento permanece na sua conta com o estado Canceled e o evento de calendário associado é removido automaticamente em segundo plano. O cancelamento de um agendamento já cancelado devolve um 400.

Campo Obrigatório Descrição
cancellation_reason Não Motivo do cancelamento, guardado no agendamento.

cURL

curl -X POST "https://api.youraiconnector.com/v1/appointments/aBcD1234eFgH5678/cancel" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "cancellation_reason": "Client asked to reschedule next month"
  }'

JavaScript

const res = await fetch(
  "https://api.youraiconnector.com/v1/appointments/aBcD1234eFgH5678/cancel",
  {
    method: "POST",
    headers: {
      "X-API-Key": "YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      cancellation_reason: "Client asked to reschedule next month",
    }),
  }
);
const data = await res.json();
console.log(data.success);

Python

import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/appointments/aBcD1234eFgH5678/cancel",
    headers={
        "X-API-Key": "YOUR_API_KEY",
        "Content-Type": "application/json",
    },
    json={"cancellation_reason": "Client asked to reschedule next month"},
)
print(res.json()["success"])

Resposta (200 OK):

{
  "success": true,
  "appointment_id": "aBcD1234eFgH5678"
}

Reenviar a confirmação da reserva

POST /appointments/{appointmentId}/resend-confirmation

Envia novamente a confirmação da reserva ao contacto, por exemplo, quando este diz que nunca a recebeu ou que foi para o spam. Duas partes, ambas enviadas a menos que desative uma delas: o e-mail de confirmação (o mesmo e-mail que o contacto recebeu quando efetuou a reserva) e, quando o agendamento está no seu Google Calendar, o convite do Google Calendar. Ambos são enviados para o endereço de e-mail do contacto.

Campo Obrigatório Descrição
email Não false ignora o e-mail de confirmação. O valor predefinido é true.
calendar_invite Não false ignora o convite do Google Calendar. O valor predefinido é true.

Cada parte retorna com o seu próprio resultado: sent, not_requested, no_contact_email, turned_off_for_event_type (o interruptor Enviar e-mail de agendamento ao contacto do tipo de evento está desligado), not_on_google_calendar, imported (agendamentos importados do seu calendário não recebem e-mail de confirmação) ou failed.

  • 200 quando pelo menos uma parte foi enviada. recipient é o endereço para onde foi enviada.
  • 409 para um agendamento cancelado, um que já terminou, ou uma reserva feita através do Zenchef, Formitable, OpenTable, TheFork ou Trafft (esse sistema envia a sua própria confirmação). code é appointment_canceled, appointment_in_past ou managed_by_provider.
  • 422 quando nada pôde ser enviado, com o motivo em error.

cURL

curl -X POST "https://api.youraiconnector.com/v1/appointments/aBcD1234eFgH5678/resend-confirmation" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

JavaScript

const res = await fetch(
  "https://api.youraiconnector.com/v1/appointments/aBcD1234eFgH5678/resend-confirmation",
  {
    method: "POST",
    headers: {
      "X-API-Key": "YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ calendar_invite: false }),
  }
);
const data = await res.json();
console.log(data.email, data.recipient);

Python

import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/appointments/aBcD1234eFgH5678/resend-confirmation",
    headers={
        "X-API-Key": "YOUR_API_KEY",
        "Content-Type": "application/json",
    },
    json={},
)
print(res.json())

Resposta (200 OK):

{
  "success": true,
  "appointment_id": "aBcD1234eFgH5678",
  "email": "sent",
  "calendar_invite": "sent",
  "recipient": "jane@example.com"
}

Eliminar um agendamento

DELETE /appointments/{appointmentId}

Elimina permanentemente um agendamento e as suas referências. Se apenas pretende cancelar a marcação mantendo o registo, utilize cancelar em vez disso.

cURL

curl -X DELETE "https://api.youraiconnector.com/v1/appointments/aBcD1234eFgH5678" \
  -H "X-API-Key: YOUR_API_KEY"

JavaScript

const res = await fetch(
  "https://api.youraiconnector.com/v1/appointments/aBcD1234eFgH5678",
  { method: "DELETE", headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const data = await res.json();
console.log(data.success);

Python

import requests

res = requests.delete(
    "https://api.youraiconnector.com/v1/appointments/aBcD1234eFgH5678",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
print(res.json()["success"])

Resposta (200 OK):

{
  "success": true
}

Listar os seus Google Calendars ligados

GET /appointments/google-calendars

Devolve os Google Calendars disponíveis nesta conta, diretamente do Google — útil para mostrar ao titular da conta um seletor de qual calendário importar abaixo, ou apenas para confirmar que a ligação está ativa.

Isto só funciona depois de a conta ter ligado o Google Calendar (Definições → Integrações) com, pelo menos, acesso de leitura. Se não o tiver feito, ou se o acesso concedido já não incluir o âmbito de leitura do calendário, receberá um 400 a indicar-lhe que deve ligá-lo (ou ligá-lo novamente).

cURL

curl "https://api.youraiconnector.com/v1/appointments/google-calendars" \
  -H "X-API-Key: YOUR_API_KEY"

JavaScript

const res = await fetch("https://api.youraiconnector.com/v1/appointments/google-calendars", {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
console.log(data.data);

Python

import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/appointments/google-calendars",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
print(res.json()["data"])

Resposta (200 OK):

{
  "success": true,
  "data": [
    {
      "id": "primary",
      "summary": "jane@example.com",
      "timeZone": "America/New_York",
      "accessRole": "owner",
      "primary": true
    },
    {
      "id": "abcdefg1234567890@group.calendar.google.com",
      "summary": "Bookings",
      "timeZone": "America/New_York",
      "accessRole": "writer"
    }
  ]
}

Cada entrada tem o formato CalendarListEntry da própria Google, pelo que os nomes dos campos seguem a camelCase da Google e não a snake_case habitual desta API — são dados da Google transmitidos tal como estão, não os nossos. Uma ligação em falta ou revogada devolve um 400 com um erro a explicar que o Google Calendar precisa de ser ligado (ou ligado novamente).


Importar eventos de um Google Calendar

POST /appointments/import-calendar-events

Extrai os eventos que já se encontram nos Google Calendar(s) ligados a uma campanha ou a um Agente de IA e transforma-os em marcações — útil na primeira vez que liga um calendário que já tem reservas. Isto pode demorar algum tempo (cada evento passa por um processo de extração para determinar a quem se destina), pelo que nunca é executado em linha: o pedido coloca em fila de espera um trabalho de fundo e devolve-lhe um job_id para consulta.

Campo Obrigatório Descrição
campaign_id Um destes dois A campanha cujos calendários ligados devem ser importados.
agent_id Um destes dois O Agente de IA cujos calendários ligados devem ser importados.
identifier Sim "EMAIL" ou "PHONE_NUMBER" — que informação de contacto extrair de cada evento do calendário para corresponder ou criar o contacto a que pertence.

Envie exatamente um de campaign_id / agent_id, nunca ambos e nunca nenhum — qualquer uma destas combinações devolve um 400. O que enviar tem de pertencer à sua conta, caso contrário receberá um 404.

cURL

curl -X POST "https://api.youraiconnector.com/v1/appointments/import-calendar-events?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "agent_abc123",
    "identifier": "EMAIL"
  }'

JavaScript

const res = await fetch("https://api.youraiconnector.com/v1/appointments/import-calendar-events", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    agent_id: "agent_abc123",
    identifier: "EMAIL",
  }),
});
const data = await res.json();
console.log(data.job_id);

Python

import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/appointments/import-calendar-events",
    headers={
        "X-API-Key": "YOUR_API_KEY",
        "Content-Type": "application/json",
    },
    json={"agent_id": "agent_abc123", "identifier": "EMAIL"},
)
print(res.json()["job_id"])

Resposta (202 Accepted):

{
  "success": true,
  "job_id": "jK9mQ2xR7pL4wN1t",
  "status": "queued",
  "campaign_id": null,
  "agent_id": "agent_abc123"
}

campaign_id e agent_id devolvem o que enviou; o outro é sempre null.

Consultar o trabalho de importação

GET /appointments/import-calendar-events/{jobId}

curl "https://api.youraiconnector.com/v1/appointments/import-calendar-events/jK9mQ2xR7pL4wN1t" \
  -H "X-API-Key: YOUR_API_KEY"

Resposta (200 OK):

{
  "success": true,
  "job_id": "jK9mQ2xR7pL4wN1t",
  "status": "completed",
  "message": "Imported 12 events as appointments.",
  "error": null
}
status Significado
queued Ainda não processado. Continue a consultar.
processing A importação está em curso. Continue a consultar.
completed Concluído — message contém um breve resumo legível.
failed Algo correu mal — error contém o motivo.

GET num jobId que não existe (ou que pertence a uma conta diferente) devolve 404.


Integrações de reservas externas (Zenchef / Formitable / OpenTable / TheFork / Trafft)

O Zenchef e o Formitable são sistemas de reservas de restaurantes através dos quais o seu Agente de IA pode reservar mesas reais; o Trafft é uma plataforma de agendamento para empresas de marcações, ligada uma vez por conta em vez de por restaurante. As duas plataformas de restauração possuem cada uma um widget de reserva público e não autenticado (https://api.youraiconnector.com/v1/zenchef-widget/... e https://api.youraiconnector.com/v1/formitable-widget/...) que é apresentado dentro do chat para o cliente — esses caminhos de widget são páginas HTML simples destinadas a serem abertas num navegador, não endpoints de API JSON, pelo que não estão documentados aqui. O que se segue são os endpoints de gestão de conta: verificar se um ID de restaurante pertence ao titular da conta e, em seguida, adicioná-lo, atualizá-lo ou removê-lo.

Zenchef

A ligação de um restaurante Zenchef é um processo de verificação de dois passos, para que o titular da conta prove que realmente gere o restaurante antes de este ser ligado ao bot: primeiro, verifique se o ID existe (sem revelar o nome), depois peça-lhe para escrever o nome do restaurante e verifique se corresponde.

Passo 1 — Verificar se um ID de restaurante existe

POST /appointments/zenchef-restaurants/check

Campo Obrigatório Descrição
restaurant_id Sim O ID do restaurante Zenchef a verificar.
curl -X POST "https://api.youraiconnector.com/v1/appointments/zenchef-restaurants/check?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "restaurant_id": "12345" }'

Resposta (200 OK):

{
  "success": true,
  "data": { "exists": true, "requiresNameVerification": true }
}

exists: false significa que nenhum restaurante Zenchef tem esse ID — não há mais nada a fazer. Limitado a 10 verificações por cada 5 minutos por conta; exceder este limite devolve 429.

Passo 2 — Verificar o nome do restaurante

POST /appointments/zenchef-restaurants/verify-name

Campo Obrigatório Descrição
restaurant_id Sim O ID do restaurante Zenchef do passo 1.
user_input_name Sim O nome que o titular da conta escreveu — comparado com o nome real do restaurante no Zenchef (insensível a maiúsculas/minúsculas e espaços).
curl -X POST "https://api.youraiconnector.com/v1/appointments/zenchef-restaurants/verify-name?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "restaurant_id": "12345", "user_input_name": "The Blue Door Bistro" }'

Resposta (200 OK):

{
  "success": true,
  "data": {
    "verified": true,
    "restaurantDetails": {
      "id": "12345",
      "name": "The Blue Door Bistro",
      "address": "1 Rue de Rivoli, Paris",
      "status": "active"
    }
  }
}

verified: false significa que o nome não correspondeu — restaurantDetails é omitido, peça ao titular da conta para tentar novamente. Limitado a 3 tentativas por cada 5 minutos (mais restrito do que a verificação de existência, uma vez que este é o passo de prova real). Um restaurant_id que já não é resolvido no Zenchef devolve 404.

Passo 3 — Guardar o restaurante

POST /appointments/zenchef-restaurants

Campo Obrigatório Descrição
restaurant_id Sim 1–64 caracteres, letras/números/underscore/hífen.
restaurant_name Sim O nome do restaurante verificado do passo 2.
curl -X POST "https://api.youraiconnector.com/v1/appointments/zenchef-restaurants?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "restaurant_id": "12345", "restaurant_name": "The Blue Door Bistro" }'

Resposta (201 Created):

{ "success": true, "data": { "restaurantId": "12345" } }

Atualizar um restaurante Zenchef guardado

PUT /appointments/zenchef-restaurants/{restaurantId}

Campo Obrigatório Descrição
restaurant_name Não Novo nome de apresentação.
is_active Não Defina false para impedir que o bot efetue reservas neste restaurante sem o remover.
curl -X PUT "https://api.youraiconnector.com/v1/appointments/zenchef-restaurants/12345" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "is_active": false }'

Resposta (200 OK): mesma estrutura que a resposta de guardar acima.

Remover um restaurante Zenchef

DELETE /appointments/zenchef-restaurants/{restaurantId}

curl -X DELETE "https://api.youraiconnector.com/v1/appointments/zenchef-restaurants/12345" \
  -H "X-API-Key: YOUR_API_KEY"

Resposta (200 OK): { "success": true, "data": { "restaurantId": "12345" } }

Um restaurantId que não esteja atualmente na conta devolve 404 ao atualizar ou eliminar.

Formitable

O Formitable não necessita da prova de nome em dois passos como o Zenchef — os seus IDs de restaurante já estão delimitados por empresa, pelo que uma chamada de verificação é suficiente. Também possui uma consulta de detalhes utilizada para colocar em cache o URL do website do restaurante durante a configuração.

Verificar um ID de restaurante

POST /appointments/formitable-restaurants/verify

Campo Obrigatório Descrição
restaurant_id Sim O ID de restaurante Formitable.
language Não Etiqueta de idioma para o pedido de sondagem. O valor predefinido é "nl".
curl -X POST "https://api.youraiconnector.com/v1/appointments/formitable-restaurants/verify?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "restaurant_id": "the-blue-door", "language": "en" }'

Resposta (200 OK):

{
  "success": true,
  "data": {
    "verified": true,
    "restaurantDetails": {
      "restaurantId": "the-blue-door",
      "productCount": 4,
      "sampleProductTitle": "Dinner for two",
      "language": "en"
    }
  }
}

Um restaurant_id que o Formitable não reconheça devolve 404. Limitado a 10 tentativas por cada 5 minutos por conta.

Obter detalhes do restaurante

GET /appointments/formitable-restaurants/{restaurantId}/details?language=en

Obtém o perfil público do restaurante a partir do Formitable, incluindo o seu website — utilizado para colocar em cache o URL do website durante a configuração do restaurante. language é um parâmetro de consulta opcional, com o valor predefinido "en".

curl "https://api.youraiconnector.com/v1/appointments/formitable-restaurants/the-blue-door/details?language=en" \
  -H "X-API-Key: YOUR_API_KEY"

Resposta (200 OK):

{
  "success": true,
  "data": {
    "uid": "the-blue-door",
    "name": "The Blue Door Bistro",
    "website": "https://thebluedoorbistro.com",
    "email": "info@thebluedoorbistro.com",
    "telephone": "+31201234567",
    "streetAddress": "Prinsengracht 1",
    "zipcode": "1015 AB",
    "city": "Amsterdam",
    "country": "Netherlands",
    "countryCode": "NL",
    "currency": "EUR"
  }
}

Guardar o restaurante

POST /appointments/formitable-restaurants

Campo Obrigatório Descrição
restaurant_id Sim 1–64 caracteres, letras/números/underscore/hífen.
restaurant_name Sim Nome a apresentar.
language Sim Etiqueta de idioma ISO, p. ex. "en" ou "en-GB".
website_url Não O website do restaurante, a partir da consulta de detalhes acima. Deve ser http(s)://.
curl -X POST "https://api.youraiconnector.com/v1/appointments/formitable-restaurants?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "restaurant_id": "the-blue-door",
    "restaurant_name": "The Blue Door Bistro",
    "language": "en",
    "website_url": "https://thebluedoorbistro.com"
  }'

Resposta (201 Created): { "success": true, "data": { "restaurantId": "the-blue-door" } }

Atualizar um restaurante Formitable guardado

PUT /appointments/formitable-restaurants/{restaurantId}

Campo Obrigatório Descrição
restaurant_name Não Novo nome a apresentar.
language Não Nova etiqueta de idioma ISO.
is_active Não Defina false para impedir que o bot efetue reservas neste restaurante sem o remover.
website_url Não Novo URL do website.
curl -X PUT "https://api.youraiconnector.com/v1/appointments/formitable-restaurants/the-blue-door" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "is_active": false }'

Resposta (200 OK): mesma estrutura que a resposta de guardar acima.

Remover um restaurante Formitable

DELETE /appointments/formitable-restaurants/{restaurantId}

curl -X DELETE "https://api.youraiconnector.com/v1/appointments/formitable-restaurants/the-blue-door" \
  -H "X-API-Key: YOUR_API_KEY"

Resposta (200 OK): { "success": true, "data": { "restaurantId": "the-blue-door" } }

Um restaurantId que não esteja atualmente na conta devolve 404 ao atualizar ou eliminar.

OpenTable

Os restaurantes OpenTable são acedidos através das credenciais de parceiro OpenTable da plataforma, e o OpenTable apenas permite que essas credenciais vejam os restaurantes que ligaram a listagem da plataforma dentro do Marketplace de Integrações do OpenTable. Portanto, tal como no Formitable, uma chamada de verificação é suficiente: um ID de Restaurante alcançável (o “RID” numérico) prova tanto que o restaurante existe como que ligou a integração. Até que a listagem de parceiro OpenTable seja ativada na plataforma, a chamada de verificação responde 503.

Verificar um restaurante OpenTable

POST /appointments/opentable-restaurants/verify

Campo Obrigatório Descrição
restaurant_id Sim O ID de Restaurante (RID) do OpenTable, um número como 1038007.
curl -X POST "https://api.youraiconnector.com/v1/appointments/opentable-restaurants/verify?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "restaurant_id": "1038007" }'

Resposta (200 OK):

{
  "success": true,
  "data": {
    "verified": true,
    "restaurantDetails": {
      "restaurantId": "1038007",
      "diningAreaCount": 2,
      "diningAreaNames": ["Main Room", "Garden"],
      "tableTypes": ["default", "outdoor", "bar"]
    }
  }
}

verified: false significa que nenhum restaurante OpenTable tem esse ID. Um 403 significa que o restaurante existe, mas ainda não ligou a integração da plataforma dentro do OpenTable. Limitado a 10 tentativas por cada 5 minutos por conta.

Adicionar um restaurante OpenTable

POST /appointments/opentable-restaurants

Campo Obrigatório Descrição
restaurant_id Sim O ID de Restaurante verificado.
restaurant_name Sim Nome de exibição (uma etiqueta; também o que a IA chama ao restaurante).
website_url Não Um URL http(s) mostrado aos convidados quando a IA os reencaminha para o restaurante.
curl -X POST "https://api.youraiconnector.com/v1/appointments/opentable-restaurants?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "restaurant_id": "1038007", "restaurant_name": "The Blue Door", "website_url": "https://thebluedoor.example" }'

Resposta (201 Created): { "success": true, "data": { "restaurantId": "1038007" } }

Atualizar um restaurante OpenTable guardado

PUT /appointments/opentable-restaurants/{restaurantId}

Envie qualquer um de restaurant_name, is_active (pausa com false) ou website_url (uma string vazia limpa o campo); os campos omitidos permanecem inalterados.

curl -X PUT "https://api.youraiconnector.com/v1/appointments/opentable-restaurants/1038007" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "is_active": false }'

Resposta (200 OK): { "success": true, "data": { "restaurantId": "1038007" } }

Remover um restaurante OpenTable

DELETE /appointments/opentable-restaurants/{restaurantId}

curl -X DELETE "https://api.youraiconnector.com/v1/appointments/opentable-restaurants/1038007" \
  -H "X-API-Key: YOUR_API_KEY"

Resposta (200 OK): { "success": true, "data": { "restaurantId": "1038007" } }

Um restaurantId que não esteja atualmente na conta devolve 404 na atualização.

TheFork

Os restaurantes do TheFork são acedidos através das credenciais de parceiro TheFork da plataforma, e o TheFork apenas permite que essas credenciais vejam restaurantes que tenham o parceiro da plataforma ativado na sua conta TheFork. Portanto, tal como no Formitable e no OpenTable, uma chamada de verificação é suficiente: um ID de Restaurante alcançável prova tanto que o restaurante existe como que o parceiro está ativado nele. O ID é o UUID que o TheFork atribui ao restaurante no TheFork Manager, enviado como uma string. Até que o TheFork tenha aprovado a plataforma como parceiro e emitido as credenciais, a chamada de verificação responde 503 — consulte TheFork para saber o que isso significa atualmente.

Verificar um restaurante TheFork

POST /appointments/thefork-restaurants/verify

Campo Obrigatório Descrição
restaurant_id Sim O ID de Restaurante do TheFork, um UUID como 9f2a1c34-5b6d-4e7f-8a90-1b2c3d4e5f60.
curl -X POST "https://api.youraiconnector.com/v1/appointments/thefork-restaurants/verify?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "restaurant_id": "9f2a1c34-5b6d-4e7f-8a90-1b2c3d4e5f60" }'

Resposta (200 OK):

{
  "success": true,
  "data": {
    "verified": true,
    "restaurantDetails": {
      "restaurantId": "9f2a1c34-5b6d-4e7f-8a90-1b2c3d4e5f60",
      "partySizes": [1, 2, 3, 4, 5, 6, 7, 8]
    }
  }
}

partySizes são os tamanhos de grupo que o restaurante aceita online nos próximos 30 dias. Um 404 ou 403 significa que o TheFork não nos forneceu um restaurante com esse ID — ou o ID está incorreto, ou o parceiro da plataforma ainda não está ativado nesse restaurante; um 400 significa que o ID não é um UUID. Limitado a 10 tentativas por cada 5 minutos por conta.

Adicionar um restaurante TheFork

POST /appointments/thefork-restaurants

Campo Obrigatório Descrição
restaurant_id Sim O ID de Restaurante verificado (UUID).
restaurant_name Sim Nome de exibição (uma etiqueta; também o nome pelo qual a IA chama o restaurante).
website_url Não Um URL http(s) mostrado aos convidados quando a IA os encaminha para o restaurante.
curl -X POST "https://api.youraiconnector.com/v1/appointments/thefork-restaurants?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "restaurant_id": "9f2a1c34-5b6d-4e7f-8a90-1b2c3d4e5f60", "restaurant_name": "The Blue Door", "website_url": "https://thebluedoor.example" }'

Resposta (201 Created): { "success": true, "data": { "restaurantId": "9f2a1c34-5b6d-4e7f-8a90-1b2c3d4e5f60" } }

Atualizar um restaurante TheFork guardado

PUT /appointments/thefork-restaurants/{restaurantId}

Envie qualquer um de restaurant_name, is_active (pausa com false) ou website_url (uma string vazia limpa o campo); os campos omitidos permanecem inalterados.

curl -X PUT "https://api.youraiconnector.com/v1/appointments/thefork-restaurants/9f2a1c34-5b6d-4e7f-8a90-1b2c3d4e5f60" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "is_active": false }'

Resposta (200 OK): { "success": true, "data": { "restaurantId": "9f2a1c34-5b6d-4e7f-8a90-1b2c3d4e5f60" } }

Remover um restaurante TheFork

DELETE /appointments/thefork-restaurants/{restaurantId}

curl -X DELETE "https://api.youraiconnector.com/v1/appointments/thefork-restaurants/9f2a1c34-5b6d-4e7f-8a90-1b2c3d4e5f60" \
  -H "X-API-Key: YOUR_API_KEY"

Resposta (200 OK): { "success": true, "data": { "restaurantId": "9f2a1c34-5b6d-4e7f-8a90-1b2c3d4e5f60" } }

Um restaurantId que não esteja atualmente na conta devolve 404 ao atualizar ou eliminar.

Trafft

O Trafft é ligado uma vez para toda a conta, não por localização: um endereço de empresa mais as credenciais da API do painel de administração do Trafft (Features & Integrations → API & Connectors, parte do plano Business do Trafft). A chamada de ligação verifica essas credenciais junto do Trafft antes de guardar qualquer coisa, pelo que um endereço errado, credenciais erradas ou um plano sem acesso à API falharão aqui em vez de durante uma conversa com o cliente. O segredo do cliente é guardado encriptado e nunca é devolvido por nenhum endpoint.

Todas as três chamadas de escrita (POST, PUT, DELETE) requerem a permissão de edição de Integrações; o estado GET necessita de visualização de Integrações.

Ligar Trafft

POST /appointments/trafft/connect

Campo Obrigatório Descrição
subdomain Sim O endereço da empresa — a parte antes de .admin.trafft.com no URL em que inicia sessão, por exemplo acme. Um endereço completo é aceite e reduzido ao mesmo valor.
client_id Sim ID de cliente da página API & Connectors do Trafft.
client_secret Sim Segredo do cliente da mesma página. Guardado encriptado, nunca devolvido.
company_name Não Uma etiqueta para a sua própria lista.
curl -X POST "https://api.youraiconnector.com/v1/appointments/trafft/connect?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "subdomain": "acme",
    "client_id": "YOUR_TRAFFT_CLIENT_ID",
    "client_secret": "YOUR_TRAFFT_CLIENT_SECRET",
    "company_name": "Acme Salon"
  }'

Resposta (200 OK):

{
  "success": true,
  "data": {
    "subdomain": "acme",
    "service_count": 12,
    "employee_count": 4,
    "location_count": 2
  }
}

As contagens são devolvidas pelo Trafft durante a verificação — são a forma mais rápida de confirmar que as credenciais apontam para a conta que pretendia.

Obter o estado da ligação

GET /appointments/trafft

curl "https://api.youraiconnector.com/v1/appointments/trafft" \
  -H "X-API-Key: YOUR_API_KEY"

Resposta (200 OK):

{
  "success": true,
  "data": {
    "connected": true,
    "subdomain": "acme",
    "hostname": "acme.admin.trafft.com",
    "client_id": "YOUR_TRAFFT_CLIENT_ID",
    "company_name": "Acme Salon",
    "is_active": true,
    "service_count": 12,
    "employee_count": 4,
    "location_count": 2
  }
}

connected: false significa que ainda não foi configurado nada. O segredo do cliente nunca é incluído nesta resposta.

Atualizar a ligação

PUT /appointments/trafft

Campo Obrigatório Descrição
is_active Não Defina false para pausar — a IA deixa de efetuar marcações no Trafft, mas a ligação permanece. true retoma-a.
company_name Não Nova etiqueta.
curl -X PUT "https://api.youraiconnector.com/v1/appointments/trafft" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "is_active": false }'

Resposta (200 OK): o mesmo objeto de ligação que o GET acima.

Desligar Trafft

DELETE /appointments/trafft

curl -X DELETE "https://api.youraiconnector.com/v1/appointments/trafft" \
  -H "X-API-Key: YOUR_API_KEY"

Resposta (200 OK): { "success": true }

Desligar remove apenas as credenciais armazenadas. As marcações já existentes no Trafft permanecem inalteradas.

Formato de erro em todos os endpoints Zenchef/Formitable/OpenTable/TheFork: ao contrário do resto desta página, os erros aqui apresentam o estado duas vezes — uma como estado HTTP e outra como error_code no corpo — por exemplo { "success": false, "error": "Restaurant not found", "error_code": 404 }. Trate-o da mesma forma que qualquer outro erro: verifique success, leia error para obter a mensagem.


Erros da API de marcações

Os endpoints de marcações devolvem o envelope de erro padrão:

{
  "success": false,
  "error": "Appointment not found"
}
Estado Quando ocorre num endpoint de agendamento
400 Um campo obrigatório está em falta ou é inválido — por exemplo, um start_time incorreto, um end_time não posterior a start_time, uma combinação de filtros inválida, sem campos para atualizar, ou um agendamento já cancelado. Ao reservar: nem event_id nem title enviados, ambos enviados em conjunto, ambos end_time e duration_minutes enviados, um title com mais de 200 caracteres, ou um duration_minutes fora de 1–1440.
404 O agendamento, contacto ou tipo de evento não foi encontrado.
409 O intervalo de tempo solicitado já está ocupado (conflito de reserva), ou numa atualização, a external_reference já está a ser utilizada por outro agendamento.

Os códigos partilhados que qualquer endpoint pode devolver — 401, 403 (o seu plano não inclui acesso à API), 429 (limite de taxa) e 500 — estão listados com orientações de repetição em Erros e Paginação.



Próximos passos

  • Contactos — crie e procure os contactos para os quais efetua reservas.
  • Mensagens e Conversas — envie uma confirmação ou um lembrete a um contacto.
  • Webhooks — receba notificações quando os agendamentos forem alterados.