PlanningPME API - Developer documentation
Interconnect your planning data with the rest of your information system.
PlanningPME allows read and write access to your database through a dedicated API.
The PlanningPME API follows the current development standard (REST implementation and JSON formatted data transport) for a simple programming of your synchronisations and integrations.
This document will inform you about:
How to determine your PlanningPME API address ?Where to find your interactive documentation ?
How the security is implemented in PlanningPME API ?
What are the common data considerations in PlanningPME API ?
How to make your first requests to PlanningPME API ?
PlanningPME API is based on RESTful principles, and the default data transfer format is JSON.
This documentation is mainly for developers. We recommend the reader to familiarise with JSON REST API programming before going further.
Dedicated URL
Each PlanningPME client has its own dedicated API address.
Say your brand name is "MyCompany", you should probably use the brand key "mycompany" (ignoring case) in order to build your API address.
This key will be noted as "your_brand" in the rest of this documentation.
The base API address of a brand will always be :
https://api.planningpme.com/your_brand/
or
https://try.planningpme.com/your_brand/
Interactive documentation
Each brand API also presents an interactive documentation, very useful to discover your PlanningPME API methods and models and build API calls.
This documentation is available at the following address :
https://api.planningpme.com/your_brand/doc/index
or
https://try.planningpme.com/your_brand/doc/index
Those two addresses cannot be called without presenting an application key.
Note: In the event that account authentication is enabled on your API, access to interactive documentation is one click away within the PlanningPME account application.
Security
1/ Application key presentation
Access to your API requires a key that identifies your application and secures its access: an appkey.
This appkey is available in your PlanningPME account (if account authentication is enabled on your API), or on demand to the support.
The appkey should always be passed in the headers of an API call, by using dedicated "X-APPKEY" header.
GET /your_brand/api/config HTTP/1.1 Host: api.planningpme.com X-APPKEY: e991573da5ffd4sab9b1e26bc6b64aac
To access your interactive documentation, use the appkey as an address parameter, as in the example below.
https://api.planningpme.com/your_brand/doc/index?appkey=e991573da5ffd4sab9b1e26bc6b64aac
2/ User token and impersonation
Most API requests must also have an authorization token, in order to determine the profile of the user accessing the data, and respect the user and group permissions defined in the application.
This token is previously obtained when authenticating a user at /token, and remains valid for 8 hours.
The data posted to this address differs depending on the authentication mode chosen for your application.
a) Classic authentication
If enabled, conventional authentication is achieved by posting the username and password.
POST /your_brand/token HTTP/1.1 Host: api.planningpme.com X-APPKEY: e991573da5ffd4sab9b1e26bc6b64aac Content-Type: application/x-www-form-urlencoded grant_type=password&username=your_username&password=your_password
b) Account authentication
If enabled, account authentication is done by posting a service account token, previously obtained in the PlanningPME account application.
For each user listed here, you can copy the service account token to your clipboard.
Now get an authorization token from your API, by posting the copied account token (assertion).
POST /your_brand/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=account_token
c) OAuth Client Authentication
In order to open your API to a partner or third-party application, it is recommended that you create an OAuth client, and set up its authentication tokens.
Once in possession of their OAuth client id and token, your third party will be able to authenticate with the API and obtain an authorisation token as follows.
POST /your_brand/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&client_id=id_of_client&assertion=token_of_client
d) Use of the authorisation token
In the case of successful authentication, the response body will contain a JSON element as follows.
{ "access_token": "KTuZYDLG2qjUMqMVXDuiP9giFbqDXstESvpUWzBFLpkfdlMiB3PD5s2K7En-3o39u56hpr_DlyjEc_...3Is0gcH", "token_type": "bearer", "expires_in": 86399, "username": "your_username" }
The “access_token” property contains the API authorization token.
Also, as indicated by the "token_type" property, this token is of type "bearer". Requests requiring authorization must therefore present the "Authorization" header with the value "Bearer", as in the example below.
POST /your_brand/api/customer HTTP/1.1 Host: api.planningpme.com X-APPKEY: e991573da5ffd4sab9b1e26bc6b64aac Authorization: Bearer KTuZYDLG2qjUMqMVXDuiP9giFbqDXstESvpUWzBFLpkfdlMiB3PD5s2K7En-3o39u56hpr_DlyjEc_...3Is0gcH
API usage
1/ Common data considerations
a) Models
PlanningPME data models can be easily discovered by using the interactive documentation of your API.
b) Date format
Date format used by the API and expected in each JSON request is ISO 8601 format. Ex:
2018-01-25T18:05:00Z
c) Sorting lists
GET methods often use a "sortInfo" parameter to set the sorting order of the full/paginated list returned.
This info is composed with the name of a property directly followed by a + or - sign.
For instance use "label+" in order to sort by ascending "label" property.
It is also possible to combine multiple orders by appending them.
For instance use "notValid-label+" to sort by descending "notValid" property then by ascending "label" property.
Be aware that property labels are case sensitive.
d) Constant enumerations
Complete list of enums in use with your API version is obtained by calling the "/api/config" method. This list is not entitled to change except future addition.
GET /your_brand/api/config HTTP/1.1 Host: api.planningpme.com X-APPKEY: e991573da5ffd4sab9b1e26bc6b64aac
Below is the list of enumeration constants. - v4.7.0.28
{ ... "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", "DoSearch": "DoSearch", "SwitchLabel": "SwitchLabel", "OAuthClients": "OAuthClients", "Buttoned": "Buttoned" }, "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", "SAR": "SAR" }, "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", "Multi": "Multi", "Location": "Location" }, "DescriptionFieldType": { "Index1": "Index1", "Index2": "Index2", "EmailBody": "EmailBody", "Label": "Label", "Mobile": "Mobile", "CalendarBody": "CalendarBody", "EmailSubject": "EmailSubject", "Tooltip": "Tooltip", "LabelAssignment": "LabelAssignment", "CalendarSubject": "CalendarSubject", "Print": "Print", "ToPlan": "ToPlan", "LabelUnavailability": "LabelUnavailability", "PrintUnavailability": "PrintUnavailability", "HeaderCustomer": "HeaderCustomer", "CaptionCustomer": "CaptionCustomer", "HeaderProject": "HeaderProject", "CaptionProject": "CaptionProject", "HeaderResource": "HeaderResource", "CaptionEquipment": "CaptionEquipment" }, "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", "Unavailability0": "Unavailability0", "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", "Unavailability": "Unavailability" }, "DoMode": { "None": "None", "End": "End", "Duration": "Duration" }, "EffActionType": { "Email": "Email", "Sms": "Sms", "MicrosoftOutlook": "MicrosoftOutlook", "GoogleCalendar": "GoogleCalendar" }, "EffGapUnit": { "Minute": "Minute", "Hour": "Hour", "Day": "Day", "Week": "Week", "Month": "Month", "Year": "Year" }, "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", "Creator": "Creator" }, "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", "User": "User", "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", "Lucca": "Lucca" }, "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) Response language
The language used in response texts such as error messages can be specified with the "Accept-Language" header.
Accept-Language: en
The languages available in PlanningPME API and PlanningPME WebAccess are: German (de), English (en), Danish (da), Spanish (es), Finnish (fi), French (fr), Italian (it), Japanese (ja), Dutch(nl), Norwegian (no), Polish (pl), Portuguese (pt), Russian (ru),Swedish (sv).
2/ Examples of API calls
In the examples below, the application key used is noted "your_key", and the authorization token "your_token". Please replace them with your own values.
/api/task
→ Get a full or paginated list of tasks with GET "/api/task" method.
GET /your_brand/api/task?pageIndex=1&pageSize=20&sortInfo=label+ HTTP/1.1 Host: api.planningpme.com X-APPKEY: your_key Authorization: Bearer your_token
Returns an array of tasks containing second page of 20 tasks ordered by descending label.
{ "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" } } ] }
→ Get a detailed task with GET "/api/task/{id}" method.
GET /your_brand/api/task/756 HTTP/1.1 Host: api.planningpme.com X-APPKEY: votre_clé Authorization: Bearer your_token
Returns a detailed task object representation of the task with id 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" } } ] ] }
/api/oauth
→ Retrieve the list of OAuth clients with the GET method "/api/oauth/client".
GET /your_brand/api/oauth/client HTTP/1.1 Host: api.planningpme.com X-APPKEY: your_key Authorization: Bearer your_token
{ "totalItems": 2, "items": [ { "id": "2bc87bded6bf4de7babe8ea5a9452735", "name": "backoffice" }, { "id": "1601c39ed33a4c4084750356a7f8d7a5", "name": "apptest2" } ] }
→ Create a new OAuth client with the "/api/oauth/client" POST method.
POST /your_brand/api/oauth/client HTTP/1.1 Host: api.planningpme.com X-APPKEY: votre_clé Authorization: Bearer your_token { "name": "apptest3" }
Return the created client and its ID.
{ "id": "22f37990d2304af3a9e20dc4b05efe26", "name": "apptest3" }
→ Create a new OAuth token for a given client (here "apptest3") and a given user (here the user whose key is 99), with the POST method "/api/oauth/token".
POST /your_brand/api/oauth/token HTTP/1.1 Host: api.planningpme.com X-APPKEY: votre_clé Authorization: Bearer your_token { "clientId": "22f37990d2304af3a9e20dc4b05efe26", "user": { "key": 99 } }
Return the created token, its expiration date, and the related assertion.
Be careful, the full assertion (property "jwt") will no longer be retrievable. It is therefore advisable to save it in a safe place as soon as it is created.
{ "id": "63d134cf760940e7af7acf16e4890835", "userKey": 99, "expirationDate": "2027-05-14T13:11:49.8116664Z", "resume": "eyJhbGciOiJodHR...wtO_PkdOFllvyNk", "invalid": false, "jwt": "eyJhbGciOiJodHRwOi8vd3d3FgdfLm9yZy8yMDAxLzA0L3htbGRzaWctbW9yZSNobWFjLXNoYTI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxIiwidW5pcXVlX25hbWUiOiI2M2QxMzRjZjc2MDk0MGU3YWY3YWNmMTZlODk1MDgzNSIsImp0aSI6ImRkOGM0OTZlLTBlZjYtNDQ5MS04MGNkLTM1YzRkODIxMGZlZSIsImlhdCI6MTc0NzIlkj345SwibmJmIjoxNzQ3MjI4MzA5LCJleHAiOjE4MTAzMDAzMDksImlzcyI6Imh0dHBzOi8vYXBpLnBsYW5uaW5ncG1lLmNvbSIsImF1ZCI6IjMzZjM3OTkwZDIzMDRhZjNhOWUyMGRjNGIwNWVmZTI2In0.9f-X_bc4Ca8gTyQ_FZJsAvdH0gkWwtO_PkdOFllvyNk" }
→ Retrieve the list of tokens linked to an OAuth client with the GET method "/api/oauth/token?clientID={id}".
GET /your_brand/api/oauth/token?clientId=2bc87bded6bf4de7babe8ea5a9212735 HTTP/1.1 Host: api.planningpme.com X-APPKEY: your_key Authorization: Bearer your_token
{ "totalItems": 1, "items": [ { "id": "63d134cf760940e7af7acf16e4890835", "userKey": 99, "expirationDate": "2027-05-14T13:11:49.8116664Z", "resume": "eyJhbGciOiJodHR...wtO_PkdOFllvyNk", "invalid": false } ] }