Intégrer TrackChantier à votre écosystème
L’API TrackChantier vous permet de pousser vos données depuis un ERP ou un outil externe vers la plateforme TrackChantier : compagnies, agences, postes, employés, chantiers et hiérarchie de phases/zones/étapes.
Vous ciblez votre fonction HTTP Firebase :
BASE_URL = https://<region>-<project-id>.cloudfunctions.net
Dans la collection Postman fournie, cette valeur est injectée via la
variable BASE_URL.
Authentification & headers
Toutes les fonctions HTTP sont protégées par un secret
TOKEN (stocké côté Firebase). Vous devez inclure le token
dans chaque requête.
Bearer <TOKEN>
requis
application/json
requis
upsertCompagnies) :
x-odoo-token: <TOKEN>
optionnel
curlcurl -X POST \
"$BASE_URL/upsertCompagnies" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "id": "1", "nom": "TrackChantier" }'
IDs en string & liens cohérents
L’API fonctionne en upsert : chaque appel crée le document s’il n’existe pas, ou fusionne les champs envoyés s’il existe déjà (merge Firestore).
- Les IDs sont des numériques castés en chaîne :
"1","2"… - Vous pouvez envoyer un number, il sera transformé en string côté API.
- Les relations se font toujours via ces mêmes IDs string.
"1" pour TrackChantiercompanyId (string)"1" = Chargé d’affairesagenceId + posteId"1", et champs caId, ctId,
ceId pointent vers employees/{id}.
Sur la plupart des endpoints, seuls les champs envoyés sont écrasés. Les champs non présents dans le body sont laissés intacts.
-
Pour
upsertChantierFields, beaucoup de champs sont conditionnés par unhas('path'): si vous n’envoyez pas le champ, l’ancienne valeur est conservée. -
L’adresse du chantier est mise à jour uniquement si vous envoyez au moins
un des champs
street,street2,zip,city,country. - Les phases/zones/étapes sont upsertées sans suppression des éléments existants non mentionnés.
Endpoints principaux
Voici les endpoints utilisés dans la collection “TrackChantiers – API INIT (TrackChantier)” pour créer une base de données de tests cohérente.
Création / mise à jour de compagnies.
| Nom du champ | Obligatoire | Type | Description |
|---|---|---|---|
| id | Oui | string / number | Identifiant de la compagnie, casté en string dans Firestore |
| nom / name | Non | string | Nom affiché de la compagnie |
| salarie_de_pret | Non | bool | Indique si la compagnie gère du prêt de salariés |
| loan_ids | Non | array | Liste d’IDs externes (ex : contrats de prêt Odoo) conservée telle quelle |
| chantiersDePret | Non | array<object> | Sous-collection compagnies/{id}/chantiersDePret. Chaque élément : { companyId, chantierId } ou { company_id, chantier_id } (tous castés en string). |
curlcurl -X POST "$BASE_URL/upsertCompagnies" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"id": "1",
"nom": "TrackChantier",
"salarie_de_pret": false,
"loan_ids": [],
"chantiersDePret": [
{ "companyId": "1", "chantierId": "1" }
]
}'
jsawait fetch(`${BASE_URL}/upsertCompagnies`, {
method: "POST",
headers: {
"Authorization": `Bearer ${TOKEN}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
id: "1",
nom: "TrackChantier",
salarie_de_pret: false,
loan_ids: [],
chantiersDePret: [
{ companyId: "1", chantierId: "1" }
]
})
});
Création / mise à jour d’agences. Supporte un objet unique ou un tableau d’agences.
| Nom du champ | Obligatoire | Type | Description |
|---|---|---|---|
| id | Oui | string / number | ID de l’agence, casté en string |
| nom / name | Non | string | Nom de l’agence |
| city | Non | string | Ville, stockée dans le champ ville |
| color | Non | string | Couleur associée, stockée dans couleur |
| samsara_tracking | Non | bool | Active le tracking Samsara pour l’agence |
| display_invoice_ratio_dashboard | Non | bool | Affiche le ratio de facturation sur le dashboard |
| display_exploitation_dashboard | Non | bool | Affiche le dashboard exploitation |
| warehouse | Non | string / number / array | ID d’entrepôt Odoo (simple valeur ou premier élément d’un tableau), stocké dans warehouse_id |
| show_on_dashboard | Non | bool | Visibilité de l’agence sur le dashboard principal (showOnDashboard) |
| show_on_dashboard_widget | Non | bool | Visibilité dans certains widgets du dashboard (showOnDashboardWidget) |
| show_on_missing_hours_widget | Non | bool | Contrôle des heures manquantes / acomptes à valider (showWidgetAcomptesAValider) |
| show_widget_holidays_on_dashboard | Non | bool | Affiche les congés sur le dashboard |
| show_widget_late_invoices | Non | bool | Widget factures en retard |
| show_widget_projects_to_invoice | Non | bool | Widget projets / situations à facturer (showWidgetSituationsMois) |
| show_widget_hours_tracking | Non | bool | Widget pointages à contrôler (showWidgetPointagesAControler) |
| show_widget_agora_invoices | Non | bool | Widget factures AGORA |
| show_widget_acomptes_to_validate | Non | bool | Widget acomptes à valider (showWidgetAcomptesToValidate) |
| margin_goals | Non | any | Objectifs de marge, structure libre |
| goals | Non | any | Autres objectifs agences, structure libre |
| companyId | Non | string | ID de la compagnie Firestore (compagnies/{companyId}) |
| is_principal | Non | bool | Si vrai, copie de l’agence enregistrée dans agences/GROUPE avec original_id et original_nom |
exemple{
"id": "1",
"nom": "Agence Grenoble",
"companyId": "1",
"city": "Grenoble",
"color": "#1976D2",
"samsara_tracking": false,
"display_invoice_ratio_dashboard": true,
"display_exploitation_dashboard": true,
"warehouse": 1,
"show_on_dashboard": true,
"show_on_dashboard_widget": true,
"show_on_missing_hours_widget": false,
"show_widget_holidays_on_dashboard": true,
"show_widget_late_invoices": true,
"show_widget_projects_to_invoice": true,
"show_widget_hours_tracking": true,
"show_widget_agora_invoices": false,
"show_widget_acomptes_to_validate": false,
"margin_goals": {},
"goals": {},
"is_principal": true
}
Référentiel de postes utilisés par les employés.
| Nom du champ | Obligatoire | Type | Description |
|---|---|---|---|
| id | Oui | string / number | ID du poste, casté en string |
| nom | Oui | string | Libellé du poste |
| description | Non | string | Description métier |
| actif | Non | bool | Poste actif ou non |
exemple[
{ "id": "1", "nom": "Chargé d'affaires", "actif": true },
{ "id": "2", "nom": "Conducteur de travaux", "actif": true },
{ "id": "3", "nom": "Chef de chantier", "actif": true },
{ "id": "4", "nom": "Opérateur de chantier", "actif": true }
]
Création / mise à jour d’employés dans la collection
employees. L’API vérifie notamment que
agenceId et posteId existent.
| Nom du champ | Obligatoire | Type | Description |
|---|---|---|---|
| id | Oui | string / number | ID de l’employé, casté en string |
| firstName / prenom | Oui (création) | string | Prénom de l’employé |
| lastName / nom | Oui (création) | string | Nom de famille |
| initial | Non | string | Initiales (ex : FB) |
| displayName | Non | string | Nom complet d’affichage ; si absent il est calculé à partir de firstName + lastName |
| poste | Non | string | Libellé du poste (ex : Chargé d'affaires) |
| posteId | Non | string / number | ID du poste, doit correspondre à postes/{posteId} |
| agence | Non | string | Nom de l’agence (ex : Agence Grenoble) |
| agenceId | Non | string / number | ID d’agence, casté en string, référence agences/{agenceId} |
| company | Non | string | Nom de la compagnie (TrackChantier) |
| companyId | Non | string | ID de la compagnie (compagnies/{companyId}) |
| parentId | Non | string | ID du manager / responsable hiérarchique |
| parentName | Non | string | Nom du manager |
| userId | Non | string | ID utilisateur TrackChantier associé |
| Non | string | Email professionnel, utilisé aussi pour les accès | |
| isManager | Non | bool | Indique si l’employé est manager |
| telephone | Non | string | Téléphone personnel |
| telephonePro | Non | string | Téléphone professionnel |
| telUrgence | Non | string | Numéro à contacter en cas d’urgence |
| intitulePoste | Non | string | Intitulé de poste complet |
| matricule | Non | string | Matricule interne |
| agoraMailEmployee | Non | string | Email AGORA de l’employé |
| agoraMailAgence | Non | string | Email AGORA de l’agence |
| agoraMailGroupe | Non | string | Email AGORA du groupe |
| active | Non | bool | Employé actif ou archivé |
| coach | Non | string | Nom du coach |
| coachId | Non | string | ID du coach |
| formationDrive | Non | string | ID / URL de dossier Drive lié aux formations |
| adresse | Non | object | Adresse postale normalisée : { rue, rue1, rue2, cp, ville } |
| googleDrive | Non | object | Informations Drive diverses, structure libre |
| skills | Non | array | Compétences / habilitations de l’employé |
| formations | Non | object / array | Formations liées à l’employé |
exemple[
{
"id": "1",
"firstName": "Fabien",
"lastName": "BEL",
"poste": "Chargé d'affaires",
"posteId": "1",
"agence": "Agence Grenoble",
"agenceId": "1",
"company": "TrackChantier",
"companyId": "1",
"mail": "fabien@fbel.info",
"active": true,
"telephonePro": "+33 4 00 00 00 00",
"adresse": {
"rue1": "5 Rue des Écoles",
"cp": "38210",
"ville": "La Rivière"
},
"skills": [],
"formations": {}
}
]
Endpoint principal pour créer / mettre à jour un chantier et ses métadonnées (agence, client, dates, objectifs, hiérarchie, etc.). La plupart des champs sont conditionnés par la présence de la clef dans le body (si vous ne l’envoyez pas, la valeur existante est conservée).
| Nom du champ | Obligatoire | Type | Description |
|---|---|---|---|
| id | Oui | string | ID du chantier, casté en string |
| name | Non | string | Nom du chantier (stocké dans nom) |
| start_date | Non | string (YYYY-MM-DD) | Date de démarrage |
| end_date | Non | string (YYYY-MM-DD) | Date de fin |
| agence | Non | string | Nom de l’agence |
| agence_id | Non | string | ID de l’agence → stocké dans agenceId |
| client | Non | string | Nom du client |
| client_id | Non | string | ID externe du client |
| client_type | Non | string | Type du client (public / privé…) |
| main_company | Non | string | Compagnie principale d’exploitation |
| company | Non | string | Nom de la compagnie (TrackChantier) |
| company_id | Non | string | ID de la compagnie (stocké dans companyId) |
| company_details | Non | any | Détails supplémentaires sur la compagnie |
| maitre_ouvrage | Non | string | Maître d’ouvrage |
| maitre_oeuvre | Non | string | Maître d’œuvre |
| number | Non | string | Numéro du chantier (ex: 25001) |
| status | Non | string |
Statut (valeurs: demarre, non_demarre, administratif, archive, termine)
|
| odoo_project | Non | string / number | ID projet Odoo |
| odoo_account | Non | string / number | ID compte Odoo |
| sales_order | Non | any | Référence de commande de vente |
| id_drive_folder | Non | string | ID du dossier Drive principal |
| drive | Non | object | Liste des sous-dossiers Drive (plans, photos…) |
| advancement_hours | Non | number | Objectif d’avancement global |
| target_hours | Non | number | Objectif total d’heures du chantier |
| times_set | Non | bool | Objectifs par zone activés |
| is_closed | Non | bool | Chantier clos |
| date_closed | Non | string | Date de clôture |
| int_type_id | Non | string / number | Type d’intervention |
| location_id | Non | string / number | Localisation Odoo |
| ca | Non | object | Chargé d’affaires → {id, name} |
| ct | Non | object | Conducteur de travaux → {id, name} |
| ce | Non | object | Chef de chantier → {id, name} |
| charge_da_id | Non | string | ID CA compatible DOLO |
| conducteur_travaux_id | Non | string | ID CT compatible DOLO |
| chef_chantier_id | Non | string | ID CE compatible DOLO |
| street | Non | string | Rue |
| street2 | Non | string | Complément de rue |
| zip | Non | string | Code postal |
| city | Non | string | Ville |
| country | Non | string | Pays |
| adresse | Non | object | Objet adresse consolidé : { rue, rue1, rue2, codePostal, departement, ville, country } |
| phases | Non | array | Hiérarchie complète phases → zones → étapes |
exemple{
"id": "1",
"name": "Réhabilitation école de La Rivière",
"start_date": "2025-11-15",
"end_date": "2026-03-31",
"street": "5 Rue des Écoles",
"zip": "38210",
"city": "La Rivière",
"country": "FR",
"agence": "Agence Grenoble",
"agence_id": "1",
"client": "Ville de La Rivière",
"client_id": "1",
"client_type": "public",
"company": "TrackChantier",
"company_id": "1",
"number": "25001",
"status": "demarre",
"odoo_project": 123,
"odoo_account": 456,
"id_drive_folder": "DRIVE_FOLDER_ID",
"drive": {
"plans": "FOLDER_ID_PLANS",
"photos": "FOLDER_ID_PHOTOS"
},
"advancement_hours": 120,
"target_hours": 200,
"times_set": true,
"is_closed": false,
"ca": { "id": "1", "name": "Fabien BEL" },
"ct": { "id": "2", "name": "Nicolas Dubost" },
"ce": { "id": "3", "name": "Jonathan Paterne" },
"phases": [
{
"id": 1,
"name": "Phase 1",
"order": 1,
"start_date": "2025-11-15",
"end_date": "2025-12-15",
"zones": [
{
"id": 1,
"name": "Zone A",
"order": 1,
"etapes": [
{ "uuid": "etp-1", "name": "Préparation", "planned_hours": 40 }
]
}
]
}
]
}
Créer une base de tests cohérente
La collection “TrackChantiers – API INIT (TrackChantier)” illustre un scénario complet avec une compagnie, plusieurs agences, postes, employés, et chantiers liés aux bons CA / CT / CE.
- /upsertPostes – créer vos postes (Chargé d’affaires, Conducteur de travaux, Chef de chantier, Opérateur…).
-
/upsertCompagnies – créer la compagnie principale
(ex :
id = "1",nom = "TrackChantier"). -
/upsertAgences – rattacher des agences à la compagnie
(
companyId = "1"). -
/upsertEmployes – créer les employés en précisant
posteId+agenceId+companyId. -
/upsertChantierFields – créer vos chantiers en pointant
ca.id,ct.id,ce.idsur les employés créés à l’étape 4.
Script minimal d’intégration
Exemple de script Node.js pour rejouer la logique de la collection d’init : création de la compagnie TrackChantier, des agences, des postes, des employés et d’un chantier lié.
nodeimport fetch from "node-fetch";
const BASE_URL = process.env.TRACKCHANTIERS_BASE_URL;
const TOKEN = process.env.TRACKCHANTIERS_TOKEN;
async function call(endpoint, payload) {
const res = await fetch(`${BASE_URL}/${endpoint}`, {
method: "POST",
headers: {
"Authorization": `Bearer ${TOKEN}`,
"Content-Type": "application/json"
},
body: JSON.stringify(payload)
});
if (!res.ok) {
const txt = await res.text();
throw new Error(`${endpoint} → HTTP ${res.status}: ${txt}`);
}
return res.json().catch(() => ({}));
}
(async () => {
// 1. Postes
await call("upsertPostes", [
{ id: "1", nom: "Chargé d'affaires", actif: true },
{ id: "2", nom: "Conducteur de travaux", actif: true },
{ id: "3", nom: "Chef de chantier", actif: true },
{ id: "4", nom: "Opérateur de chantier", actif: true }
]);
// 2. Compagnie
await call("upsertCompagnies", { id: "1", nom: "TrackChantier" });
// 3. Agences
await call("upsertAgences", [
{ id: "1", nom: "Agence Grenoble", companyId: "1", ville: "Grenoble", codePostal: "38000" },
{ id: "2", nom: "Agence Lyon", companyId: "1", ville: "Lyon", codePostal: "69000" },
{ id: "3", nom: "Agence Paris", companyId: "1", ville: "Paris", codePostal: "75000" }
]);
// 4. Employés (François, Julien, Joe)
await call("upsertEmployes", [
{
id: "1",
firstName: "François",
lastName: "Biol",
poste: "Chargé d'affaires",
posteId: "1",
agence: "Agence Grenoble",
agenceId: "1",
company: "TrackChantier",
companyId: "1",
mail: "François@gmail.info",
active: true
},
{
id: "2",
firstName: "Julien",
lastName: "Dubois",
poste: "Conducteur de travaux",
posteId: "2",
agence: "Agence Lyon",
agenceId: "2",
company: "TrackChantier",
companyId: "1",
mail: "Julien@gmail.info",
active: true
},
{
id: "3",
firstName: "Joe",
lastName: "Pater",
poste: "Chef de chantier",
posteId: "3",
agence: "Agence Paris",
agenceId: "3",
company: "TrackChantier",
companyId: "1",
mail: "Joe@gmail.info",
active: true
}
]);
// 5. Chantier lié aux 3 encadrants
await call("upsertChantierFields", {
id: "1",
name: "Réhabilitation école de La Rivière",
start_date: "2025-11-15",
end_date: "2026-03-31",
street: "5 Rue des Écoles",
zip: "38210",
city: "La Rivière",
country: "FR",
agence: "Agence Grenoble",
agence_id: "1",
client: "Ville de La Rivière",
client_id: "1",
client_type: "public",
company: "TrackChantier",
company_id: "1",
number: "25001",
ca: { id: "1", name: "François Biol" },
ct: { id: "2", name: "Julien Dubois" },
ce: { id: "3", name: "Joe Pater" }
});
console.log("Base de tests TrackChantier initialisée ✅");
})().catch(err => {
console.error(err);
process.exit(1);
});
Télécharger la collection d’exemples
Vous pouvez utiliser une collection Postman prête à l’emploi pour rejouer tous les endpoints décrits dans cette documentation. Elle contient des requêtes d’init complètes pour créer une base de tests cohérente (compagnie, agences, postes, employés, chantiers…).
Téléchargez le fichier suivant et importez-le dans Postman :
👉 Télécharger la collection TrackChantiers – API INIT
Important : après l’import, ouvrez l’onglet Variables de la collection et configurez :
TOKEN– le secret attendu par les endpoints (headerAuthorization: Bearer <TOKEN>).BASE_URL– l’URL de base de vos fonctions HTTP Firebase (ex:https://europe-west1-votre-projet.cloudfunctions.net).
Une fois ces variables renseignées, vous pouvez lancer les requêtes dans l’ordre recommandé (section “Flow d’init”) pour initialiser votre environnement de tests.