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 synchronizations and integrations.

This document will inform you about:

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 familiarize 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

Interactive documentation

Those two addresses cannot be called without presenting an application key.

Security

1/ Application key presentation

You need an application key (appkey) in order to access your API, thus identifying the caller application.
This appkey is available in your PlanningPME account or on demand to our support.
In addition to securing API access, the appkey let you grant access to a partner or a tier-application, by bringing them their own key to identify their calls to the API.

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

In order to access your interactive documentation, use your appkey as a query parameter, like in the sample below:

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

2/ User token and impersonation

Most of the API calls should be user-authenticated, in order to use impersonation during the data access and respect defined user and group authorizations.

An authorization is granted by submitting user's name and password to the API, then getting a token that will be used to authenticate or impersonate any subsequent API call.

Getting an authorization token is always done by posting these data to the "/token" url.

POST /votre_marque/token HTTP/1.1
Host: api.planningpme.com
X-APPKEY: e991573da5ffd4sab9b1e26bc6b64aac

grant_type=password&username=your_username&password=your_password

In the case of successful authentication, the response body will contain a JSON element as follows.

{
    "access_token": "KTuZYDLG2qjUMqMVXDuiP9giFbqDXstESvpUWzBFLpkfdlMiB3PD5s2K7En-3o39u56hpr_DlyjEc_oUzBbR0PoEQfOb_O7m5BrLz9vwDzV_YjtRRrQ_7QxYnxO9uZs38SJ7UxTjDZgx_JKRUoZ3Wk6RNnXRpSkcmOrINvJLDMYXptYFiTjn9Op-vkPdtOKFp9M1cNjrH1ho2uaRBpUUMH_vJ-8W8mTH9wgFrJlecGIpntb7jet2GYpGs3Is0gcH",
    "token_type": "bearer",
    "expires_in": 86399,
    "username": "your_username"
}

Value of the "access_token" property should then be used in subsequent authorized requests to the API.
And as indicated by the "token_type" property, this value is a bearer token.

Any subsequent authorized call should then present the "Authorization" header with this specific "Bearer" value.

POST /your_brand/api/customer HTTP/1.1
Host: api.planningpme.com
X-APPKEY: e991573da5ffd4sab9b1e26bc6b64aac
Authorization: Bearer KTuZYDLG2qjUMqMVXDuiP9giFbqDXstESvpUWzBFLpkfdlMiB3PD5s2K7En-3o39u56hpr_DlyjEc_oUzBbR0PoEQfOb_O7m5BrLz9vwDzV_YjtRRrQ_7QxYnxO9uZs38SJ7UxTjDZgx_JKRUoZ3Wk6RNnXRpSkcmOrINvJLDMYXptYFiTjn9Op-vkPdtOKFp9M1cNjrH1ho2uaRBpUUMH_vJ-8W8mTH9wgFrJlecGIpntb7jet2GYpGs3Is0gcH

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 the list enums for version 4.1.1.117 of the API.

{
  ...
  enums: {
    "Access": {
      "All": 0,
      "Read": 82,
      "Write": 87
    },
    "BillingType": {
      "Package": 0,
      "Unit": 1
    },
    "ConstraintAction": {
      "NoTaskBeforeNbHours": 0,
      "NoTaskBeforeNbDays": 1,
      "NoTaskSamePeriod": 2,
      "NbMaxHours": 3,
      "NbMax": 4,
      "DurationMaxHours": 5,
      "DurationMaxDays": 6
    },
    "ConstraintFor": {
      "All": 0,
      "Resources": 1,
      "Departments": 2
    },
    "ConstraintIf": {
      "Nothing": 0,
      "Nb": 1,
      "NbHours": 2,
      "Begin": 3,
      "End": 4
    },
    "ConstraintOp": {
      "Nothing": 0,
      "Equal": 1,
      "Inf": 2,
      "InfEqual": 3,
      "Sup": 4,
      "SupEqual": 5,
      "Before": 6,
      "After": 7
    },
    "ConstraintType": {
      "Task": 0,
      "Unavailability": 1
    },
    "ConstraintWhat": {
      "LabelAll": 0,
      "LabelExact": 1,
      "LabelBegin": 2
    },
    "ConstraintWhen": {
      "Nothing": 0,
      "Day": 1,
      "Week": 2,
      "Month": 3,
      "Year": 4
    },
    "CustomerType": {
      "Individual": 1026,
      "Company": 1027
    },
    "DataFieldType": {
      "Date": 1,
      "Time": 2,
      "Text": 3,
      "Numeric": 4,
      "Double": 5,
      "Combo": 6,
      "Link": 7,
      "Check": 8,
      "Memo": 9,
      "Separator": 10,
      "File": 11,
      "Position": 12,
      "SignatureMobile": 13,
      "Hyperlink": 16,
      "Startdate": 17,
      "Enddate": 18,
      "Duration": 19,
      "Signature": 20
    },
    "DescriptionFieldType": {
      "Index1": 49,
      "Index2": 50,
      "EmailBody": 69,
      "Label": 76,
      "Mobile": 77,
      "Calendar": 79,
      "EmailSubject": 83,
      "Tooltip": 84
    },
    "Destination": {
      "Task0": 48,
      "Task2": 50,
      "Task3": 51,
      "Task4": 52,
      "Task5": 53,
      "Equipment0": 65,
      "Customer1": 67,
      "MaterialResource1": 77,
      "MaterialResource2": 78,
      "MaterialResource3": 79,
      "Project0": 80,
      "HumanResource1": 82,
      "HumanResource2": 83,
      "Task1": 84,
      "HumanResource3": 86,
      "Customer0": 97,
      "HumanResource0": 98,
      "Customer2": 99,
      "MaterialResource0": 100
    },
    "DestinationType": {
      "Task": 0,
      "Customer": 1,
      "Equipment": 2,
      "Resource": 3,
      "Project": 4
    },
    "HistoryOp": {
      "Insert": 65,
      "Delete": 68,
      "Email": 69,
      "Invitation": 73,
      "Update": 85
    },
    "HistoryType": {
      "Customer": 67,
      "Unavailability": 73,
      "Project": 80,
      "Resource": 82,
      "Task": 84
    },
    "JsonWritingType": {
      "Normal": 1,
      "KeyLabel": 2,
      "String": 3,
      "Data": 4
    },
    "LicenseStatus": {
      "Other": 0,
      "Evaluation": 1,
      "Ok": 2,
      "NoExpirationDate": -8,
      "WrongDatabase": -7,
      "WrongMachine": -6,
      "ResourceCount": -5,
      "LicenseCount": -4,
      "Expired": -3,
      "Empty": -2,
      "Corrupted": -1
    },
    "NotificationType": {
      "None": 0,
      "TaskInsert": 1,
      "TaskUpdate": 2,
      "UnavailabilityInsert": 4,
      "UnavailabilityUpdate": 8
    },
    "OneOrMoreCustomers": {
      "OneCustomer": 1422,
      "MoreCustomer": 1423
    },
    "OneOrMoreResources": {
      "OneResource": 1076,
      "MoreResource": 1077
    },
    "RecurrenceDaily": {
      "AllThe": 1255,
      "AllWorkingDays": 1256
    },
    "RecurrenceMonthly": {
      "Date": 1258,
      "Day": 1259
    },
    "RecurrenceMonthlyDayWhich": {
      "First": 0,
      "Second": 1,
      "Third": 2,
      "Fourth": 3,
      "Last": 4
    },
    "RecurrenceRange": {
      "NoEndDate": 1250,
      "EndThe": 1252
    },
    "RecurrenceType": {
      "Daily": 1246,
      "Weekly": 1247,
      "Monthly": 1248,
      "Yearly": 1249
    },
    "ResourceFilter": {
      "All": 40960,
      "Human": 45056,
      "Material": 49152,
      "ToPlan": 53248
    },
    "ResourceType": {
      "Human": 1035,
      "Material": 1036,
      "ToPlan": 1537
    },
    "TaskType": {
      "Default": 1467,
      "Duration": 1468,
      "Time": 1469
    },
    "Title": {
      "Miss": 0,
      "Mr": 1,
      "Ms": 2
    },
    "TimeLapseUnit": {
      "Day": 0,
      "Week": 1,
      "Month": 2,
      "Year": 3
    },
    "TypeHatch": {
      "BDIAGONAL": 0,
      "CROSS": 1,
      "DIAGCROSS": 2,
      "FDIAGONAL": 3,
      "HORIZONTAL": 4,
      "VERTICAL": 5
    },
    "WorkCapacity": {
      "Hours": 1590,
      "Slots": 1591
    }
  }
  ...

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: danish (da), dutch (nl), english (en), finnish (fi), french (fr), german (de), italian (it), norwegian (no), polish (pl), russian (ru), spanish (es), swedish (sv).

2/ Examples of API calls

In the examples below the application key will be noted as "your_key" and the bearer token as "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"
        }
      }
    ]
  ]
}