Klantly Developers

Rendez-vous depuis votre propre planning

Placez les rendez-vous de votre propre logiciel de planning dans l'agenda de Klantly, gardez-les à jour et laissez Klantly envoyer une confirmation au client.

Vous planifiez dans votre propre système, par exemple un tableau de planning pour vos techniciens ? Avec l'API, vous placez ces rendez-vous dans l'agenda de Klantly. Vous les retrouvez alors sur la fiche du client et sur votre tableau de pipeline, et votre client reçoit les mêmes confirmations et rappels que pour un rendez-vous créé dans Klantly même.

Ce dont vous avez besoin

Une clé API avec ces scopes :

Scope Pour quoi faire
customers.read Rechercher le client par adresse e-mail.
customers.write Créer un client qui n'existe pas encore.
appointments.read Lister les rendez-vous et les créneaux libres.
appointments.write Planifier, déplacer, annuler et terminer des rendez-vous.
appointments.send Envoyer au client une confirmation, un déplacement, une annulation ou un rappel par e-mail.

La fonctionnalité Rendez-vous doit être activée pour votre entreprise.

Étape 1 : le client

Un rendez-vous appartient toujours à un client ; le nom, l'e-mail et le téléphone viennent de lui. Recherchez le client avec filter[email] ou créez-le, comme dans Du formulaire web au prospect. Conservez son id dans votre propre système : vous n'aurez pas à le rechercher la prochaine fois.

Étape 2 : planifier le rendez-vous

cURL
curl -X POST "https://app.klantly.com/api/v1/appointments" \
  -H "Authorization: Bearer $KLANTLY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: planning-4711" \
  -d '{"customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70", "title": "Métré véranda", "starts_at": "2026-10-06T09:00:00+02:00", "ends_at": "2026-10-06T10:30:00+02:00", "location": "12 rue du Village, Lille"}'
  • Envoyez toujours les heures avec un fuseau horaire, par exemple +02:00 ou Z. La réponse les donne en UTC.
  • Sans ends_at, le rendez-vous dure autant que le type de rendez-vous indiqué dans appointment_type_id, sinon la durée par défaut de vos paramètres de rendez-vous.
  • Mettez l'id de votre propre planning dans l'Idempotency-Key. Si votre serveur réessaie après un délai d'attente, il n'y a toujours qu'un seul rendez-vous.
  • Conservez l'id de la réponse à côté de votre propre id. Vous en avez besoin pour modifier le rendez-vous plus tard.

Un nouveau rendez-vous est confirmed. S'il doit encore être confirmé, envoyez "status": "pending". Klantly ne vérifie pas la disponibilité lors de la planification : votre planning fait foi.

Remarque

L'API n'envoie pas d'e-mail au client lors de la planification. Vous le faites délibérément, à l'étape 4. Attention : si votre entreprise a des automatisations sur « rendez-vous planifié » (par exemple une confirmation WhatsApp), elles s'exécutent, comme pour un rendez-vous dans l'agenda. Désactivez-les un moment lorsque vous importez votre planning pour la première fois.

Étape 3 : déplacer, annuler et terminer

Si l'heure change dans votre planning, envoyez uniquement la nouvelle heure :

cURL
curl -X PATCH "https://app.klantly.com/api/v1/appointments/0b6f3a52-7c1d-4e8a-9b2f-5d4c3b2a1f09" \
  -H "Authorization: Bearer $KLANTLY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"starts_at": "2026-10-08T13:00:00+02:00"}'

Sans ends_at, la durée reste identique, et rescheduled_at indique que le rendez-vous a été déplacé. Si un rendez-vous n'a pas lieu, annulez-le au lieu de le supprimer : il reste ainsi visible sur la fiche du client.

cURL
curl -X POST "https://app.klantly.com/api/v1/appointments/0b6f3a52-7c1d-4e8a-9b2f-5d4c3b2a1f09/cancel" \
  -H "Authorization: Bearer $KLANTLY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"reason": "Le client est malade"}'

Une fois la visite effectuée, terminez le rendez-vous avec POST /appointments/{id}/complete. Si votre conversion des prospects est réglée sur « rendez-vous terminé », un prospect devient client, comme dans l'agenda.

Étape 4 : informer le client

cURL
curl -X POST "https://app.klantly.com/api/v1/appointments/0b6f3a52-7c1d-4e8a-9b2f-5d4c3b2a1f09/notify" \
  -H "Authorization: Bearer $KLANTLY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: planning-4711-confirmation" \
  -d '{"message": "confirmation"}'

Klantly envoie l'e-mail avec le modèle que vous avez configuré dans Klantly. Le message doit correspondre au statut du rendez-vous :

message Possible avec le statut
confirmation confirmed
reschedule pending ou confirmed
cancellation cancelled
reminder confirmed

Si ce n'est pas le cas, si le rendez-vous n'a pas de date, si le client n'a pas d'adresse e-mail ou si votre entreprise a désactivé le modèle, vous recevez une 409 avec le code invalid_state_transition. detail en donne la raison.

Dans l'autre sens : les réservations depuis Klantly

Les clients peuvent aussi réserver eux-mêmes via votre page de réservation. Pour les voir dans votre planning, écoutez avec un webhook les événements appointment.created, appointment.updated, appointment.confirmed, appointment.cancelled, appointment.completed et appointment.deleted. Un changement de statut arrive comme événement distinct, pas comme appointment.updated. Chaque événement contient le rendez-vous complet.

Ces événements arrivent aussi pour les rendez-vous que vous avez planifiés vous-même via l'API. Reconnaissez-les à l'id conservé à l'étape 2, sinon ils apparaîtront deux fois dans votre planning.

Consulter les créneaux libres

Pour voir dans votre propre système où Klantly a encore de la place, demandez les créneaux libres :

cURL
curl --globoff "https://app.klantly.com/api/v1/availability?date_from=2026-10-06&date_to=2026-10-10&duration_minutes=90" \
  -H "Authorization: Bearer $KLANTLY_API_KEY"

Ce sont presque les mêmes créneaux que sur votre page de réservation : horaires, pauses, jours bloqués, délai de réservation maximal et rendez-vous déjà réservés sont pris en compte. Seul votre agenda Google n'est pas pris en compte ici, et les horaires valent pour toute l'entreprise, pas par collaborateur. Vous demandez au maximum 31 jours à la fois.

Tout ensemble

PHP
use GuzzleHttp\Client;

/**
 * $klantly est un client Guzzle avec l'URL de base et votre clé API, $job un rendez-vous de votre propre
 * planning. Renvoie l'id du rendez-vous dans Klantly : conservez-le avec le job.
 */
function syncAppointment(Client $klantly, array $job): string
{
    $body = [
        'title' => $job['title'],
        'starts_at' => $job['start']->format(DATE_ATOM),
        'ends_at' => $job['end']->format(DATE_ATOM),
        'location' => $job['address'],
    ];

    // Nouveau : planifier et envoyer une confirmation au client.
    if ($job['klantly_id'] === null) {
        $appointment = json_decode((string) $klantly->post('appointments', [
            'headers' => ['Idempotency-Key' => "planning-{$job['id']}"],
            'json' => $body + ['customer_id' => $job['klantly_customer_id']],
        ])->getBody(), true)['data'];

        $klantly->post("appointments/{$appointment['id']}/notify", [
            'headers' => ['Idempotency-Key' => "planning-{$job['id']}-confirmation"],
            'json' => ['message' => 'confirmation'],
        ]);

        return $appointment['id'];
    }

    // Existant : le modifier et, si l'heure change, prévenir le client du déplacement.
    $klantly->patch("appointments/{$job['klantly_id']}", ['json' => $body]);

    if ($job['time_changed']) {
        $klantly->post("appointments/{$job['klantly_id']}/notify", [
            'json' => ['message' => 'reschedule'],
        ]);
    }

    return $job['klantly_id'];
}
Node.js
const BASE_URL = 'https://app.klantly.com/api/v1';

async function klantly(method, path, { body, idempotencyKey } = {}) {
  const response = await fetch(`${BASE_URL}/${path}`, {
    method,
    headers: {
      Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
      ...(body ? { 'Content-Type': 'application/json' } : {}),
      ...(idempotencyKey ? { 'Idempotency-Key': idempotencyKey } : {}),
    },
    body: body ? JSON.stringify(body) : undefined,
  });

  const json = await response.json();
  if (!response.ok) throw new Error(json.detail ?? json.title);
  return json;
}

// job est un rendez-vous de votre propre planning ; start et end sont en ISO 8601 avec fuseau horaire.
// Renvoie l'id du rendez-vous dans Klantly : conservez-le avec le job.
export async function syncAppointment(job) {
  const body = { title: job.title, starts_at: job.start, ends_at: job.end, location: job.address };

  // Nouveau : planifier et envoyer une confirmation au client.
  if (!job.klantlyId) {
    const { data } = await klantly('POST', 'appointments', {
      body: { ...body, customer_id: job.klantlyCustomerId },
      idempotencyKey: `planning-${job.id}`,
    });
    await klantly('POST', `appointments/${data.id}/notify`, {
      body: { message: 'confirmation' },
      idempotencyKey: `planning-${job.id}-confirmation`,
    });
    return data.id;
  }

  // Existant : le modifier et, si l'heure change, prévenir le client du déplacement.
  await klantly('PATCH', `appointments/${job.klantlyId}`, { body });
  if (job.timeChanged) {
    await klantly('POST', `appointments/${job.klantlyId}/notify`, { body: { message: 'reschedule' } });
  }
  return job.klantlyId;
}

Gérer les erreurs

  • 422 avec validation_failed : par exemple une heure sans fuseau horaire. errors indique par champ ce qui ne va pas.
  • 409 avec invalid_state_transition : par exemple terminer un rendez-vous annulé, ou un message qui ne correspond pas au statut.
  • 429 avec rate_limited : attendez le nombre de secondes indiqué dans Retry-After et réessayez. Lorsque vous importez votre planning pour la première fois, étalez les requêtes dans le temps. Voir Rate limits.

Dernière mise à jour le 15 septembre 2026