Lire et planifier dans le calendrier
Lire les événements d'une période, créer un événement, le déplacer ou l'annuler, et inviter un contact.
Un événement vit dans un calendrier : celui d'un utilisateur (« Mon calendrier »), d'une équipe, d'une ressource, ou un calendrier partagé. Il n'a pas de droits propres : le voit qui voit son calendrier, le modifie qui peut y écrire. Ses dates sont en UTC ; envoyez-les avec leur fuseau — voir Dates et fuseaux.
1Les calendriers de l'utilisateur
GET https://staging-api.docage.com/Calendars/Mine
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9…curl "https://staging-api.docage.com/Calendars/Mine" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9…"using HttpClient client = new();
using HttpRequestMessage request = new(HttpMethod.Get, "https://staging-api.docage.com/Calendars/Mine");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
using HttpResponseMessage response = await client.SendAsync(request);
string result = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
throw new HttpRequestException(result);const response = await fetch("https://staging-api.docage.com/Calendars/Mine", {
headers: {
Authorization: `Bearer ${token}`
}
});
const text = await response.text();
if (!response.ok) throw new Error(text);
const result = text ? JSON.parse(text) : null;Les calendriers que l'utilisateur voit, son calendrier personnel en tête — créé s'il n'existe pas encore :
Id,Name,TimeZoneId;Kind:1personnel,2d'équipe,3de ressource,4partagé ;IsOwn: son calendrier personnel ;IsDefault: son calendrier par défaut ;CanModify: il peut y créer et y modifier des événements.
Le calendrier personnel d'un collègue n'y paraît que si ce collègue l'a ouvert à l'utilisateur.
2Lire les événements d'une période
GET https://staging-api.docage.com/CalendarEvents/Range?from=2026-11-15T23:00:00Z&to=2026-11-22T23:00:00Z&calendarIds=3a9c5e17-0000-4000-8000-000000000201
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9…curl "https://staging-api.docage.com/CalendarEvents/Range?from=2026-11-15T23:00:00Z&to=2026-11-22T23:00:00Z&calendarIds=3a9c5e17-0000-4000-8000-000000000201" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9…"using HttpClient client = new();
using HttpRequestMessage request = new(HttpMethod.Get, "https://staging-api.docage.com/CalendarEvents/Range?from=2026-11-15T23:00:00Z&to=2026-11-22T23:00:00Z&calendarIds=3a9c5e17-0000-4000-8000-000000000201");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
using HttpResponseMessage response = await client.SendAsync(request);
string result = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
throw new HttpRequestException(result);const response = await fetch("https://staging-api.docage.com/CalendarEvents/Range?from=2026-11-15T23:00:00Z&to=2026-11-22T23:00:00Z&calendarIds=3a9c5e17-0000-4000-8000-000000000201", {
headers: {
Authorization: `Bearer ${token}`
}
});
const text = await response.text();
if (!response.ok) throw new Error(text);
const result = text ? JSON.parse(text) : null;from(inclus) etto(exclu), avec leur fuseau ; sans fuseau, lus en UTC.tosuitfrom, sinon400.calendarIds: les calendriers à lire — répétez le paramètre pour en lire plusieurs. Un calendrier que l'utilisateur ne voit pas est ignoré. SanscalendarIds, tous ceux qu'il voit.
La réponse rend chaque événement qui chevauche la période :
Id,CalendarId,Name,Description,Location,StartUtc,EndUtc,IsAllDay,TimeZoneId;Status:1confirmé,2provisoire,3annulé ;ShowAs:1occupé,2libre,3provisoire,4absent ;- sa série :
RecurrenceRule,RecurrenceException,RecurrenceParentId,OriginalStartUtc; - ses rattachements :
ContactId,CompanyId,PipelineItemId,TransactionId,ConversationId,MeetingId; CanModify: l'utilisateur peut le modifier.
Une série revient une seule fois, avec sa règle — une RRULE de la RFC 5545, sans le préfixe RRULE: —, datée de sa première
occurrence : déroulez-la depuis StartUtc, à durée égale, dans le fuseau TimeZoneId, sans les dates de RecurrenceException.
Une occurrence modifiée revient à part, avec RecurrenceParentId et OriginalStartUtc.
Un événement privé (Visibility 2) d'un calendrier que l'utilisateur ne fait que lire ne montre que son créneau : il revient
sous le nom « Occupé », sans description, sans lieu, sans lien de visio ni rattachement — ici comme dans sa fiche
(GET https://staging-api.docage.com/CalendarEvents/{id}), dans la liste des événements et sous son nom (GET https://staging-api.docage.com/CalendarEvents/Name/{id}) ; son
historique est vide. Une liste qui interroge ce qu'il cache — filtrée ou triée sur son objet, sa description ou son lieu, restreinte à
un contact ou à une autre fiche — ne le compte pas. Qui peut écrire dans le calendrier le lit en entier.
Un créneau est libre quand aucun événement ne l'occupe. Un événement occupe, sauf annulé (Status 3) ou affiché libre
(ShowAs 2).
3Créer un événement
POST https://staging-api.docage.com/CalendarEvents
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9…
Content-Type: application/json
{
"Name": "Rendez-vous avec Camille Martin",
"StartUtc": "2026-11-17T14:00:00+01:00",
"EndUtc": "2026-11-17T15:00:00+01:00",
"TimeZoneId": "Europe/Paris",
"Location": "Agence de Lyon",
"ContactId": "9b2d7a46-3c1e-4f0a-8b5d-1a2b3c4d5e6f"
}curl -X POST "https://staging-api.docage.com/CalendarEvents" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9…" \
-H "Content-Type: application/json" \
-d '{
"Name": "Rendez-vous avec Camille Martin",
"StartUtc": "2026-11-17T14:00:00+01:00",
"EndUtc": "2026-11-17T15:00:00+01:00",
"TimeZoneId": "Europe/Paris",
"Location": "Agence de Lyon",
"ContactId": "9b2d7a46-3c1e-4f0a-8b5d-1a2b3c4d5e6f"
}'using HttpClient client = new();
using HttpRequestMessage request = new(HttpMethod.Post, "https://staging-api.docage.com/CalendarEvents");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
request.Content = new StringContent("""
{
"Name": "Rendez-vous avec Camille Martin",
"StartUtc": "2026-11-17T14:00:00+01:00",
"EndUtc": "2026-11-17T15:00:00+01:00",
"TimeZoneId": "Europe/Paris",
"Location": "Agence de Lyon",
"ContactId": "9b2d7a46-3c1e-4f0a-8b5d-1a2b3c4d5e6f"
}
""", Encoding.UTF8, "application/json");
using HttpResponseMessage response = await client.SendAsync(request);
string result = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
throw new HttpRequestException(result);const response = await fetch("https://staging-api.docage.com/CalendarEvents", {
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"Name": "Rendez-vous avec Camille Martin",
"StartUtc": "2026-11-17T14:00:00+01:00",
"EndUtc": "2026-11-17T15:00:00+01:00",
"TimeZoneId": "Europe/Paris",
"Location": "Agence de Lyon",
"ContactId": "9b2d7a46-3c1e-4f0a-8b5d-1a2b3c4d5e6f"
})
});
const text = await response.text();
if (!response.ok) throw new Error(text);
const result = text ? JSON.parse(text) : null;CalendarId: le calendrier. Sans lui, le calendrier par défaut des préférences de l'utilisateur, sinon son calendrier personnel.TimeZoneId: un nom IANA. Il déroule une série et situe le jour d'une journée entière ; omis ou vide, c'est celui du calendrier.StatusetShowAs:1d'office ;Visibility:1normale (d'office),2privée — l'événement ne montre alors son détail qu'à qui peut écrire dans le calendrier (voir plus haut).ReminderMinutesBefore: le rappel — une notification de l'application à son auteur et aux collègues invités —, en minutes avant le début ; omis, celui des préférences de l'utilisateur (15 minutes d'office).RecurrenceRule: une série, par exempleFREQ=WEEKLY;BYDAY=MO.- Une journée entière :
"IsAllDay": true,StartUtcà minuit du premier jour,EndUtcà minuit du lendemain du dernier jour, exclu. Les 17 et 18 novembre : de2026-11-17T00:00:00+01:00à2026-11-19T00:00:00+01:00; un minuit local se lit dans le fuseauTimeZoneIdde l'événement. - Les rattachements, pour que l'événement paraisse sur ces fiches :
ContactId,CompanyId,PipelineItemId(une carte),TransactionId(un parcours),ConversationId. Chacun est une fiche active de l'organisation de l'événement, que l'utilisateur voit ; une conversation, il y participe. Une modification ne juge que ceux qu'elle pose ou change.MeetingIdy pose une réunion de visio — voir Planifier une réunion de visio.
La réponse est l'identifiant de l'événement. 422, avec sa raison :
- un objet vide, une fin avant le début, une règle illisible, un rappel négatif ;
- un calendrier inconnu ou que l'utilisateur ne voit pas, groupé, ou où il ne peut pas écrire ;
- un rattachement inconnu, d'une autre organisation ou que l'utilisateur ne voit pas — la même réponse dans les trois cas, qui ne dit jamais si la fiche existe.
4Inviter
POST https://staging-api.docage.com/CalendarEvents/7c21d4a8-0000-4000-8000-000000000501/Invite
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9…curl -X POST "https://staging-api.docage.com/CalendarEvents/7c21d4a8-0000-4000-8000-000000000501/Invite" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9…"using HttpClient client = new();
using HttpRequestMessage request = new(HttpMethod.Post, "https://staging-api.docage.com/CalendarEvents/7c21d4a8-0000-4000-8000-000000000501/Invite");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
using HttpResponseMessage response = await client.SendAsync(request);
string result = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
throw new HttpRequestException(result);const response = await fetch("https://staging-api.docage.com/CalendarEvents/7c21d4a8-0000-4000-8000-000000000501/Invite", {
method: "POST",
headers: {
Authorization: `Bearer ${token}`
}
});
const text = await response.text();
if (!response.ok) throw new Error(text);
const result = text ? JSON.parse(text) : null;{ "Sent": 1, "Message": null }- L'invitation — un email et son fichier iCalendar — part à chaque participant qui a une adresse, l'organisateur excepté. Le contact
rattaché (
ContactId) devient participant au premier envoi, s'il a une adresse email. Un collègue participant reçoit aussi une notification de l'application. Une personne d'une autre organisation que l'événement n'est ni invitée ni prévenue. Sentcompte les invitations parties ; à0,Messagedit pourquoi : aucun participant n'a d'adresse email, ou seul l'organisateur en a une.404: l'événement est introuvable, à la corbeille, ou l'utilisateur ne le voit pas.403: il le voit, mais ne peut pas écrire dans son calendrier.400: aucun envoi n'a réussi.- Renvoyée après un changement, l'invitation met l'événement à jour chez les invités : elle porte le même identifiant iCalendar.
5Déplacer, annuler, supprimer
- Déplacer :
PUT https://staging-api.docage.com/CalendarEvents/{id}, avec le nouveauStartUtcet le nouveauEndUtc. Une série se déplace tout entière. Renvoyez ensuite l'invitation. - Annuler en prévenant :
PUT https://staging-api.docage.com/CalendarEvents/{id}avec{ "Status": 3 }, puisPOST https://staging-api.docage.com/CalendarEvents/{id}/Invite: c'est l'annulation qui part. L'événement reste dans le calendrier, sans plus l'occuper. - Supprimer :
DELETE https://staging-api.docage.com/CalendarEvents/{id}le met à la corbeille. Personne n'est prévenu.
Les pièges
- Dans une adresse, un
+non encodé se lit comme une espace : une borne…T00:00:00+01:00devient illisible (400). Écrivez la borne en UTC (Z), ou encodez le signe (%2B01:00). TimeZoneIdomis est celui du calendrier, pas celui du poste qui écrit : donnez-le quand l'événement vit dans un autre fuseau que son calendrier, pour une série ou une journée entière.- L'API n'invite que le contact rattaché, en plus des participants que l'événement a déjà (posés par une réservation, par exemple) : la liste des participants ne s'écrit pas.
- Un événement qui matérialise une absence (
AbsenceId) ne se modifie pas par le calendrier (422) : il suit son absence. - Les rendez-vous pris sur un modèle de réservation se gèrent comme dans Gérer les rendez-vous d'un modèle de réservation.