Créer un contact, une société et une carte
Enregistrer une société et son contact sans doublon, puis ouvrir une carte dans un pipeline et la faire avancer.
1La société
POST https://staging-api.docage.com/Companies
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9…
Content-Type: application/json
{
"Name": "Atelier Lumière",
"Country": "FR",
"Phone": "+33499001234",
"Email": "contact@example.com",
"City": "Lyon"
}curl -X POST "https://staging-api.docage.com/Companies" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9…" \
-H "Content-Type: application/json" \
-d '{
"Name": "Atelier Lumière",
"Country": "FR",
"Phone": "+33499001234",
"Email": "contact@example.com",
"City": "Lyon"
}'using HttpClient client = new();
using HttpRequestMessage request = new(HttpMethod.Post, "https://staging-api.docage.com/Companies");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
request.Content = new StringContent("""
{
"Name": "Atelier Lumière",
"Country": "FR",
"Phone": "+33499001234",
"Email": "contact@example.com",
"City": "Lyon"
}
""", 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/Companies", {
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"Name": "Atelier Lumière",
"Country": "FR",
"Phone": "+33499001234",
"Email": "contact@example.com",
"City": "Lyon"
})
});
const text = await response.text();
if (!response.ok) throw new Error(text);
const result = text ? JSON.parse(text) : null;La réponse est l'identifiant de la société créée. Seul Name est obligatoire. Country est un code de pays ISO à deux lettres.
2Le contact, sans doublon
POST https://staging-api.docage.com/Contacts?duplicates=ask
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9…
Content-Type: application/json
{
"FirstName": "Camille",
"LastName": "Martin",
"Gender": 2,
"Email": "camille.martin@example.com",
"Mobile": "+33600000001",
"Country": "FR",
"ParentCompanyId": "00000000-0000-4000-8000-000000000101",
"Job": "Gérante"
}curl -X POST "https://staging-api.docage.com/Contacts?duplicates=ask" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9…" \
-H "Content-Type: application/json" \
-d '{
"FirstName": "Camille",
"LastName": "Martin",
"Gender": 2,
"Email": "camille.martin@example.com",
"Mobile": "+33600000001",
"Country": "FR",
"ParentCompanyId": "00000000-0000-4000-8000-000000000101",
"Job": "Gérante"
}'using HttpClient client = new();
using HttpRequestMessage request = new(HttpMethod.Post, "https://staging-api.docage.com/Contacts?duplicates=ask");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
request.Content = new StringContent("""
{
"FirstName": "Camille",
"LastName": "Martin",
"Gender": 2,
"Email": "camille.martin@example.com",
"Mobile": "+33600000001",
"Country": "FR",
"ParentCompanyId": "00000000-0000-4000-8000-000000000101",
"Job": "Gérante"
}
""", 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/Contacts?duplicates=ask", {
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"FirstName": "Camille",
"LastName": "Martin",
"Gender": 2,
"Email": "camille.martin@example.com",
"Mobile": "+33600000001",
"Country": "FR",
"ParentCompanyId": "00000000-0000-4000-8000-000000000101",
"Job": "Gérante"
})
});
const text = await response.text();
if (!response.ok) throw new Error(text);
const result = text ? JSON.parse(text) : null;ParentCompanyIdrattache le contact à sa société, qui doit être une société que vous voyez : sinon l'appel répond422.- Seul
LastNameest obligatoire.Gendervaut1(homme) d'office :2femme,3autre — donnez-le. - Un numéro s'enregistre au format international E.164 (
+33600000001) ; écrivez-le ainsi d'emblée.
duplicates=ask fait vérifier les doublons avant l'écriture, selon les règles de dédoublonnage de l'organisation. Une fiche
proche répond 409, avec les fiches qui lui ressemblent :
{
"EntityTypeName": "Contact",
"Candidates": [
{ "Id": "00000000-0000-4000-8000-000000000201", "Name": "Camille Martin", "Email": "camille.martin@example.com", "Score": 100, "IsCertain": true }
],
"HiddenCount": 0
}Reprenez l'identifiant d'une fiche proposée, ou renvoyez la même requête avec duplicates=acknowledged pour créer la fiche malgré
tout (« pas un doublon »). Une règle qui bloque refuse dans tous les cas. Sans le paramètre, seule une règle qui bloque
refuse : la fiche s'écrit, et la paire est signalée « à examiner » dans l'application.
3Le pipeline et ses étapes
Une carte circule dans les colonnes (les étapes) d'un pipeline : une affaire, un ticket, une tâche…
GET https://staging-api.docage.com/Pipelines/EntitiesIdAndName
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9…curl "https://staging-api.docage.com/Pipelines/EntitiesIdAndName" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9…"using HttpClient client = new();
using HttpRequestMessage request = new(HttpMethod.Get, "https://staging-api.docage.com/Pipelines/EntitiesIdAndName");
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/Pipelines/EntitiesIdAndName", {
headers: {
Authorization: `Bearer ${token}`
}
});
const text = await response.text();
if (!response.ok) throw new Error(text);
const result = text ? JSON.parse(text) : null;Puis, pour le pipeline choisi, son type de carte (DefinitionId, dans GET https://staging-api.docage.com/Pipelines/{id}) et ses étapes :
GET https://staging-api.docage.com/Pipelines/00000000-0000-4000-8000-000000000302/Stages
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9…curl "https://staging-api.docage.com/Pipelines/00000000-0000-4000-8000-000000000302/Stages" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9…"using HttpClient client = new();
using HttpRequestMessage request = new(HttpMethod.Get, "https://staging-api.docage.com/Pipelines/00000000-0000-4000-8000-000000000302/Stages");
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/Pipelines/00000000-0000-4000-8000-000000000302/Stages", {
headers: {
Authorization: `Bearer ${token}`
}
});
const text = await response.text();
if (!response.ok) throw new Error(text);
const result = text ? JSON.parse(text) : null;Chaque étape a son Id, son nom, son rang (Order) et son statut (0 nouveau, 1 en cours, 2 en attente, 3 aboutie, 4
échouée, 5 close).
4La carte
POST https://staging-api.docage.com/PipelineItems
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9…
Content-Type: application/json
{
"DefinitionId": "00000000-0000-4000-8000-000000000301",
"PipelineId": "00000000-0000-4000-8000-000000000302",
"Name": "Vitrine de Noël — Atelier Lumière",
"MainContactId": "00000000-0000-4000-8000-000000000201",
"Amount": 4800,
"DueDate": "2026-12-15T00:00:00Z",
"Priority": 2
}curl -X POST "https://staging-api.docage.com/PipelineItems" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9…" \
-H "Content-Type: application/json" \
-d '{
"DefinitionId": "00000000-0000-4000-8000-000000000301",
"PipelineId": "00000000-0000-4000-8000-000000000302",
"Name": "Vitrine de Noël — Atelier Lumière",
"MainContactId": "00000000-0000-4000-8000-000000000201",
"Amount": 4800,
"DueDate": "2026-12-15T00:00:00Z",
"Priority": 2
}'using HttpClient client = new();
using HttpRequestMessage request = new(HttpMethod.Post, "https://staging-api.docage.com/PipelineItems");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
request.Content = new StringContent("""
{
"DefinitionId": "00000000-0000-4000-8000-000000000301",
"PipelineId": "00000000-0000-4000-8000-000000000302",
"Name": "Vitrine de Noël — Atelier Lumière",
"MainContactId": "00000000-0000-4000-8000-000000000201",
"Amount": 4800,
"DueDate": "2026-12-15T00:00:00Z",
"Priority": 2
}
""", 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/PipelineItems", {
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"DefinitionId": "00000000-0000-4000-8000-000000000301",
"PipelineId": "00000000-0000-4000-8000-000000000302",
"Name": "Vitrine de Noël — Atelier Lumière",
"MainContactId": "00000000-0000-4000-8000-000000000201",
"Amount": 4800,
"DueDate": "2026-12-15T00:00:00Z",
"Priority": 2
})
});
const text = await response.text();
if (!response.ok) throw new Error(text);
const result = text ? JSON.parse(text) : null;DefinitionId, le type de carte, est obligatoire, même avecPipelineId. SansPipelineId, la carte rejoint le pipeline par défaut de son type.- La carte entre dans l'étape d'entrée du pipeline. Avec un
StageId(et unFailureReasonIdvers une étape échouée), elle y est menée aussitôt, comme par un déplacement (pas 5) : statut, dates et historique suivent.Status,StageEnteredDateetClosedDatene se donnent pas. - Sans
CompanyId, la carte prend la société de son interlocuteur. UnCompanyIddonné désigne une société que vous voyez, sinon l'appel répond422.
5La faire avancer
PUT https://staging-api.docage.com/PipelineItems/00000000-0000-4000-8000-000000000401/MoveToStage/00000000-0000-4000-8000-000000000303?comment=Devis%20accept%C3%A9
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9…curl -X PUT "https://staging-api.docage.com/PipelineItems/00000000-0000-4000-8000-000000000401/MoveToStage/00000000-0000-4000-8000-000000000303?comment=Devis%20accept%C3%A9" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9…"using HttpClient client = new();
using HttpRequestMessage request = new(HttpMethod.Put, "https://staging-api.docage.com/PipelineItems/00000000-0000-4000-8000-000000000401/MoveToStage/00000000-0000-4000-8000-000000000303?comment=Devis%20accept%C3%A9");
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/PipelineItems/00000000-0000-4000-8000-000000000401/MoveToStage/00000000-0000-4000-8000-000000000303?comment=Devis%20accept%C3%A9", {
method: "PUT",
headers: {
Authorization: `Bearer ${token}`
}
});
const text = await response.text();
if (!response.ok) throw new Error(text);
const result = text ? JSON.parse(text) : null;Le déplacement tient la carte à jour : statut, date d'entrée dans l'étape, probabilité, date de clôture, historique. Vers une étape
échouée, donnez le motif (failureReasonId, parmi GET https://staging-api.docage.com/Pipelines/{id}/FailureReasons). Un refus répond 400, avec son
motif ; une carte que vous voyez sans pouvoir la modifier, 403 ; une carte introuvable, ou que vous ne voyez pas, 404.
Les pièges
- Le statut et les dates d'une carte suivent son étape : un
PUTde la carte n'écrit jamaisStatus,StageEnteredDateniClosedDate— renvoyés inchangés, ils sont ignorés ; changés, la requête est refusée (400). Pour changer d'étape,MoveToStage, ouStageIddans lePUT: les deux passent par le moteur du pipeline. UnFailureReasonIdseul corrige le motif d'une carte échouée. - Un
PipelineIdd'un autre type de carte ou d'une autre organisation est refusé avant l'écriture. Une création refusée après l'enregistrement (un pipeline sans étape, une étape demandée que la carte n'a pas pu rejoindre) laisse la carte créée : le message le dit, avec l'identifiant de la carte entre parenthèses ; relisez-la avant de recommencer. - La règle de dédoublonnage par défaut compare les nom, prénom, email et mobile tels qu'envoyés : un mobile écrit autrement qu'en E.164 ne retrouve pas la fiche existante.