PlanningPME API - Documentation développeur

Interconnectez votre planning avec le reste de votre système d'information.
PlanningPME permet l'accès en lecture et écriture aux données de votre base client par le biais d'une API dédiée. L'API PlanningPME respecte les standards de développement actuels (implémentation REST et échange de données au format JSON) pour une programmation simple de vos synchronisations et intégrations.

Ce document vous renseignera sur :

Où trouver l'adresse de votre API PlanningPME ?
Comment accéder à votre documentation interactive ?
L'implémentation de la sécurité dans l'API PlanningPME
Quelles sont les généralités à connaître sur les données de PlanningPME API ?
Comment faire vos premières demandes à l'API PlanningPME ?

L'API PlanningPME est basée sur les principes d'API RESTful et le format de transfert de données utilisé est JSON.
Cette documentation est principalement destinée aux développeurs. Nous recommandons au lecteur de se familiariser avec la programmation d'API REST JSON avant d'aller plus loin.

URL dédiée

Chaque client PlanningPME dispose de sa propre adresse API dédiée.
Supposons que votre marque soit "MyCompany", vous devrez très probablement utiliser la clé "mycompany" (non-sensible à la casse) pour construire votre adresse d'API.
Cette clé sera notée "votre_marque" dans le reste de cette documentation.

L'adresse API de base d'une marque sera toujours de la forme :
https://api.planningpme.com/votre_marque/
ou
https://try.planningpme.com/votre_marque/

Documentation interactive

Chaque API est livrée avec une documentation interactive, très utile pour découvrir les méthodes et modèles utilisés dans l'API PlanningPME, ou générer des requêtes.

Documentation interactive

Cette documentation est disponible à l'adresse suivante:
https://api.planningpme.com/votre_marque/doc/index
ou
https://try.planningpme.com/votre_marque/doc/index

Ces deux adresses ne peuvent pas être appelées sans présentation d'une clé d'API.

Note : dans le cas où l'authentification de compte est activée sur votre API, l'accès à la documentation interactive se fait en un clic au sein l'application de compte PlanningPME.

Sécurité

1/ Présentation de la clé d'API

L'accès à votre API nécessite une clé identifiant l'application qui appelle l'API : une appkey.
Cette appkey est disponible dans votre compte PlanningPME (si l'authentification de compte est activée sur votre API), ou à la demande au support.
Au-delà de la sécurité qu'elle apporte, l'appkey vous permet d'identifier un accès par un partenaire ou une application tierce disposant de sa propre clé.

L'appkey doit toujours être envoyée en en-tête d'une requête d'API, au moyen de l'en-tête dédié "X-APPKEY".

GET /votre_marque/api/config HTTP/1.1
Host: api.planningpme.com
X-APPKEY: e991573da5ffd4sab9b1e26bc6b64aac

Pour accéder à votre documentation interactive, utilisez l'appkey en paramètre d'adresse, comme dans l'exemple ci-dessous.

https://api.planningpme.com/votre_marque/doc/index?appkey=e991573da5ffd4sab9b1e26bc6b64aac

2/ Authentification et chargement de profil

La plupart des requêtes d'API doivent également présenter un jeton d'autorisation, afin de déterminer le profil de l'utilisateur accédant aux données, et de respecter les autorisations d'utilisateur et de groupe définies dans l'application.

Ce jeton est préalablement obtenu lors de l'authentification d'un utilisateur à l'addresse /token, et reste valable 8 heures.

Les données postées à cette adresse diffèrent selon le mode d'authentification choisi pour votre application.

a) Authentification classique

Si elle est activée, l'authentification classique se réalise en postant le nom d'utilisateur (username) et le mot de passe (password).

POST /votre_marque/token HTTP/1.1
Host: api.planningpme.com
X-APPKEY: e991573da5ffd4sab9b1e26bc6b64aac
Content-Type: application/x-www-form-urlencoded

grant_type=password&username=votre_utilisateur&password=votre_motdepasse

b) Authentification de compte

Si elle est activée, l'authentification de compte se réalise en postant un jeton de compte de service, obtenu préalablement dans l'application de compte PlanningPME.

API PlannningpmE

Pour chaque utilisateur listé ici, vous pouvez copier le jeton de compte de service dans votre presse-papier.

Obtenez à présent un jeton d'autorisation auprès de votre API, en postant le jeton de compte copié (assertion).

POST /votre_marque/token HTTP/1.1
Host: api.planningpme.com
X-APPKEY: e991573da5ffd4sab9b1e26bc6b64aac
Content-Type: application/x-www-form-urlencoded

grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=jeton_de_compte

c) Utilisation du jeton d'autorisation

Dans le cas d'une authentification réussie, le corps de la réponse contiendra un élément JSON comme suit.

{
    "access_token": "KTuZYDLG2qjUMqMVXDuiP9giFbqDXstESvpUWzBFLpkfdlMiB3PD5s2K7En-3o39u56hpr_DlyjEc_...3Is0gcH",
    "token_type": "bearer",
    "expires_in": 86399,
    "username": "votre_utilisateur"
}

La propriété "access_token" contient le jeton d'autorisation d'API.

Aussi, comme indiqué par la propriété "token_type", ce jeton est de type "bearer". Les requêtes nécessitant une autorisation doivent donc présenter l'en-tête "Authorization" avec la valeur "Bearer", comme dans l'exemple ci-dessous.

POST /votre_marque/api/customer HTTP/1.1
Host: api.planningpme.com
X-APPKEY: e991573da5ffd4sab9b1e26bc6b64aac
Authorization: Bearer KTuZYDLG2qjUMqMVXDuiP9giFbqDXstESvpUWzBFLpkfdlMiB3PD5s2K7En-3o39u56hpr_DlyjEc_...3Is0gcH

Utilisation de l'API

1/ Généralités

a) Modèles de données

Les modèles de données PlanningPME sont détaillés dans la documentation interactive de votre API.

b) Format de date

Le format de date utilisé par l'API et attendu dans chaque requête JSON est le format ISO 8601. Ex:

2018-01-25T18:05:00Z

c) Ordre des listes

Les méthodes GET utilisent souvent un paramètre "sortInfo" pour définir l'ordre de tri de la liste complète ou paginée qui est renvoyée.

Cette information est composée du nom d'une propriété directement suivie d'un signe + ou -.
Par exemple, utilisez "label+" pour demander un tri par ordre alphabétique ascendant sur la propriété "label".

Il est également possible de combiner plusieurs commandes en les ajoutant.
Utilisez par exemple "notValid-label+" pour demander un tri par propriété "notValid" descendante puis par ordre alphabétique ascendant sur "label".

Prenez garde au fait que les noms de propriétés sont sensibles à la casse.

d) Constantes d'énumérations

Bien qu'elle ne soit pas amenée à changer, sauf ajout, la liste complète des énumérations utilisées dans votre version d'API est obtenue en appelant la méthode "/api/config".

GET /votre_marque/api/config HTTP/1.1
Host: api.planningpme.com
X-APPKEY: e991573da5ffd4sab9b1e26bc6b64aac

Ci-dessous la liste des enums en version 4.7.0.26

{
...
"enums": {
  "Access": {
    "All": "All",
    "Read": "Read",
    "Write": "Write"
  },
  "BillingType": {
    "Package": "Package",
    "Unit": "Unit"
  },
  "ColorDepending": {
    "Label": "Label",
    "Category": "Category",
    "Customer": "Customer",
    "Time": "Time",
    "Project": "Project"
  },
  "ConfigType": {
    "ExportTemplates": "ExportTemplates",
    "TimeRestrictedView": "TimeRestrictedView",
    "Filterings": "Filterings",
    "Language": "Language",
    "DateTimeFormat": "DateTimeFormat",
    "GCSync": "GCSync",
    "EffectTemplates": "EffectTemplates",
    "SyncResource": "SyncResource",
    "PrintTemplates": "PrintTemplates"
  },
  "ConstraintAction": {
    "NoTaskBeforeNbHours": "NoTaskBeforeNbHours",
    "NoTaskBeforeNbDays": "NoTaskBeforeNbDays",
    "NoTaskSamePeriod": "NoTaskSamePeriod",
    "NbMaxHours": "NbMaxHours",
    "NbMax": "NbMax",
    "DurationMaxHours": "DurationMaxHours",
    "DurationMaxDays": "DurationMaxDays"
  },
  "ConstraintFor": {
    "All": "All",
    "Resources": "Resources",
    "Departments": "Departments"
  },
  "ConstraintIf": {
    "Nothing": "Nothing",
    "Nb": "Nb",
    "NbHours": "NbHours",
    "Begin": "Begin",
    "End": "End"
  },
  "ConstraintOp": {
    "Nothing": "Nothing",
    "Equal": "Equal",
    "Inf": "Inf",
    "InfEqual": "InfEqual",
    "Sup": "Sup",
    "SupEqual": "SupEqual",
    "Before": "Before",
    "After": "After"
  },
  "ConstraintType": {
    "Task": "Task",
    "Unavailability": "Unavailability"
  },
  "ConstraintWhat": {
    "LabelAll": "LabelAll",
    "LabelExact": "LabelExact",
    "LabelBegin": "LabelBegin"
  },
  "ConstraintWhen": {
    "Nothing": "Nothing",
    "Day": "Day",
    "Week": "Week",
    "Month": "Month",
    "Year": "Year"
  },
  "CountHolidays": {
    "Five": "Five",
    "Six": "Six"
  },
  "CurrencyCode": {
    "GBP": "GBP",
    "EUR": "EUR",
    "USD": "USD",
    "DEM": "DEM",
    "FRF": "FRF",
    "CHF": "CHF",
    "ARS": "ARS",
    "BRL": "BRL",
    "CLP": "CLP",
    "CRC": "CRC",
    "RUB": "RUB",
    "GTQ": "GTQ",
    "PAB": "PAB",
    "PYG": "PYG",
    "PEN": "PEN",
    "UYU": "UYU",
    "SVC": "SVC",
    "HNL": "HNL",
    "NOK": "NOK",
    "CNY": "CNY",
    "JPY": "JPY",
    "CAD": "CAD"
  },
  "CustomerType": {
    "Individual": "Individual",
    "Company": "Company"
  },
  "DataFieldType": {
    "Date": "Date",
    "Time": "Time",
    "Text": "Text",
    "Numeric": "Numeric",
    "Double": "Double",
    "Combo": "Combo",
    "Link": "Link",
    "Check": "Check",
    "Memo": "Memo",
    "Separator": "Separator",
    "File": "File",
    "Position": "Position",
    "SignatureMobile": "SignatureMobile",
    "Hyperlink": "Hyperlink",
    "ProjectStartDate": "ProjectStartDate",
    "ProjectEndDate": "ProjectEndDate",
    "ProjectDuration": "ProjectDuration",
    "ProjectDeadline": "ProjectDeadline",
    "ProjectDeadlineOver": "ProjectDeadlineOver",
    "Signature": "Signature",
    "ProjectEstimateDuration": "ProjectEstimateDuration",
    "SubProjectEstimateDuration": "SubProjectEstimateDuration"
  },
  "DescriptionFieldType": {
    "Index1": "Index1",
    "Index2": "Index2",
    "EmailBody": "EmailBody",
    "Label": "Label",
    "Mobile": "Mobile",
    "CalendarBody": "CalendarBody",
    "EmailSubject": "EmailSubject",
    "Tooltip": "Tooltip",
    "LabelAssignment": "LabelAssignment",
    "CalendarSubject": "CalendarSubject",
    "Print": "Print",
    "LabelUnavailability": "LabelUnavailability",
    "PrintUnavailability": "PrintUnavailability"
  },
  "DescriptionFieldStyle": {
    "Normal": "Normal",
    "Bold": "Bold",
    "Italic": "Italic",
    "Underline": "Underline"
  },
  "DescriptionFieldColor": {
    "Custom": "Custom",
    "Default": "Default",
    "Destination": "Destination"
  },
  "Destination": {
    "Task0": "Task0",
    "Task2": "Task2",
    "Task3": "Task3",
    "Task4": "Task4",
    "Task5": "Task5",
    "Equipment0": "Equipment0",
    "Customer1": "Customer1",
    "MaterialResource1": "MaterialResource1",
    "MaterialResource2": "MaterialResource2",
    "MaterialResource3": "MaterialResource3",
    "Project0": "Project0",
    "HumanResource1": "HumanResource1",
    "HumanResource2": "HumanResource2",
    "Task1": "Task1",
    "HumanResource3": "HumanResource3",
    "Customer0": "Customer0",
    "HumanResource0": "HumanResource0",
    "Customer2": "Customer2",
    "MaterialResource0": "MaterialResource0",
    "Customer3": "Customer3",
    "Project1": "Project1",
    "Project2": "Project2",
    "SubProject0": "SubProject0",
    "Project3": "Project3"
  },
  "DestinationType": {
    "Task": "Task",
    "Customer": "Customer",
    "Equipment": "Equipment",
    "Resource": "Resource",
    "Project": "Project",
    "SubProject": "SubProject"
  },
  "DoMode": {
    "None": "None",
    "End": "End",
    "Duration": "Duration"
  },
  "EffActionType": {
    "Email": "Email",
    "Sms": "Sms",
    "MicrosoftOutlook": "MicrosoftOutlook",
    "GoogleCalendar": "GoogleCalendar"
  },
  "EffIfType": {
    "Category": "Category",
    "Status": "Status"
  },
  "EffIfOp": {
    "IsIn": "IsIn",
    "BecomesIn": "BecomesIn"
  },
  "EffSourceType": {
    "Customer": "Customer",
    "Resource": "Resource",
    "Project": "Project",
    "Status": "Status",
    "ResourceIn": "ResourceIn",
    "ProjectIn": "ProjectIn",
    "TaskIn": "TaskIn",
    "Assignment": "Assignment",
    "Unavailability": "Unavailability",
    "Task": "Task"
  },
  "EffStepType": {
    "Start": "Start",
    "End": "End",
    "Insert": "Insert",
    "Delete": "Delete",
    "Unperiodize": "Unperiodize",
    "Update": "Update"
  },
  "EffSubjectType": {
    "Assignment": "Assignment",
    "Unavailability": "Unavailability",
    "Task": "Task"
  },
  "EffTargetType": {
    "Customer": "Customer",
    "Resource": "Resource",
    "User": "User",
    "Account": "Account"
  },
  "HistoryOp": {
    "Insert": "Insert",
    "Delete": "Delete",
    "Email": "Email",
    "Invitation": "Invitation",
    "Unperiodize": "Unperiodize",
    "Session": "Session",
    "Update": "Update"
  },
  "HistoryType": {
    "Assignment": "Assignment",
    "Customer": "Customer",
    "SessionDesktop": "SessionDesktop",
    "Unavailability": "Unavailability",
    "SessionMobile": "SessionMobile",
    "Project": "Project",
    "Resource": "Resource",
    "Task": "Task",
    "SessionWebAccess": "SessionWebAccess"
  },
  "InRootType": {
    "Customer": "Customer",
    "Project": "Project",
    "Resource": "Resource"
  },
  "JoinStatus": {
    "Invited": "Invited",
    "Connected": "Connected"
  },
  "JsonWritingType": {
    "None": "None",
    "Normal": "Normal",
    "KeyLabel": "KeyLabel",
    "String": "String",
    "Data": "Data"
  },
  "LicenseStatus": {
    "Other": "Other",
    "Evaluation": "Evaluation",
    "Ok": "Ok",
    "NoExpirationDate": "NoExpirationDate",
    "WrongDatabase": "WrongDatabase",
    "WrongMachine": "WrongMachine",
    "ResourceCount": "ResourceCount",
    "LicenseCount": "LicenseCount",
    "Expired": "Expired",
    "Empty": "Empty",
    "Corrupted": "Corrupted"
  },
  "LinkRefType": {
    "Assignment": "Assignment",
    "Customer": "Customer",
    "Unavailability": "Unavailability",
    "Project": "Project",
    "Resource": "Resource",
    "Task": "Task"

  },
  "NotificationType": {
    "None": "None",
    "TaskInsert": "TaskInsert",
    "TaskUpdate": "TaskUpdate",
    "UnavailabilityInsert": "UnavailabilityInsert",
    "UnavailabilityUpdate": "UnavailabilityUpdate"
  },
  "OneOrMoreCustomers": {
    "OneCustomer": "OneCustomer",
    "MoreCustomer": "MoreCustomer"
  },
  "OneOrMoreResources": {
    "OneResource": "OneResource",
    "MoreResource": "MoreResource"
  },
  "RecurrenceDaily": {
    "AllThe": "AllThe",
    "AllWorkingDays": "AllWorkingDays"
  },
  "RecurrenceMonthly": {
    "Date": "Date",
    "Day": "Day"
  },
  "RecurrenceMonthlyDayWhich": {
    "First": "First",
    "Second": "Second",
    "Third": "Third",
    "Fourth": "Fourth",
    "Last": "Last"
  },
  "RecurrenceRange": {
    "NoEndDate": "NoEndDate",
    "EndThe": "EndThe"
  },
  "RecurrenceType": {
    "Daily": "Daily",
    "Weekly": "Weekly",
    "Monthly": "Monthly",
    "Yearly": "Yearly"
  },
  "ResourceType": {
    "Human": "Human",
    "Material": "Material",
    "ToPlan": "ToPlan",
    "Extern": "Extern"
  },
  "StatusType": {
    "Task": "Task",
    "Unavailability": "Unavailability"
  },
  "SyncType": {
    "_Google": "_Google",
    "Microsoft": "Microsoft",
    "Google": "Google"
  },
  "TaskType": {
    "Default": "Default",
    "Duration": "Duration",
    "Time": "Time"
  },
  "Title": {
    "Miss": "Miss",
    "Mr": "Mr",
    "Ms": "Ms"
  },
  "TimeLapseUnit": {
    "Day": "Day",
    "Week": "Week",
    "Month": "Month",
    "Year": "Year"
  },
  "TypeHatch": {
    "BDIAGONAL": "BDIAGONAL",
    "CROSS": "CROSS",
    "DIAGCROSS": "DIAGCROSS",
    "FDIAGONAL": "FDIAGONAL",
    "HORIZONTAL": "HORIZONTAL",
    "VERTICAL": "VERTICAL"
  },
  "WorkCapacity": {
    "Hours": "Hours",
    "Slots": "Slots"
  }
},
...

e) Langues des réponses

La langue voulue dans les textes de réponse tels que les messages d'erreur peut être spécifiée dans l'en-tête "Accept-Language".

Accept-Language: fr

Les langues disponibles dans PlanningPME API et PlanningPME WebAccess sont : allemand (de), anglais (en), danois (da), espagnol (es), finnois (fi), français (fr), italien (it), japonais (ja), néerlandais (nl), norvégien (no), polonais (pl), portugais (pt), russe (ru), suédois (sv).

2/ Exemples de requêtes d'API

Dans les exemples ci-dessous, la clé d'application utilisée est notée "votre_clé", et le jeton d'autorisation"votre_jeton". Veuillez les remplacer par vos propres valeurs.

/api/task

→ Récupérer une liste (complète ou paginée) des tâches avec la méthode GET "/api/task".

GET /votre_marque/api/task?pageIndex=1&pageSize=20&sortInfo=label+ HTTP/1.1
Host: api.planningpme.com
X-APPKEY: votre_clé
Authorization: Bearer votre_jeton

Retourne la seconde page de vingt tâches dans un tableau trié par ordre croissant sur le libellé.

{
  "totalItems": 97,
  "items": [
    {
      "key": 756,
      "label": "Cours d'anglais pour enfant",
      "type": 1467,
      "style": {
        "backgroundColor": "#65A18D",
        "color": "#000000"
      }
    },
	...
    {
      "key": 131,
      "label": "Coaching",
      "type": 1467,
      "style": {
        "backgroundColor": "#214DE9",
        "color": "#000000"
      }
    }
  ]
}

→ Récupérer le détail d'une tâche avec la méthode GET "/api/task/{id}".

GET /votre_marque/api/task/756 HTTP/1.1
Host: api.planningpme.com
X-APPKEY: votre_clé
Authorization: Bearer votre_jeton

Retourne le détail de la tâche d'identifiant 756.

{
  "key": 756,
  "label": "Cours d'anglais pour enfant",
  "type": 1467,
  "style": {
    "backgroundColor": "#65A18D",
    "color": "#000000"
  },
  "skills": [
    [
      {
        "key": 12,
        "name": "Enfant",
        "label": "Pédagogie > Enfant",
        "level": 1,
        "domain": {
          "key": 4,
          "label": "Pédagogie"
        }
      },
      {
        "key": 83,
        "name": "Anglais",
        "label": "Langue > Anglais",
        "level": 1,
        "domain": {
          "key": 4,
          "label": "Langue"
        }
      }
    ]
  ]
}