PlanningPME API - Documentação do desenvolvedor

Interligue os seus dados de planeamento com o resto do seu sistema de informação.
PlanningPME permite o acesso de leitura e escrita à sua base de dados através de uma API dedicada. A API PlanningPME segue o padrão de desenvolvimento actual (implementação REST e transporte de dados em formato JSON) para uma programação simples das suas sincronizações e integrações.

Este documento irá informá-lo sobre o assunto:

Como determinar o seu endereço API do PlanningPME ?
Onde encontrar a sua documentação interactiva ?
Como é implementada a segurança no PlanningPME API ?
Quais são as considerações de dados comuns no PlanningPME API ?
Como fazer os seus primeiros pedidos ao PlanningPME API ?

PlanningPME API é baseado em RESTful princípios, e o formato padrão de transferência de dados é JSON.
Esta documentação é principalmente para programadores. Recomendamos que o leitor se familiarize com a programação JSON REST API antes de ir mais longe.

URL dedicado

Cada cliente PlanningPME tem o seu próprio endereço API dedicado.
Digamos que o seu nome de marca é "MyCompany", deverá provavelmente utilizar a chave de marca "mycompany" (ignorando o caso) para construir o seu endereço API.
Esta chave será anotada como "seu_marca" no resto desta documentação.

O endereço API de base de uma marca será sempre :
https://api.planningpme.com/a sua_marca/
o
https://try.planningpme.com/a sua_marca/

Documentação interactiva

Cada API de marca também apresenta uma documentação interactiva, muito útil para descobrir os seus métodos e modelos de API PlanningPME e construir chamadas API.

Documentação interactiva

Esta documentação está disponível no seguinte endereço :
https://api.planningpme.com/a sua_marca/doc/index
o
https://try.planningpme.com/a sua_marca/doc/index

Estes dois endereços não podem ser chamados sem apresentar uma chave de aplicação.

Nota: se a autenticação da conta estiver activada na sua API, o acesso à documentação interactiva está à distância de um clique na aplicação da conta PlanningPME.

Segurança

1/ Apresentação da chave de aplicação

Necessita de uma chave de aplicação (appkey) para aceder à sua API, identificando assim a aplicação que chama.
Esta appkey está disponível na sua conta PlanningPME (se a autenticação da conta estiver activada na sua API), ou a pedido do suporte.
Para além de garantir o acesso à API, a appkey permite-lhe conceder acesso a um parceiro ou a uma aplicação de nível, trazendo-lhe a sua própria chave para identificar as suas chamadas para a API.

A appkey deve ser sempre passada nos cabeçalhos de uma chamada API, utilizando o cabeçalho dedicado "X-APPKEY".

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

Para aceder à sua documentação interactiva, utilize a appkey como parâmetro de endereço, como no exemplo abaixo.

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

2/ Ficha de utilizador e imitação

A maioria dos pedidos de API deve também apresentar um token de autorização, a fim de determinar o perfil do utilizador que acede aos dados e respeitar as autorizações de utilizador e de grupo definidas na aplicação.

Este token é obtido previamente quando um utilizador é autenticado no endereço /token e permanece válido durante 8 horas.

Os dados enviados para este endereço diferem consoante o modo de autenticação escolhido para a aplicação.

a) Autenticação tradicional

Se estiver activada, a autenticação tradicional é executada colocando o nome de utilizador e a palavra-passe.

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

grant_type=password&username=o seu_nome_de_utilizador&password=a sua_password

b) Autenticação da conta

Se activada, a autenticação da conta é conseguida postando um token de conta de serviço, previamente obtido na aplicação de conta PlanningPME.

API PlannningpmE

Para cada utilizador aqui listado, pode copiar o token da conta de serviço para a área de transferência.

Agora, obtenha um token de autorização da sua API, postando o token de conta copiado (asserção).

POST /a sua_marca/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) Utilização do testemunho de autorização

Em caso de autenticação bem sucedida, o organismo de resposta conterá um elemento JSON como se segue.

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

A propriedade "access_token" contém o token de autorização da API.

Além disso, tal como indicado pela propriedade "token_type", este token é do tipo "bearer". Os pedidos que requerem autorização devem, portanto, apresentar o cabeçalho "Authorization" com o valor "Bearer", como no exemplo abaixo.

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

Utilização de API

1/ Considerações sobre dados comuns

a) Modelos

Os modelos de dados PlanningPME podem ser facilmente descobertos usando a documentação interativa do seu API.

b) Formato da data

O formato de data utilizado pelo API e esperado em cada pedido JSON é formatoISO 8601. Ex:

2018-01-25T18:05:00Z

c) Listas de ordenação

Os métodos GET utilizam frequentemente um parâmetro "sortInfo" para definir a ordem de ordenação da lista completa/paginada devolvida.

Esta informação é composta com o nome de um bem directamente seguido por um sinal + ou -.
Por exemplo, utilizar "label+" para ordenar por ordem ascendente da propriedade "label".

É também possível combinar várias ordens anexando-as.
Por exemplo, utilizar "notValid-label+" para ordenar pela propriedade "notValid" descendente e depois pela propriedade "label" ascendente.

Esteja ciente de que as etiquetas de propriedade são sensíveis a maiúsculas e minúsculas.

d) Enumerações constantes

A lista completa dos enums em uso com a sua versão API é obtida chamando o método "/api/config". Esta lista não tem direito a alteração, excepto em caso de adição futura.

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

Segue-se a lista de enums na versão 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) Linguagem de resposta

A língua utilizada nos textos de resposta, tais como mensagens de erro, pode ser especificada com o cabeçalho "Accept-Language".

Aceitar-Língua: pt

As línguas disponíveis no PlanningPME API e no PlanningPME WebAccess são: alemão (de), inglês (en), dinamarquês (da), espanhol (es), finlandês (fi), francês (fr), italiano (it), japonês (ja), neerlandês (nl), norueguês (no), polaco (pl), português (pt), russo (ru), sueco (sv).

2/ Exemplos de chamadas API

Nos exemplos abaixo, a chave de aplicação utilizada é "your_key" e o token de autorização "your_token". Por favor, substitua-os pelos seus próprios valores.

/api/task

→ Obtenha uma lista completa ou paginada de tarefas com o método GET "/api/task".

GET /a sua_marca/api/task?pageIndex=1&pageSize=20&sortInfo=label+ HTTP/1.1
Host: api.planningpme.com
X-APPKEY: a sua_chave
Authorization: Bearer seu_token

Retorna um conjunto de tarefas contendo a segunda página de 20 tarefas ordenadas por etiqueta descendente.

{
  "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"
      }
    }
  ]
}

→ Obtenha uma tarefa detalhada com o método GET "/api/task/{id}".

GET /a sua_marca/api/task/756 HTTP/1.1
Host: api.planningpme.com
X-APPKEY: votre_clé
Authorization: Bearer seu_token

Retorna uma representação detalhada do objecto da tarefa com 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"
        }
      }
    ]
  ]
}