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

O acesso à sua API requer uma chave que identifique sua aplicação e assegure seu acesso: uma appkey.
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.

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) Autenticação de cliente OAuth

Para abrir sua API a um parceiro ou a uma aplicação de terceiros, é aconselhável criar um cliente OAuth e configurar seus tokens de autenticação.

Gerir os seus acessos OAuth

Uma vez que tenha os seus IDs e token de cliente OAuth, o seu terceiro poderá autenticar-se junto da API e obter um token de autorização da seguinte forma.

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&client_id=id_de_client&assertion=token_de_cliente

d) Utilização do token 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

Abaixo está a lista das constantes de enumeração. - 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) 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"
        }
      }
    ]
  ]
}

/api/oauth

→ Recuperar a lista dos clientes OAuth com o método GET "/api/oauth/client".

GET /a sua_marca/api/oauth/client HTTP/1.1
Host: api.planningpme.com
X-APPKEY: a sua_chave
Authorization: Bearer seu_token
{
  "totalItems": 2,
  "items": [
    {
      "id": "2bc87bded6bf4de7babe8ea5a9452735",
      "name": "backoffice"
    },
    {
      "id": "1601c39ed33a4c4084750356a7f8d7a5",
      "name": "apptest2"
    }
  ]
}

→ Criar um novo cliente OAuth com o método POST "/api/oauth/client".

POST /a sua_marca/api/oauth/client HTTP/1.1
Host: api.planningpme.com
X-APPKEY: votre_clé
Authorization: Bearer seu_token

{
  "name": "apptest3"
}

Retorna o cliente criado e seu identificador.

{
  "id": "22f37990d2304af3a9e20dc4b05efe26",
  "name": "apptest3"
}

→ Criar um novo token OAuth para um cliente dado (aqui "apptest3") e um usuário dado (aqui o usuário cuja chave é 99), com o método POST "/api/oauth/token".

POST /a sua_marca/api/oauth/token HTTP/1.1
Host: api.planningpme.com
X-APPKEY: votre_clé
Authorization: Bearer seu_token

{
  "clientId": "22f37990d2304af3a9e20dc4b05efe26",
  "user": {
    "key": 99
  }
}

Retorna o token criado, sua data de expiração e a afirmação relacionada.

Atenção, a afirmação completa (propriedade "jwt") não poderá mais ser recuperada. Portanto, é aconselhável guardá-la em um local seguro assim que for criada.

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

→ Recuperar a lista dos tokens relacionados a um cliente OAuth com o método GET "/api/oauth/token?clientID={id}".

GET /a sua_marca/api/oauth/token?clientId=2bc87bded6bf4de7babe8ea5a9212735 HTTP/1.1
Host: api.planningpme.com
X-APPKEY: a sua_chave
Authorization: Bearer seu_token
{
  "totalItems": 1,
  "items": [
    {
	  "id": "63d134cf760940e7af7acf16e4890835",
	  "userKey": 99,
	  "expirationDate": "2027-05-14T13:11:49.8116664Z",
	  "resume": "eyJhbGciOiJodHR...wtO_PkdOFllvyNk",
	  "invalid": false
	}
  ]
}