# Welcome to Peoplelogic.dev

The developer infrastructure for AI-native talent solutions.

Peoplelogic.dev is the developer infrastructure for AI-native talent solutions.  We provide composable talent management modules (with universal access to dozens of talent management systems), autonomous HR and WorkTech agent SDKs, and the developer-first infrastructure you need to build the future of work.

<p align="center"><a href="/pages/zknBmCnjlYxMenXmmFUu" class="button primary" data-icon="square-terminal">API Documentation</a> <a href="/pages/PGIy8QW2WqbBzLKQAPPX" class="button secondary" data-icon="puzzle">Composable Talent Platform</a> <a href="/pages/kPKBy136ZX2NR0rimHd6" class="button secondary" data-icon="microchip-ai">Agent SDK</a> <a href="/pages/nlWbOmjYSNdpK0SYYY5I" class="button secondary" data-icon="book-open">Tutorials</a></p>


# Key Concepts

As part of using our APIs and SDKs there are a few key concepts that you should be familiar with.  These are described in more detail in the subsequent pages.  Don't worry if you miss something - we try to point to these as we talk about them in the actual documentation. &#x20;

If you think we're missing something, feel free to message us in your Slack channel if you're a customer or reach out to our support team at <support@peoplelogic.dev>!


# Agents

Human in the loop or autonomous AI to help you get more done.

AI agents are specialized sets of AI tools that can be set to task to accomplish very specific tasks.  Within Peoplelogic.dev you can create and host agentic workflows with many single agents or a team of agents working together to accomplish a task.

### What is available to the agents?

Peoplelogic.dev's agent SDK aims to provide you with everything you need to be able to build commercial agentic workflows.  As such, all agents come with the ability to talk to the Universal Talent API and Merge.dev along with the ability to build your own custom Tools for each agent. &#x20;

The SDK also includes a common tool layer to handle scheduled tasks, working with email or Slack notifications, and working with file uploads.

### Agent Teams

Peoplelogic.dev's Agent SDK supports building and interacting with teams of agents in addition to a single agent. &#x20;

With Agent Teams you interact with a Coordinator Agent that knows about the rest of the team (Worker Agents) and the tools that are available to your agents.  It handles assignment to the appropriate agents and verifying that the user has given all the inputs the agents need to execute appropriately.

You can also make the Coordinator Agent be a Worker Agent so that it can handle its own tasks.  For example, it might be the one that handles high level strategic work (a VP role) in addition to delegating more tactical work or analysis work to other agents.

### How do I access my agents?

The Agent SDK provides the foundation to setup access to your agents directly in the flow of work, from a dedicated API to email to Slack or Teams and more.  To enable this access you usually need to give your agent specific keys to the services (such as Slack) but once this is provided the access is built-in.

{% hint style="info" %}
&#x20;A pre-built web interface and components to integrate with Javascript-based UIs will be available soon.
{% endhint %}

You can also see the list of agents that you have deployed through your management dashboard.

For more information - read the guide [Getting Started with the Talent Agent SDK.](/guides/getting-started-with-the-talent-agent-sdk)


# Apps

Connections to other applications - because nothing exists in a silo.

In the Peoplelogic.dev platform, an App represents a connection to another system - whether that's external to your instance or another part of our infrastructure.  Here are a few examples:

* Connected Slack account
* Stripe customer ID
* [HRIS connection via Merge](/guides/synchronizing-org-charts)
* [A Performance Management system](/guides/getting-started-with-the-composable-talent-platform/universal-talent-api/performance-management)
* Linking an organization to an SSO system

### Storing data from an App

When you connect to an application, there are typically two different types of data - sensitive and non-sensitive.  While this seems intuitive, you should distinguish between things like a Stripe customer ID or a Slack channel ID and a Merge Linked Account Token. &#x20;

Within the App API, we make a clear distinction between the two types - providing `secretData` and `appData` storage. The secretData storage is encrypted within the database (beyond simply encrypting at rest), while appData is not.  You use both storage mechanisms the same way - by PATCHing your App via the API.  Let's take a look.

### Creating and using an App

First, we use the API to create a simple App within the current Organization.  As you can see, we are storing sensitive data (in this case, the returned Merge linked account token) in the secretData.

```http
POST https://api.peoplelogic.dev/api/v1/app
Content-Type: application/json
Authorization: Bearer {{demoOrgToken}}

{
  "type": "pl:sync:merge:hris",
  "internal": true,
  "name": "Demo Connection with MS Entra",
  "externalId": "abc",
  "secretData": {
    "accountToken": "{{entraToken}}"
  }
}
```

This returns a 201 response code when its successful.  You can may have many App instances of the same type, but the combination of type and externalId must be unique.

To edit an App, just execute a PATCH call against the same API endpoint using the ID you received from the previous call.  Here's an example:

```http
PATCH https://api.peoplelogic.dev/api/v1/app/{{previousAppId}}
Content-Type: application/json
Authorization: Bearer {{demoOrgToken}}

{
  "appData": {
    "demo": "Hi there!"
  }
}
```

You'll receive a 200 response code when successful and your data will be updated!


# Conversation

A conversation is simply a holder of messages back and forth between a user and your agents.  Conversations have a name for easy lookup and are also the anchor point for the agent ChatMemory. &#x20;

When using things like Slack or email to interact with your agents, the conversation creation and management are handled automatically.


# Flows

Coming soon!


# Getting Started with the Composable Talent Platform

Unlock your talent data - integrate Goals, Compensation, Skills, Reviews, and more.

The Peoplelogic.dev Composable Talent Platform consists of 2 main components:

1. The Universal Talent API
2. The Talent Application Platform

### The Universal Talent API

Whether you want to build your own talent management tool or integrate with existing ones, we provide a single common interface for all the functionality you need across several categories including:

* [Performance Management](/guides/getting-started-with-the-composable-talent-platform/universal-talent-api/performance-management) - through this API you can easily integrate your performance data into new workflows and tools.  Build dashboards, create Agents, automate status updates - across tools and all through one universal API.
* Learning Management *- Coming Soon*
* Skills Management *- Coming Soon*
* Compensation *- Coming Soon*

### The Talent Application Platform (coming soon!)

The talent application platform allows developers to build on the Peoplelogic foundational components that power the Universal API, Peoplelogic Impact and Peopleogic Nova.  These include:

* Managed organizational charts in a powerful directory
* Audit trails
* Advanced version management
* Task management
* Assignments
* Advaned permissions
* Webhooks
* and more coming daily...

### The Talent Cloud

Peoplelogic.dev also provides the scalable cloud infrastructure to host your talent application or talent agents, allowing you to serve thousands of employees within your organization or millions of users around the globe. We discuss [managing your Talent Cloud](/guides/managing-your-cloud) in more detail later.


# What is a composable talent platform?

Composable talent platforms are an evolution of the headless HR concept, focusing on creating modular, interchangeable talent components that can be reassembled to meet specific business needs.  These composable platforms are defined by:

* **Modularity:** Each talent function exists as an independent, self-contained component
* **Interoperability:** Components can easily connect and communicate with each other
* **Flexibility:** Organizations can swap out or upgrade individual components without disrupting the entire system
* **Best-of-Breed:** Freedom to choose specialized solutions for specific talent functions

Peoplelogic.dev provides a universal talent API that also includes a composable talent platform, giving you the power to expand your own functionality or leverage data from your other talent tools that were previously locked in silos.

### More resources

* [Why the Future of Talent Platforms is API-First and Developer-Driven](https://docs.peoplelogic.dev/)
* [How Composable Talent Platforms Enable Better Employee Experiences](https://peoplelogic.dev/blog/how-composable-talent-platforms-enable-better-employee-experiences)


# How to use the platform

REST, Java/Kotlin, Python, Typescript and more.

There are multiple ways to quickly get started with the platform. &#x20;

The first, and most flexible, is to leverage the API directly.  To get started, [just navigate to the API documentation](/api/api-endpoints) to learn more about API endpoints, authentication and the API calls.

If client libraries are more your style, we offer several generated from our OpenAPI specification that also generates the API documentation:

* Java/Kotlin (coming soon!)
* Python (coming soon!)
* Typescript (coming soon!)

Let us know which languages you'd like to see supported by emailing <support@peoplelogic.dev>.


# Connecting integrations

All integrations supported by Composable Talent are added the same way to your account.  These integrations are just Apps and so [are managed the same way as any other](/guides/key-concepts/apps#storing-data-from-an-app).  Remember, you'll need Organization admin or IT Admin permissions to save these apps.

For most you will need at minimum an API key and in many cases you will also need an Access token.  Let's take a look at the general use case for one of the integrations:

```http
POST https://api.peoplelogic.dev/api/v1/app
Content-Type: application/json
Authorization: Bearer {{demoOrgToken}}

{
  "type": "pl:sync:betterworks",
  "internal": false,
  "name": "Acme Corp Betterworks",
  "externalId": "acme-betterworks",
  "secretData": {
    "apiKey": "{{betterWorksApiKey}}"
  }
}
```

The `externalId` and `type` combination must be unique and the specifics of what goes into `secretData` are dependent on each integration.  We'll cover those in the next section!


# Universal Talent API

Whether you want to build your own talent management tool or integrate with existing ones, we provide a single common interface for all the functionality you need across several categories including:

* [Performance Management](https://docs.peoplelogic.dev/guides/getting-started-with-the-composable-talent-platform/universal-talent-api/performance-management) - through this API you can easily integrate your performance data into new workflows and tools. Build dashboards, create Agents, automate status updates - across tools and all through one universal API.
* Learning Management *- Coming Soon*
* Skills Management *- Coming Soon*
* Compensation *- Coming Soon*


# Performance Management

One single API supporting Goals, Careers, Meetings, and more.

Peoplelogic supports most of the top performance management platforms, but each of the platforms has their own individual nuances - especially related to your API keys - to be aware of.&#x20;

You can mix and match the products below - leverage OKRs from ClickUP, reviews from BetterWorks and IDPs from Peoplelogic IMPACT.  You can even connect multiple systems providing the same functionality.  Peoplelogic.dev sorts out the employee matching and de-duplication where required.

Our team frequently adds new functionality to our integrations, so check this table to verify if a particular system supports a feature you're looking for or feel free to contact our support team at <support@peoplelogic.dev>.

{% hint style="warning" %}
During the initial launch - all integrations except for the provided Peoplelogic.dev HPM will be read-only.
{% endhint %}

<table data-full-width="false"><thead><tr><th width="233.015625"></th><th width="187.61328125" align="center">Employees &#x26; Groups</th><th width="93.27734375" align="center">Goals</th><th align="center">Meetings</th><th align="center">IDPs</th><th align="center">Feedback</th><th align="center">Reviews</th><th align="center">Surveys</th></tr></thead><tbody><tr><td><a href="/pages/MT10z250aaZTNgSLeDvF">Peoplelogic.dev Headless Performance Management</a></td><td align="center">✅</td><td align="center">✅</td><td align="center">✅</td><td align="center">✅</td><td align="center">✅</td><td align="center">✅</td><td align="center">✅</td></tr><tr><td><a href="/pages/zyOwfa7dx6UWRYuyTs6w">Betterworks</a></td><td align="center">✅</td><td align="center">✅</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td></tr><tr><td><a href="/pages/Er80qczQAiLnxR442dm6">ClickUp</a></td><td align="center">✅</td><td align="center">✅</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td></tr><tr><td><a href="/pages/PpQVUz1HnmWEeqrdwzt2">15Five</a></td><td align="center">✅</td><td align="center">✅</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td></tr><tr><td><a href="/pages/lfFcWixzp9gyK1HSH0pT">Perdoo</a></td><td align="center">✅</td><td align="center">✅</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td></tr><tr><td><a href="/pages/5BlTajsrfSHEaH67HWxd">Profit.co</a></td><td align="center">✅</td><td align="center">✅</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td></tr><tr><td><a href="/pages/1TOwEro9xHqs8dUTuw8d">Peoplelogic IMPACT</a></td><td align="center">✅</td><td align="center">✅</td><td align="center">✅</td><td align="center">✅</td><td align="center">✅</td><td align="center">✅</td><td align="center">✅</td></tr><tr><td><a href="/pages/VwhA0S2Zt8RyspaUYd3v">SimpleOKR</a></td><td align="center">✅</td><td align="center">✅</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td></tr><tr><td><a href="/pages/vVUqr6Sfo4B91rfz8lM7">Sloneek</a></td><td align="center">✅</td><td align="center">✅</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td></tr><tr><td><a href="/pages/OHxWp6w3lkchKJjA5vf2">Weekdone</a></td><td align="center">✅</td><td align="center">✅</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td></tr><tr><td><a href="/pages/mS6uPqubtStVTVfDGEMW">Workboard</a></td><td align="center">✅</td><td align="center">✅</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td></tr></tbody></table>

### Coming soon

The integrations below are next on our list to add to the Performance Management category.  If you are interested in being a beta user of one of these integrations, please contact <support@peoplelogic.dev>.

<table data-full-width="false"><thead><tr><th width="233.015625"></th><th width="187.61328125" align="center">Employees &#x26; Groups</th><th width="93.27734375" align="center">Goals</th><th align="center">Meetings</th><th align="center">IDPs</th><th align="center">Feedback</th><th align="center">Reviews</th><th align="center">Surveys</th></tr></thead><tbody><tr><td>CultureAmp</td><td align="center">✅</td><td align="center">✅</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td></tr><tr><td>Deel Engage</td><td align="center">✅</td><td align="center">✅</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td></tr><tr><td>Gusto Performance</td><td align="center">✅</td><td align="center">✅</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td></tr><tr><td>Lattice</td><td align="center">✅</td><td align="center">✅</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td></tr><tr><td>Leapsome</td><td align="center">✅</td><td align="center">✅</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td></tr><tr><td>PerformYard</td><td align="center">✅</td><td align="center">✅</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td></tr><tr><td>Workday</td><td align="center">✅</td><td align="center">✅</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td><td align="center">❌</td></tr></tbody></table>


# Peoplelogic.dev Headless Performance Management

Composable performance modules so you can add only the features you want and none of the ones you don't.

In addition to the powerful synchronization and integration capabilities of the Universal API, we also provide a totally headless performance management suite. &#x20;

For example, you can use the Directory APIs to store employees, sync with Merge to connect your HRIS and leverage the powerful OKR APIs to integrate with your existing workflows.&#x20;

### Setup

This module provides the easiest setup as you don't need to connect anything and the data is always up to date.  Just connect to the main API endpoints and leverage the modules that your administrator has enabled.


# Betterworks

{% hint style="info" %}
**Description:** Betterworks is the proven performance management solution HR professionals rely on for increasing employee engagement, manager efficiency, and business impact.&#x20;

**Website:** [https://betterworks.com](https://betterworks.com/)
{% endhint %}

Follow the steps below to generate an API key and then connect your Betterworks instance to the Universal Talent API.

<figure><img src="/files/1VtXnn3X26g9SQKFt1gT" alt=""><figcaption></figcaption></figure>

1. First, click Admin in the top navigation.
2. Select Platform Configuration.
3. Select Betterworks API in the sidebar.
4. Select a user to associate with the API calls - this determines the permissions granted to the API.
5. Give a name to API Key so you can distinguish it from other keys.
6. Click the **GENERATE KEY** button.
7. Copy your new key to the clipboard.

### Connect the API to Peoplelogic.dev

Send the following request to your API endpoint and you'll start to see data start sync'ing into your Peoplelogic.dev workspace.  Remember, replace the values surrounded by `{{`  and `}}`  (including the curly brackets!) with your actual values.

```http
POST https://api.peoplelogic.dev/api/v1/app
Content-Type: application/json
Authorization: Bearer {{demoOrgToken}}

{
  "type": "pl:sync:betterworks",
  "internal": false,
  "name": "{{your organization in betterworks}}",
  "externalId": "{{your organization shortname}}-betterworks",
  "secretData": {
    "apiKey": "{{betterWorksApiKey}}"
  }
}
```


# ClickUp

{% hint style="info" %}
**Description:** ClickUp is the everything app, for work. One app for projects, knowledge, conversations, and more. Get more done faster—together.

**Website:** [https://clickup.com](https://clickup.com/)
{% endhint %}

Follow the steps below to generate an API key and then connect your ClickUp workspace to the Universal Talent API. &#x20;

1. Log in to ClickUp. In the upper-right corner, click your avatar. Select Settings.

<figure><img src="/files/cC971ZpuaK5ZeXFey5YD" alt=""><figcaption></figcaption></figure>

2. In the sidebar, scroll down and click Apps
3. Under API Token, click Generate or Regenerate.
4. Copy your new token to the clipboard.

### Connect the API to Peoplelogic.dev

Send the following request to your API endpoint and you'll start to see data start sync'ing into your Peoplelogic.dev workspace.  Remember, replace the values surrounded by `{{`  and `}}`  (including the curly brackets!) with your actual values.

```http
POST https://api.peoplelogic.dev/api/v1/app
Content-Type: application/json
Authorization: Bearer {{demoOrgToken}}

{
  "type": "pl:sync:clickup",
  "internal": false,
  "name": "{{your organization in clickup}}",
  "externalId": "{{your organization shortname}}-clickup",
  "secretData": {
    "apiKey": "{{clickUpApiToken}}"
  }
}
```


# Deel Engage

Coming soon!


# 15Five

{% hint style="info" %}
**Description:** 15Five is the performance management platform built for business impact. Where performance, engagement and retention isn’t just measured - it’s maximized.

**Website:** [https://15five.com](https://15five.com/)
{% endhint %}

Follow the steps below to generate an Access token and then connect your 15Five workspace to the Universal Talent API.

1. First, click the Gear menu in the upper right and Click Integrations from the dropdown.  Scroll down till you find Public API.  Click Manage.

<figure><img src="/files/q6IijQ7aNmAjbCGamHQQ" alt=""><figcaption></figcaption></figure>

2. Click Create new key

<figure><img src="/files/9kI45EGS7Zz019AncOFK" alt=""><figcaption></figcaption></figure>

2. Fill in a name for the new API key and hit Save.

<figure><img src="/files/ELiL8rJNVUXDC4b5ZiwR" alt=""><figcaption></figcaption></figure>

2. Copy your new API key (or access token) to the clipboard.

<figure><img src="/files/ig4MIfZNBW8RHeSvE02P" alt=""><figcaption></figcaption></figure>

### Connect the API to Peoplelogic.dev

Send the following request to your API endpoint and you'll start to see data start sync'ing into your Peoplelogic.dev workspace.  Remember, replace the values surrounded by `{{`  and `}}`  (including the curly brackets!) with your actual values.

```http
POST https://api.peoplelogic.dev/api/v1/app
Content-Type: application/json
Authorization: Bearer {{demoOrgToken}}

{
  "type": "pl:sync:15five",
  "internal": false,
  "name": "{{your organization in 15five}}",
  "externalId": "{{your organization shortname}}-15five",
  "secretData": {
    "apiKey": "{{15fiveApiKey}}"
  }
}
```


# Gusto Performance

Coming soon!


# Leapsome

Coming soon!


# Peoplelogic IMPACT


# Perdoo OKRs

{% hint style="info" %}
**Description:** Perdoo is better strategies. Faster execution - the #1 software for OKR & Strategy Execution.

**Website:** [https://perdoo.com](https://perdoo.com/)
{% endhint %}

Follow the steps below to generate an API key and then connect your Perdoo instance to the Universal Talent API.

1. Navigate to [https://web.perdoo.com](https://web.perdoo.com/login/regular) and log in.

<figure><img src="/files/baaQZsNZo8PvpzuQH5tW" alt=""><figcaption></figcaption></figure>

2. In the upper-right corner, click your avatar and select Personal Settings.

<figure><img src="/files/xgxQ5BQrr5IN15PnZUGq" alt=""><figcaption></figcaption></figure>

3. Click on API Tokens tab
4. Fill in the Token name field
5. Click the **Generate** button

<figure><img src="/files/u5zKLFOGLxLQDuyllEjx" alt=""><figcaption></figcaption></figure>

6. Enter your password for confirmation when prompted.
7. Copy your new API Token to the clipboard.

<figure><img src="/files/Ke0XdEuOsRAsRhiasQVC" alt=""><figcaption></figcaption></figure>

### Connect the API to Peoplelogic.dev

Send the following request to your API endpoint and you'll start to see data start sync'ing into your Peoplelogic.dev workspace.  Remember, replace the values surrounded by `{{`  and `}}`  (including the curly brackets!) with your actual values.

```http
POST https://api.peoplelogic.dev/api/v1/app
Content-Type: application/json
Authorization: Bearer {{demoOrgToken}}

{
  "type": "pl:sync:perdoo",
  "internal": false,
  "name": "{{our organization in perdoo}}",
  "externalId": "{{your organization shortname}}-perdoo",
  "secretData": {
    "apiKey": "{{perdooApiToken}}"
  }
}
```


# PerformYard

Coming soon!


# Profit.co

{% hint style="info" %}
**Description:** Profit.co is OKR Software to Execute Your Strategy with Precision. Focus on Goals. Measure your Progress. Achieve Results.

**Website:** [https://profit.co](https://profit.co/)
{% endhint %}

Follow the steps below to generate an API Key and Access Key and connect your Profit instance to the Universal Talent API.

1. Login to Profit and click Settings.

<figure><img src="/files/T29WCAfLwDHVsQ41ZVy1" alt=""><figcaption></figcaption></figure>

2. In Settings, select Security from the left sidebar.
3. Click the Regenerate button if you want to cycle your keys.&#x20;
4. Copy the API Key and Access Key to your clipboard.

### Connect the API to Peoplelogic.dev

Send the following request to your API endpoint and you'll start to see data start sync'ing into your Peoplelogic.dev workspace.  Remember, replace the values surrounded by `{{`  and `}}`  (including the curly brackets!) with your actual values.

```http
POST https://api.peoplelogic.dev/api/v1/app
Content-Type: application/json
Authorization: Bearer {{demoOrgToken}}

{
  "type": "pl:sync:profitco",
  "internal": false,
  "name": "{{your organization in profit}}",
  "externalId": "{{your organization shortname}}-profitco",
  "secretData": {
    "apiKey": "{{profitCoApiKey}}",
    "accessKey": "{{profitCoAccessKey}}"
  }
}
```


# SimpleOKR


# Sloneek


# Weekdone

{% hint style="info" %}
**Description:** Weekdone is Goal Alignment & Progress Reporting Made Simple with Quarterly OKRs + Weekly Updates.

**Website:** [https://weekdone.com](https://weekdone.com/)
{% endhint %}

Follow the steps below to generate a ClientID and Access Token and connect your Weekdone instance to the Universal Talent API.

1. Login to Weekdone and go to Company settings

<figure><img src="/files/zhjc2UWgj0ae2kgmZilf" alt=""><figcaption></figcaption></figure>

2. In Settings, select Applications from the left sidebar.
3. Go to Applications and select new Application
4. Add Application name and Redirect URI (this can be anything).  Click Save or Update.  Make note of the new Client ID and Client Secret

<figure><img src="/files/t71ComEp8EbvqQ986aYu" alt=""><figcaption></figcaption></figure>

5. Open new browser tab and browse this:

`https://weekdone.com/oauth_authorize?client_id=<YOUR_CLIENT_ID>&redirect_uri=<YOUR_REDIRECT_URI>&response_type=code&state=123`

6. Copy the code from the redirect URI that the browser sends you to\
   Example: `http://localhost:8080/?code=<YOUR_AUTH_CODE>&state=123`
7. Make a POST request to get the access token and refresh token

```http
POST https://weekdone.com/oauth_token 
Content-Type: application/x-www-form-urlencoded 

code = <YOUR_AUTH_CODE> & 
grant_type = authorization_code & 
client_id = <YOUR_CLIENT_ID> & 
client_secret = <YOUR_CLIENT_SECRET> & 
redirect_uri = <YOUR_REDIRECT_URI>
```

The response will look something like the following:

```json
{
"access_token":"<ACCESS_TOKEN>",
"refresh_token":"<REFRESH_TOKEN>",
  "token_type":"bearer",
  "expires_in":3600,
  "user":{
    "id":"<YOUR_ID>",
    "name":"<YOUR_NAME>",
    "email":"<YOUR_EMAIL>"
  }
}
```

### Connect the API to Peoplelogic.dev

Send the following request to your API endpoint and you'll start to see data start sync'ing into your Peoplelogic.dev workspace.  Remember, replace the values surrounded by `{{`  and `}}`  (including the curly brackets!) with your actual values.

```http
POST https://api.peoplelogic.dev/api/v1/app
Content-Type: application/json
Authorization: Bearer {{demoOrgToken}}

{
  "type": "pl:sync:weekdone",
  "internal": false,
  "name": "{{your organization in weekdone}}",
  "externalId": "{{your organization shortname}}-weekdone",
  "secretData": {
    "accessToken": "{{yourAccessToken}}"
  }
}
```


# Workboard


# Workday

Coming soon!


# Learning Management

Coming soon!


# Skills Management

Coming Soon!


# Compensation

Coming Soon!


# Talent Application Platform

Coming soon!

The Talent Application Platform allows developers to build their own enterprise ready AI-first talent applications. &#x20;

We're accepting early interest in this exciting new platform.  If you'd like to learn more, please click the [Book a Demo](https://peoplelogic.dev/book-a-demo) button in the top navigation!


# Building your own modules

Coming soon!


# Deploying to Talent Cloud

Coming soon!


# Getting Started with the Talent Agent SDK

The Talent Agent SDK is the easiest way to build AI agents that work with your talent data.  Built on Spring Boot and [Langchain4J](https://github.com/langchain4j/langchain4j), the SDK provides everything you need to integrate agent technology either into your existing platform or running standalone.

### What's in the box?

* Java/Kotlin Support
* Source access
* Built-in agent orchestration for multi-step agents
* Seamless agent history and chat memory
* Seamless RAG support
* Scheduled tasks
* Native integration with the [Universal Talent API](/guides/getting-started-with-the-composable-talent-platform)
* Pre-built talent agents (HR analyst, HRBP, TA Coordinator, HR Coordinator) with built-in tools to work with your talent data (reviews, OKRs, etc)
* Integration into the flow of work
  * Slack integration (including sending messages to Slack and all the plumbing to build a Slack application)
  * Incoming and outgoing email support&#x20;
  * Teams Integration (coming soon!)
* CLI support&#x20;
* REST API (disabled if CLI is enabled)
* [and so much more coming!](https://peoplelogic.releasedhub.com/peoplelogic-agents/roadmap/b2dd0512)


# Getting the SDK

Source access, package downloads and more.

As part of your Talent Agent SDK subscription you'll receive source access to the full SDK source code and samples at <https://github.com/peoplelogic/agent-sdk>.  We will have invited your organization as a collaborator during signup.

The preferred method of starting a new project with the SDK is to leverage Gradle or Maven as your build tool.&#x20;

{% tabs %}
{% tab title="Gradle" %}
{% code title="build.gradle" %}

```groovy
plugins {
    id 'java'
    id "io.freefair.lombok" version "8.6"
    id "org.springframework.boot" version "3.5.3"
}

group = 'dev.peoplelogic.agents.sample'
project.description = "Peoplelogic Agent SDK Sample"
def agent_sdk_version = "${agent_sdk_version}"

java { toolchain { languageVersion = JavaLanguageVersion.of(17) } }
repositories {
    mavenCentral()
    maven { url 'https://jitpack.io' }
    maven {
        name = "SDK Repository"
        url = uri("https://maven.pkg.github.com/peoplelogic/agent-sdk")
        credentials {
            username = System.getenv("GITHUB_USERNAME") ?: project.findProperty("github.username")
            password = System.getenv("GITHUB_PACKAGES_TOKEN") ?: project.findProperty("github.packagesToken")
        }
    }
}

dependencies {
    implementation(platform("ai.peoplelogic:agent-sdk-dependencies:${agent_sdk_version}"))
    // Include teh SDK
    implementation "ai.peoplelogic:agent-sdk"
    implementation "dev.langchain4j:langchain4j"
}
```

{% endcode %}
{% endtab %}

{% tab title="Maven" %}
{% code title="pom.xml" %}

```xml
<project xmlns="http://maven.apache.org/POM/4.0.0" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
                             https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <!-- Inherit Spring Boot’s plugin and dependency-management settings -->
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>${spring.boot.version}</version>
    <relativePath/> <!-- lookup parent from repository -->
  </parent>

  <groupId>dev.peoplelogic.agents.sample</groupId>
  <artifactId>agent-sdk-sample</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>Peoplelogic Agent SDK Sample</name>
  <description>Peoplelogic Agent SDK Sample</description>

  <properties>
    <!-- pulled in from your Space variables -->
    <java.version>17</java.version>
    <lombok.version>8.6</lombok.version>
    <spring.boot.version>3.5.3</spring.boot.version>
    <agent.sdk.version>1.0.8-RC1</agent.sdk.version>

    <!-- for GitHub Packages auth -->
    <github.username>${env.GITHUB_USERNAME}</github.username>
    <github.packagesToken>${env.GITHUB_PACKAGES_TOKEN}</github.packagesToken>
  </properties>

  <repositories>
    <repository>
      <id>maven-central</id>
      <url>https://repo.maven.apache.org/maven2/</url>
    </repository>
    <repository>
      <id>jitpack.io</id>
      <url>https://jitpack.io</url>
    </repository>
    <repository>
      <id>sdk-repository</id>
      <name>SDK Repository</name>
      <url>https://maven.pkg.github.com/peoplelogic/agent-sdk</url>
      <releases><enabled>true</enabled></releases>
      <snapshots><enabled>true</enabled></snapshots>
      <authentication>
        <username>${github.username}</username>
        <password>${github.packagesToken}</password>
      </authentication>
    </repository>
  </repositories>

  <dependencyManagement>
    <dependencies>
      <!-- import the agent‑sdk BOM so you can omit explicit versions -->
      <dependency>
        <groupId>ai.peoplelogic</groupId>
        <artifactId>agent-sdk-dependencies</artifactId>
        <version>${agent.sdk.version}</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <dependencies>
    <!-- platform BOM already imported -->
    <dependency>
      <groupId>ai.peoplelogic</groupId>
      <artifactId>agent-sdk</artifactId>
    </dependency>

    <dependency>
      <groupId>dev.langchain4j</groupId>
      <artifactId>langchain4j</artifactId>
    </dependency>

    <!-- Lombok (annotation‑only) -->
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>${lombok.version}</version>
      <scope>provided</scope>
    </dependency>

    <!-- Spring Boot test support, etc., can go here if needed -->
  </dependencies>

  <build>
    <plugins>
      <!-- Compile with Java toolchain version -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.10.1</version>
        <configuration>
          <release>${java.version}</release>
        </configuration>
      </plugin>

      <!-- Spring Boot repackage & run -->
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
          <jvmArguments>
            -Xmx2g
            --add-opens=java.base/jdk.internal.ref=ALL-UNNAMED
            --add-opens=java.base/java.lang=ALL-UNNAMED
            --add-opens=java.base/java.lang.reflect=ALL-UNNAMED
            --add-opens=java.base/sun.reflect.annotation=ALL-UNNAMED
          </jvmArguments>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

```

{% endcode %}
{% endtab %}
{% endtabs %}

If you're using Gradle, you'll also typically want to include a `gradle.properties` file with the following:

{% code title="gradle.properties" %}

```gradle
agent_sdk_version = 1.0.8-RC1
```

{% endcode %}

### Alternatives to Gradle or Maven

If you aren't a user of Gradle or Maven, you can download the SDK as a standalone package to include in your project or you can download one of our sample projects as a starter kit. &#x20;


# Classes of Agents

Agents to assign and agents to work.

The Talent Agent SDK makes a distinction between two different classes of agents - the coordinator agent (or orchestrator) and the worker agents.  This separation of concerns allows you to build highly specialized teams of agents by easily adding new agents to a team without changing your orchestration.

When using the SDK, all agents will automatically be registered as Spring Beans.  This means they can be autowired into other components (such as your tools) or other service layers that you may have within your application.

### Coordinator Agents

The `CoordinatorAgent` implementation defines the agent that will handle assignment of tasks to the workers.  In addition to implementing the CoordinatorAgent interface, you also need to be sure to name your agent bean the `coordinatorAgent`.&#x20;

{% hint style="info" %}
The same agent can be used as both a coordinator and worker, you simply need to implement both interfaces.
{% endhint %}

This agent also handles verification of inputs for the requested task or conversation to minimize back and forth.  Finally, in addition to assigning tasks and managing orchestration, the CoordinatorAgent can also answer simple questions about the team or if it is also a worker agent, it can handle the task itself.

Finally, the CoordinatorAgent has it's own pre-configured `ToolProvider` that only executes when you use it also as a WorkerAgent.  It will automatically pick up any `Tools` that you define on the agent.  We'll talk more about Tools in a later section.

### Worker Agents

Put simply, the `WorkerAgent` implementations are responsible for receiving a task and doing the work.  These agents typically have their own personality and instructions along with a specialized `SystemMessage`  and `Tools` that help them get things done.

As part of the SDK, we have included several built-in Talent-related agents that you can enable, customize and include as part of your team.


# Built-in Talent Agents

Pre-packaged HR and Talent agents to include in your team.

What would a Talent Agent SDK be without also including the tools and agents to work with some of your common talent processes?

To help jumpstart your new Agentic AI project, we've included the following agents that you can enable within your project simply and then customize to fit your team persona.&#x20;

<table data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-cover data-type="files"></th></tr></thead><tbody><tr><td><strong>Kate - HR Coordinator</strong></td><td>Kate is the pro for working with your HRIS through Merge and helps you stay on top of important employee milestones.</td><td><a href="/files/JojfZyqBZopAGe7VKlTl">/files/JojfZyqBZopAGe7VKlTl</a></td></tr><tr><td><strong>Omar - HRBP</strong></td><td>Omar is the leadership and policy expert.  He can help you have difficult conversations or create new policy documents.</td><td><a href="/files/a5bpgAHBEoULxxevsqEs">/files/a5bpgAHBEoULxxevsqEs</a></td></tr><tr><td><strong>Lexi - HR Analyst</strong></td><td>Lexi cuts through data like its butter.  She's the expert on actionable insights on reviews, OKRs and surveys.</td><td><a href="/files/O9uNId2XFQoNdtYMJztG">/files/O9uNId2XFQoNdtYMJztG</a></td></tr><tr><td><strong>Noah - TA Coordinator</strong></td><td>Noah knows all things talent acquisition.  He can work with your ATS through merge to prep you for interviews, help you draft new job postings or help you sift through a mountain of resumes.</td><td><a href="/files/5eda9Za3bcFL1Feje1Wk">/files/5eda9Za3bcFL1Feje1Wk</a></td></tr></tbody></table>

### Enabling the agents

To enable the agents in your project, simply add any of the lines below to `application.properties` for the agents you want to enable.  If you don't include one of the lines or set it to something other than `true`, the agent will remain deactivated.  Each agent comes pre-configured to leverage their existing set of tools, so you don't need to configure anything else to use them.

```properties
peoplelogic.agent.HRCoordinatorAgent.enabled=true
peoplelogic.agent.TACoordinatorAgent.enabled=true
peoplelogic.agent.HRBusinessPartnerAgent.enabled=true
peoplelogic.agent.HRAnalystAgent.enabled=true
```

### Customizing the agents

In addition to the built-in configuration, you can also customize each of these agents.  Here's a fully customized example for Kate that you can add to your `application.properties`:

```properties
# HRCoordinator - Kate
peoplelogic.agent.HRCoordinatorAgent.name=DocsAgent
peoplelogic.agent.HRCoordinatorAgent.title=Operations Coordinator
peoplelogic.agent.HRCoordinatorAgent.persona=sarcastic and moody.
peoplelogic.agent.HRCoordinatorAgent.avatar=${peoplelogic.agent.appUrl:http://localhost:8080}/images/avatars/Kate.png
peoplelogic.agent.HRCoordinatorAgent.bio=DocsAgent is your organizational powerhouse, making sure nothing falls through the cracks. From scheduling recurring check-ins to tracking team milestones, DocsAgent automates the admin so you can focus on leading your team.
peoplelogic.agent.HRCoordinatorAgent.shortBio=DocsAgent is your organizational powerhouse, making sure nothing falls through the cracks. From scheduling recurring check-ins to tracking team milestones, DocsAgent automates the admin so you can focus on leading your team.
```

Granted, this is a bad example because we never want our HR Coordinator to be sarcastic and moody, but it highlights the power of configuration!

### Advanced

Finally, there are two additional properties that you can define for each agent: additional `Tools` and a `RetrievalAugmentor`.  These are somewhat more advanced, but allow you to add your own tools to each agent and also customize how the agent may decide to use a tool or [use documents to reply.](/guides/getting-started-with-the-talent-agent-sdk/working-with-documents)

```properties
peoplelogic.agent.HRCoordinatorAgent.retrieval-augmentor=beanNameOfRetrievalAugmentor
peoplelogic.agent.HRCoordinatorAgent.tools=beanNameOfYourTools
```

Both of these simply reference an existing Spring bean in your project and will be added to the configuration of the agent on startup.  We'll learn more about both Tool beans and RetrievalAugmentor beans later on.


# Tools for the built-in team

Each of the built-in talent agents includes specialized tools that help them do the work of a virtual talent team. &#x20;

Don't worry if you aren't very familiar with tools just yet.  We'll discuss giving your own agents tools (and what tools are!) in a later section.

{% hint style="info" %}
These tools and descriptions are provided purely for convenience.  Many of the names are purposefully long to catch specific edge cases in a generic talent agent.
{% endhint %}

If you want to learn more about the practical uses of these tools, check out the Peoplelogic Nova documentation at <https://help.peoplelogic.ai/collections/4846861505-playbooks>.

### HR Coordinator Tools

<table><thead><tr><th width="408.71875">Tool name</th><th>Description</th></tr></thead><tbody><tr><td>connectOrReconnectHRISOrEmployeeDirectory</td><td>Allows the user to connect or reconnect an HRIS or employee directory. This tool explicitly only outputs the message and link - it will not actually reconnect the HRIS or employee directory. Must be an admin or HR admin.</td></tr><tr><td>shareBirthdaysOnTeam</td><td>Answers the question 'who has a birthday today' (in any language). Outputs who has a birthday on the team for today. User can ask who has a birthday or what the birthdays for today are or list the birthdays or what birthdays are we celebrating today.  The tool outputs the name, their title and their location. If you need an HRIS connection - be sure to output that from this tool. It explicitly does not output their email or other personal details. Explicitly do not ask for what date the user wants - it is always today.</td></tr><tr><td>shareNewHiresTodayOrWhoIsStartingToday</td><td>Outputs the new hires for today or who is starting today or who are the new employees today. User can ask who is starting today or who the new hires are today or who are the new hires or list the new hires. The tool outputs the name, their title and their location. If you need an HRIS connection - be sure to output that from this tool. It explicitly does not output their email or other personal details. Explicitly do not ask for what date the user wants - it is always today.</td></tr><tr><td>shareWorkiversaryOrWorkAnniversary</td><td>Outputs the current workiversaries or workiversary (work anniversaries or work anniversary) of the team for today. User can ask who has a work anniversary today or who has a workiversary today or what are the workiversaries or even what are the work anniversaries today. The tool outputs the name, their tenure, their title and their location. If you need an HRIS connection - be sure to output that from this tool. It explicitly does not output their email or other personal details. Explicitly do not ask for what date the user wants - it is always today.</td></tr></tbody></table>

### HR Analyst Tools

<table><thead><tr><th width="409.48828125">Tool name</th><th>Description</th></tr></thead><tbody><tr><td>summarizeGenericFile</td><td>Summarizes a given file and should only be picked if there isn't a more specific  summarization request (like a survey or review). If a file is required (a full url for example) then this tool should only be called after that file has been uploaded. Call that tool first. Keep asking for confirmation until the user explicitly confirms.</td></tr><tr><td>summarizeOrAnalyzeReviewOrReviewCyclePDFOrCSVorExcel</td><td>Summarizes and provides specific details of review (or review cycle) results - either provided as a set of files or a single file which may contain all results of a review cycle or just a single review. All the pieces should be combined and considered in the analysis. Before processing, be sure to explicitly ask (only once) the user if they want to optionally provide an OKR cycle export to combine into the analysis. This task requires HR admin or admin access."</td></tr><tr><td>analyzeOKRCycleOrGoalFiles</td><td>Analyzes and provides specific insights with recommendations into improving OKR cycles or goals or project statuses - either provided as a set of files or a single file. If provided as multiple files, assume that it is multiple cycles and you should combine and compare them against each other. Keep asking for confirmation until the user explicitly confirms.</td></tr><tr><td>summarizeOrAnalyzeSurveyCSVOrExcelOrPDF</td><td>Summarizes or analyzes and provides specific details of survey results export or just a survey in a file or set of files in either CSV or Excel or PDF format. This export can contain multiple sections or could be multiple files. All the pieces should be combined and considered in the summary. The user must provide the files for you to analyze - usually by uploading them. You should always ask for file urls or uploads until you have them. Keep asking for confirmation until the user explicitly confirms. This task requires HR admin or admin access.</td></tr><tr><td>answerQuestionsFromPreviouslyUploadedFiles</td><td>Answers specific questions from the files that were previously uploaded. This helps to prevent hallucinations. Use this tool if the analyst is asking question AFTER uploading things and hasn't restarted.</td></tr></tbody></table>

### HR Business Partner Tools

<table><thead><tr><th width="409.421875">Tool name</th><th>Description</th></tr></thead><tbody><tr><td>generateOrCreateHandbook</td><td>Helps a user create or generate a new draft handbook based on our experience through sample handbooks and our knowledge of APM. You must explicitly ask for an output format if none is provided. PDF and Word are currently supported. Default to word if user just confirms. The user can also optionally provide an organization name, sections to exclude (mission, vision, values, meeting norms, etc) and any additional details the user might want to include to help with generating this (for example a remote work policy or specific meeting norms). Be sure to indicate these are optional. You should explicitly keep asking the user for required inputs until they confirm. The keep asking parameter should be set to true until you've asked for all the optional details and the user has confirmed. This task requires HR admin or admin access."</td></tr><tr><td>generateOrCreateIDPOrCareerPlanForEmployeeAfterReview</td><td>Helps a user create or generate a new IDP (individual development plan) or career plan for a given employee based on our experience through a sample IDP and our knowledge of APM and the results of the provided reviews. This tool must explicitly never be run without the review results having been analyzed previously. You must exit and tell the user to analyze the review first. You must explicitly ask for an output format if none is provided. PDF and Word are currently supported. Default to word if user just confirms. You should explicitly keep asking the user for required inputs until they confirm. Only ask for the optional inputs one additional time. This task requires HR admin or admin access.</td></tr><tr><td>generateOrCreateOrProduce9BoxForReviewCycle</td><td>Creates or generates or produces a 9box performance report (also known as a succession plan or promotion plan) based on the results of the provided review. The format can be Word or PDF. If no value provided, default to word format. The review cycle files must be provided and a review must have analyzed already to produce a 9box. Admin or HR Admin access is required for this action."</td></tr><tr><td>translateDocumentsOrPolicy</td><td>Translates an a set of existing documents or policies or files (or even just a single one) into the language requested. You must explicitly ask for the language to translate to - do not just assume it is english. The documents can be output in word, PDF or text/markdown. The documents must be uploaded before translation - so call the upload tool first."</td></tr><tr><td>generatePolicyDocument</td><td>Generates a custom HR policy tailored to a company's size, industry, location, audience, and compliance needs. This tool should be used when a user wants to create a new HR policy document from scratch or based on structured inputs. It supports a variety of policy topics (e.g., Remote Work, AI Usage, Leave Policies, Code of Conduct, etc.) and ensures that the output includes standard policy sections: Purpose, Scope, Policy Details, Roles &#x26; Responsibilities, Enforcement, Exceptions, and Acknowledgment. The user can provide optional inputs such as company name, size, tone, legal requirements, and cultural values along with additional context information to ensure the generated policy matches their organization’s style and needs. Returns a fully formatted HR policy in Word or PDF format. On admins and HR admins can execute this tool.</td></tr></tbody></table>

### Talent Acquisition Coordinator Tools

<table><thead><tr><th width="409.359375">Tool name</th><th>Description</th></tr></thead><tbody><tr><td>matchResumesToJobListing</td><td>Helps the user match a list of resumes (comma separated list) with a given job listing (the user can also ask you to find the best resumes, but this is not recommended). The agent will match the resumes by the overlap in keywords and themes and experience with the job listing. Both the resume and the job description need to be uploaded so prompt them to provide those. The user can also provide some additional criteria to match in the resumes and an optional number of resumes to return as matches - defaulting to 10. Be sure to confirm all inputs have been provided before proceeding. Before starting, explicitly mention to the user that this is not ranking candidates - just matching based on the job description.</td></tr><tr><td>createJobDescriptionForRole</td><td>Helps the user to create or craft a new job description for a role they are hiring for. The agents will use any uploaded data that has been shared with the organization (such as the handbook) and will guide the user through creating the job description. The user can provide optional roles and responsibilities, performance goals, benefits and perks, salary and details about the company. The user can also ask you to provide some sample data for those values. This means include it in the final document, not output it before. Explicitly do NOT deviate from the provided options when telling the user what they need to provide. It will then output in either text, Word or PDF (messaging back in the conversation is the default).</td></tr><tr><td>connectOrReconnectATS</td><td>Allows the user to connect or reconnect an applicant tracking system (ATS). This tool explicitly only outputs the message and link - it will not actually reconnect the ATS. No additional data is required. Must be an admin or HR admin.</td></tr><tr><td>getJobOrPositionOrReqDetails</td><td>Provides or tells the user about detailed information of a specific job or position. User must provide the name of a job to get these additional details.</td></tr><tr><td>getHiringOrTalentPipelineReport</td><td>Produces an excel report of the current hiring pipeline. The user can provide the stages that will be excluded from detailed lists of candidates in them but by default all stages are included. User can also tell you what period (number of days back) to include for the pipeline - it defaults to trailing 30 days, but can be trailing 60, trailing 90 or trailing 365.  You should always explicitly confirm with the user whether they want to provide these details first. Admin or HR admin access is required to retrieve this report.</td></tr><tr><td>getOpenJobsOrAvailableJobsOrOpenPositionsOrJobListings</td><td>Outputs a full list of the open or available jobs or open positions or open reqs within the company. Great for understanding what jobs are open for internal transfers or promotions or referrals. Includes the hiring manager when available.</td></tr><tr><td>summarizeOrPrepareInterviewNotes</td><td>Summarizes or prepares notes for each that the interviewers (if set, or current user otherwise) have in the ATS. This is typically for today but it no time is provided then just assume today.</td></tr></tbody></table>


# Building your first agent application

Now that you've seen how to get the SDK, we need to build our first agent.  The easiest way to get going is to clone the starter kit from GitHub, located here: <https://github.com/peoplelogic/agent-sdk-starter>.  This will setup the typical agent structure and contains the Application starter class and all of the necessary dependencies.

### Defining the Agent Application

The entry point for any new agent application is the agent runner.  This bootstraps your agents, gives you the ability to run either a web or CLI application and even allows you to override the startup banner.  For those of you familiar with Spring Boot - the code will seem familiar.

{% code title="SampleAgentRunner.java" %}

```java
@PeoplelogicAgentApplication
public class SampleAgentRunner extends PeoplelogicAgentRunner {
    public static void main(String[] args) {
        run(SampleAgentRunner.class, args);
    }
}
```

{% endcode %}

### Creating the first agent

With the boilerplate setup for your agent application, you can get to the real work of creating your agent.  The SDK makes a point of handling much of the repetitive code for you so that you can focus on the configuration, prompts and tooling for your agents.  Let's take a look at what your first agent might look like.

{% code title="KnowItAllAgent.java" %}

```java
@PeoplelogicAgent(value="coordinatorAgent",
        name = "Know It All Agent",
        persona = "Funny but a bit snarky")
public interface AllInOneAgent extends WorkerAgent, CoordinatorAgent {}
```

{% endcode %}

Don't worry if this seems a little overwhelming, we'll get to explanations of all the annotations and methods shortly!  In reality you will only need to override the methods that you want to customize, but let's walk through what all this means:

#### @PeoplelogicAgent

This annotation is the meat and potatoes of your Agent definition.  It contains all the configuration you need to setup your agents and can even use SPEL expressions to grab externalized properties (we'll show this more later!).  The `value` must be unique and there must always be one with the value `coordinatorAgent`. The coordinator agent is the one that parses out all the agent work - even if its to itself.  The rest of your agents can have whatever value you desire.

### WorkerAgent and CoordinatorAgent

The agent SDK takes care of the most common use cases for these two classes of agents - especially if you just want to use the robust base system prompts.  Let's take a look at the methods:

#### BaseAssignmentHolder assign()

{% hint style="warning" %}
Please pay attention the annotations on the parameters in the method implementation - these are required.
{% endhint %}

```java
@SystemMessage(BASE_COORDINATOR_PROMPT)
BaseAssignmentHolder assign(@MemoryId String userId, @UserMessage String userMessage, @V("InConversation") String inConversation, @V("Agent") String agent);
```

This method is called on the `CoordinatorAgent` when you send a new question or task into the SDK.  The CoordinatorAgent knows about all the other agents in your application and the `BASE_COORDINATOR_PROMPT` is generally sufficient for most tasks provided you've included sufficient instructions to your worker agents and can handle assigning to one agent or many. &#x20;

During assignment, no tools will be called, unlike the acceptWork call - this call is entirely about delegating work somewhere else.

Additionally, for the `SystemMessage` annotation you could also have referenced a prompt file from your resources folder to externalize the handling of the prompts.

#### Result\<BasePeoplelogicResult> acceptWork()

```
@SystemMessage(BASE_WORKER_PROMPT)
Result<PeoplelogicResult> acceptWork(@MemoryId String userId, @UserMessage String query, @V("previousResponse") String agentResponse);
```

The acceptWork method is the main entry point to a `WorkerAgent` and in most of your actual agents will be in a separate class with its own unique agent.  The system prompt on this method is all about executing the work for the task that has been assigned to it.  You will often use it to help the LLM choose tools more effectively or return a response in a more specific format.

{% hint style="info" %}
You will almost always want to provide your own SystemMessage prompt here as this is work all the magic happens! You can alternatively provide agent instructions and tools without overriding system prompts.
{% endhint %}

Similarly to the assign method, you can reference an external prompt file and the annotations on the method parameters are important!

### Running your new agent

{% hint style="info" %}
For the purposes of this documentation we'll be using OpenAI to run our agents.  We'll explore using other LLMs later in the documentation.
{% endhint %}

Now that you've built your first agent - you're ready to put it to work.  First, we have just a smidge of configuration to do.  You'll need to open up `resources/application.properties` and enter your OpenAI key. &#x20;

You'll also notice that the sample has the application profile set to `cli,cli-interactive` .  We'll explore these in more detail later, but these profiles control how you'll interact with your agents.

With that set, now you just need to run with the command `./gradlew bootRun` .  You should see output similar to the output below:

```bash
______                _      _             _      
| ___ \              | |    | |           (_)     
| |_/ /__  ___  _ __ | | ___| | ___   __ _ _  ___ 
|  __/ _ \/ _ \| '_ \| |/ _ \ |/ _ \ / _` | |/ __|
| | |  __/ (_) | |_) | |  __/ | (_) | (_| | | (__ 
\_|  \___|\___/| .__/|_|\___|_|\___/ \__, |_|\___|
               | |                    __/ |       
               |_|                   |___/        

 :: Spring Boot ::                (v3.5.3)
 :: Peoplelogic Agent SDK ::   (v1.0.7.22)

2025-07-16T18:53:57.625-04:00  WARN 99149 --- [           main] o.s.c.annotation.AnnotationTypeMapping   : Support for convention-based annotation attribute overrides is deprecated and will be removed in Spring Framework 7.0. Please annotate the following attributes in @ai.peoplelogic.agents.common.spring.PeoplelogicAgent with appropriate @AliasFor declarations: [wiringMode]
2025-07-16T18:53:58.787-04:00  INFO 99149 --- [           main] org.flywaydb.core.FlywayExecutor         : Database: jdbc:h2:file:./data/peoplelogic-agent-sdk (H2 2.3)
2025-07-16T18:53:58.815-04:00  INFO 99149 --- [           main] o.f.core.internal.command.DbValidate     : Successfully validated 10 migrations (execution time 00:00.018s)
2025-07-16T18:53:58.820-04:00  INFO 99149 --- [           main] o.f.core.internal.command.DbMigrate      : Current version of schema "public": 1.0.8
2025-07-16T18:53:58.822-04:00  INFO 99149 --- [           main] o.f.core.internal.command.DbMigrate      : Schema "public" is up to date. No migration necessary.
2025-07-16T18:54:00.316-04:00  WARN 99149 --- [           main] org.jline                                : Unable to create a system terminal, creating a dumb terminal (enable debug logging for more information)
peoplelogic:>
```

This is the [interactive CLI for the agent SDK](/guides/getting-started-with-the-talent-agent-sdk/agents-in-the-flow-of-work/agent-cli).  Now just ask the agent something simple with `q what is your name?` .  This sends your question or task to the SDK which assigns to your one agent and then proccesses it.  In a moment you should get back an answer:

{% code overflow="wrap" %}

```bash
peoplelogic:>q what is your name?
agent:> My name is Know It All Agent. Yes, that's actually my name—it's tough being this humble and informative all at once. What can I help you with today?
```

{% endcode %}

And now you have a running agent - a simple one, but we've shown a great deal of flexibility in a very simple package.  Now let's start to see how we can get more advanced - onward!


# Personalizing your agents

Easy configuration to ensure your agent team persona matches your brand.

Choosing the right personality for your new agents is an important consideration in making them approachable to your users.  You want to thread a fine line between obviously being AI and also being human enough for your users to want to interact with them. &#x20;

With the Talent Agent SDK you get several personalization mechanisms for your agents from personality to background (biography) to instructions that help with assignment. Let's take a look.

### Agent personas

The simplest level of personalization is defining a persona for your agent.  This primarily controls the tone that the agent responds to your users, their name, their likeness and their background (bio).  You set the persona as part of `@PeoplelogicAgent` definition.  It can be hardcoded in the annotation or you can set it in your `application.properties` . &#x20;

{% code title="Hardcoded personas in the annotation" %}

```java
@PeoplelogicAgent(name = "Kate",
        persona = "fun, outgoing, yet professional", 
        title = "HR Coordinator",
        avatar = "https://placehold.co/600x400/png", 
        bio = "Kate is an HR Coordinator with 15+ years of HR experience.")
```

{% endcode %}

{% code title="Using values from application.properties" %}

```java
@PeoplelogicAgent(name = "${peoplelogic.agent.HRCoordinatorAgent.name}",
        persona = "${peoplelogic.agent.HRCoordinatorAgent.persona}", 
        title = "${peoplelogic.agent.HRCoordinatorAgent.title}",
        avatar = "${peoplelogic.agent.HRCoordinatorAgent.avatar}", 
        bio = "${peoplelogic.agent.HRCoordinatorAgent.bio}")
```

{% endcode %}

### Agent assignment mapping

When the Coordinator goes to figure out assignments for a task or set of tasks, it combines the the agent's Spring bean value with the instructions.  This helps to give some additional hints so that the agents are assigned appropriately.  Here's a practical example:

{% code overflow="wrap" %}

```java
@PeoplelogicAgentInstructions("This agent excels at providing complete details about incident and police reports from a " +
        "demand attachments file and turning them into a coherent incident details report.")
```

{% endcode %}

Alternatively, you can combine all of your mappings across all agents into an externalized property in `application.properties` .  This added context combines the bean value with the agents name and the mappings (the value in the instructions)

{% code title="application.properties example" %}

```properties
peoplelogic.agent.team.addedContext=hrbp = ${peoplelogic.agent.HRBusinessPartnerAgent.name} - ${peoplelogic.agent.HRBusinessPartnerAgent.mapping}\n \
hrAnalyst = ${peoplelogic.agent.HRAnalystAgent.name} - ${peoplelogic.agent.HRAnalystAgent.mapping} \n \
coordinatorAgent = ${peoplelogic.agent.VPofPeopleAgent.name} - ${peoplelogic.agent.VPofPeopleAgent.mapping} \n \
hrCoordinator = ${peoplelogic.agent.HRCoordinatorAgent.name} - ${peoplelogic.agent.HRCoordinatorAgent.mapping} \n \
taCoordinator = ${peoplelogic.agent.TACoordinatorAgent.name} - ${peoplelogic.agent.TACoordinatorAgent.mapping}
.....
peoplelogic.agent.HRCoordinatorAgent.mapping=Typically does tasks in the team such as importing users (including from a file uploaded by a user), \
  onboarding (or creating) new users or employees, sending invites or deactivating users (except from Nova).
```

{% endcode %}

Both of the methods above are functionally equivalent and it's just a matter of how you want to manage your workflow.

### Agent work execution

The final personalization step comes in defining the `SystemMessage` or base instructions for your AI.  This is traditionally what is defined as "prompt engineering" and there are many resources on the web to help you improve your prompting skills.  Many of the public AI models are also able to help you with prompts and suggest improvements.   &#x20;

The SDK includes a base worker prompt that handles standard things like personalization, hallucination prevention, tool usage and multiple languages, but it can be helpful to either modify this prompt or expand on it.  Here's the base worker system message.

{% hint style="info" %}
The base worker prompt was designed with OpenAI in mind.  If you decide to use a different LLM you may experience different results.
{% endhint %}

{% code overflow="wrap" %}

```java
String BASE_WORKER_PROMPT = INTRO_SEGMENT + "\n\n" + MULTI_LINGUAL_SEGMENT + "\n\n" + "You have a set of tools at your disposal.  If you do not have enough info from the user to call a specific tool you should ask the user for that additional information. Be sure to mention which inputs are optional - explicitly do not keep asking for optional inputs. You explicitly do not need confirmation if all the required fields are provided. If the user provides some of the optional information but not all, you should continue to confirm that you have everything until the user explicitly confirms. You should attempt not to hallucinate or include information not relevant to this specific ask. Requests to 'send' or 'send summary' or 'send results' or similar should default to email if there is no specific destination and should explicitly always send even if there are no results from other tools.  If the task is being sent from a scheduled job, then the 'scheduled time' is always now and you should execute now.  Do not ask for further clarification. If part of a reminder, be sure to not be too curt with your reminder, you can be conversational. The user may not have remembered what they asked you to schedule the task.  Also remember that the user is the one who needs to do any action in the reminder. If the user asks you to output something in text or in the conversation - explicitly do not just say that you've done it - output the actual result. Calling the sending tool should always be done last. Explicitly do not hallucinate URLs or filenames.  If a user asks you to convert a previous output into a different format - just call the same tool with the requested format.  For example, changing a text output of a resume to word format or word format to PDF. Explicitly do not try to upload the file, just redo the call with the new format and use the memory." + "\n\n" + LOCALIZATION_SEGMENT;
```

{% endcode %}

You may decide it's a good idea to use this as your foundation and then expand on it. Here's an example of how you might expand the prompt in your own agent - here we needed to focus on improving very specific math that we were having issues with.  Things wrapped in `{{ }}`  are replacements from parameters on the `acceptWork` method.

{% code overflow="wrap" %}

```java
String WORKER_PROMPT = BASE_WORKER_PROMPT +
            " You should always aim for completeness" +
            "of your answer when telling the user how to do something.  " +
            "You should include step by step instructions if you can.  If a user explicitly asked you to add new knowledge or upload a file and it is not part" +
            "of another task - be sure to indicate that it will be shared with others. If you need to subtract dates (for determining a workiversary), subtract this year from the year in the start date and explicitly round up on the number of years if the number of months is more than 10. For example, 2 years, 11 months is 3 years." + "\n\nThe previous response was: {{previousResponse}}"
```

{% endcode %}

Whether you decide to use the built-in prompts or completely create your own is a choice left to implementation.  The most important decision is what prompt will handle your specific use case optimally. &#x20;


# Agent history and chat memory

A record of all the interactions with your agents.

Agent history and memory are two similar but distinct concepts within AI agents. For more details on the exact difference, Langchain4J does a good job explaining the difference simply here: <https://docs.langchain4j.dev/tutorials/chat-memory#memory-vs-history>&#x20;

The Talent Agent SDK implements both memory and history for you.  The history is managed automatically behind the scenes and is stored forever.  It is what powers the built-in search API.  ChatMemory is also handled automatically with a built-in Spring component but can be overridden if you want it handled differently.

{% hint style="info" %}
Viewing the agent history is an important part of improving your agents during initial deploys.  You should ensure that any terms of service you have with your users and/or customers gives you access to view the AI responses for the purpose of improving their output.
{% endhint %}

### Agent chat memory

Every agent that you build gets the built-in chat memory auto configured.  This memory keeps a rolling 200 messages per conversation and by default the memory ID is managed automatically as you chat back and forth with the agents.

This window can be configured in `application.properties` through the setting:

```properties
peoplelogic.agent.memory.window=50
```

{% hint style="info" %}
By default - the chat memory is not persistent through restarts.  Future versions of the SDK will include an option to enable a memory stored in the database.
{% endhint %}

You can choose to create your own replacement of the ChatMemoryProvider interface and add it to your agents.  The `@PeoplelogicAgent` annotation includes a `chatMemoryProvider` parameter that you can then point to your newly created Spring component.

For more details - check out Langchain4J's great documentation on implementing your own ChatMemory at <https://docs.langchain4j.dev/tutorials/chat-memory>

### Agent chat history

History of the interactions with your agents is handled transparently behind the scenes.  You can access this history several ways:

1. Calling the web API for search (if using the web).
2. Using the CLI to search (if using the CLI).
3. Autowiring `PeoplelogicAgentUtils`  and calling its search method.
4. Autowiring `AgentHistoryRepository` and accessing the history directly.

All of these will yield the same results.  Each message in the history is attached to a conversation and knows whether it was a user message or an agent response. If it was an agent response it also includes the token usage.

In addition to searching the agent history, one potential usage of the direct history might be to use it to break out the themes of queries that users are asking your agent to answer.  You can send the anonymized user messages back to an agent within a tool to get the themes and then output those as the result of the tool.  Or you could use the history to automatically improve the way that an agent responds to inputs.  Feel free to get in touch if you'd like help implementing these ideas!


# Multi-step agent execution

Agent 1, Agent 3, back to Agent 1 and finish.

What makes AI Agents powerful isn't their ability to use tools, but their ability to work in concert to complete a task (orchestration).

{% hint style="info" %}
Today, the Agent SDK only executes one step in the workflow at a time.  Parallel steps are coming soon.
{% endhint %}

Within the base coordinator prompt that we showed you before, there is native handling of assignment to multiple Agents.  These assignments are not just linear, they also have depth - each assignment can depend on another assignment.  &#x20;

Once the assignment is complete - usually the coordinator will echo back to you how it will execute and give you an opportunity to confirm.  After confirmation - the system will ensure that the tasks are executed in the proper order, leveraging the chat memory to pass the completion details of each step to the next assignment and ultimately finish the task. &#x20;

### A trivial example

First - let's setup a team of 4 agents.

{% tabs %}
{% tab title="Coordinator" %}

```java
@PeoplelogicAgent(value="coordinatorAgent",
        name = "Know It All Agent",
        persona = "Funny but a bit snarky")
@PeoplelogicAgentInstructions("Assigns tasks and runs first, telling the user its name.  Also runs last after everything else and says Thank you (in your own unique way!)")
public interface AllInOneAgent extends WorkerAgent, CoordinatorAgent {}
```

{% endtab %}

{% tab title="Second agent" %}

```java
@PeoplelogicAgent(value="secondaryAgent",
        name = "Secondary Agent",
        persona = "Funny but a bit snarky")
@PeoplelogicAgentInstructions("Your job is to say hi - it is always the 2nd task.")
public interface SecondaryAgent extends WorkerAgent {}
```

{% endtab %}

{% tab title="Third agent" %}

```java
@PeoplelogicAgent(value="thirdAgent",
        name = "Third Agent",
        persona = "Funny but a bit snarky")
@PeoplelogicAgentInstructions("Your job is to say the current date.")
public interface ThirdAgent extends WorkerAgent {}
```

{% endtab %}

{% tab title="Fourth agent" %}

```java
@PeoplelogicAgent(value="fourthAgent",
        name = "Fourth Agent",
        persona = "Funny but a bit snarky")
@PeoplelogicAgentInstructions("Your job is to say goodbye - it is always after the 3rd agent.")
public interface FourthAgent extends WorkerAgent {}
```

{% endtab %}
{% endtabs %}

By now, these samples should feel familiar if you've been following along in the other section of the documentation.  Let's start up the agent CLI (remember, `./gradlew bootRun`) and see what it gives us:

{% code overflow="wrap" %}

```bash
peoplelogic:>q do my agents things
Starting new conversation, 'New Conversation...'
agent:> No additional details are needed to proceed. You’ve provided everything required, so just say the word if you want your agents to do their thing! If you’re ready, just confirm, and I’ll get things rolling (well, figuratively—I never actually do the rolling, just the organizing).
peoplelogic:>q do it
agent:> Let's get the agent show started!

1. Hello! My name is Know It All Agent, and I'll be coordinating things today.
2. Hi! (from the Secondary Agent)
3. The current date is July 19, 2025. (from the Third Agent)
4. Goodbye! (from the Fourth Agent)
5. Thank you for working with the agents today—I hope someone brings you coffee (or tea, I don't judge) because you deserve it!

If you want to parade these agents out again, just say the word!
```

{% endcode %}

Trivial, but what are we seeing here?  We see that the CLI automatically handles creating a new Conversation and then has the CoordinatorAgent verify that we don't need anything else.  Since this is a bit more complicated of a task it is going to confirm with us first.  Then, we confirm that we're ready to go and it executes the workflow.  The agent assignment goes:

{% code overflow="wrap" %}

```
coordinatorAgent (step1) -> secondAgent -> thirdAgent 
-> fourthAgent -> coordinatorAgent 
```

{% endcode %}

This is exactly as we would expect to see with the instructions we provided.  In a real example you might also provide tools to each agent to do specialized work.  You can see the power in this when you start to combine the built-in agents (and their tools) with your own agents - the sky is the limit.  Now let's look at how we give your agents actual tools to work with!


# Giving your agents Tools

Ensuring your agents are evolved.

Tools (or previously called Functions in the LLMs) are critical to giving your agents access to the information they need to execute the tasks you give them.  Some examples might include:

* Searching the web
* Talking to your HRIS
* Generating a PDF

Tools are powerful because they allow you to expand what the LLM knows leveraging code and talking to your own systems via APIs.

As part of the SDK, we have provided common tools for working with Word, PDF and other common file formats.  We also have provided [built-in talent agents and tools](/guides/getting-started-with-the-talent-agent-sdk/built-in-talent-agents) for working with your HRIS and other common talent workflows.

Let's take a look at how to build a simple tool.


# Creating your own tools

{% hint style="info" %}
Peoplelogic.dev utilizes the powerful high-level tools mechanism from Langchain4j.  You can read more about their Tools interface here: <https://docs.langchain4j.dev/tutorials/tools>
{% endhint %}

While most of the base LLMs out there are very powerful in their own right, your agents will only be as good as the as the systems they can interact with.  That's where your own Tools come into play.  Fortunately, creating tools is trivial.  Let's take a look at a simple example:

{% code title="SampleTools.java" %}

```java
@PeoplelogicTools
public class SampleTools {
    @Autowired
    TestContentRetriever retriever;
    
    @Autowired
    ThirdAgent thirdAgent;

    @Tool("Answers the question: 'what is your name?' or answers if someone asks hello")
    public String whatIsYourName() {
        return "Hello. My name is Inigo Montoya. You killed my father. Prepare to die.";
    }
}
```

{% endcode %}

Pretty straightforward.  The `@PeoplelogicTools` annotation tells us where to look for tool methods and also ensures that this is a Spring bean (meaning we can also autowire it elsewhere for re-use). &#x20;

Within the class, we can also bring in other functionality from our application - this might be other agents we want to call, client libraries for some integration or even an externalized property from `application.properties`.

### The @Tool annotation

Finally, we get to the meat and potatoes - the `@Tool` annotation.  This annotated method is what is passed to the LLM when `acceptWork` is first called on the agent.  Behind the scenes, the description (value of the annotation) and the method name are passed to the LLM as an available tool/function and the LLM will return whether we should call that method.  The method is then called and it's output sent to the LLM to include in the response.

Methods annotated with `@Tool` can also have some additional parameters.  For example, if you want to be able to leverage the current chat memory (for passing it to other agents), you can annotate a parameter with `@ToolMemoryId` and it will be auto-filled.  You can also defined parameters to your tool method with the `@P` parameter.  This annotation takes a "name" as its value and that value is passed to the LLM to help assign the parameters.  You can also define whether the parameter is required.

Let's take a look at all of this put together:

<pre class="language-java"><code class="lang-java">@Tool("Analyzes and provides specific insights with recommendations into improving OKR cycles or goals or project statuses - either provided as a set of files or a single file.If provided as multiple files, assume that it is multiple cycles and you should combine and compare them against each other.  Keep asking for confirmation until the user explicitly confirms.")
public String analyzeOKRCycleOrGoalFiles(@ToolMemoryId String memoryId, 
    @P("CSV or excel export of an individual OKR cycle or several cycles 
    or goals or project status", required=true) String filenames, 
    @P("all data captured, has the user explicitly confirmed?") Boolean confirmed) {
<strong>}
</strong></code></pre>

This is a real world example from our HR Analyst tools.  Here we pass in the memory id for the conversation, accept a parameter that is required and also capture whether the user has confirmed the operation.

As the Langchain4J docs describe above, you can return many different types from your tool methods.  Just remember that not all LLMs have great support for JSON objects as return types - especially from tools!

{% hint style="info" %}
Sometimes you need to be sure to give the LLM more hints about your tools. [We've found this article to be super helpful](https://blog.pamba.app/tactics-for-agent-obedience/) when getting the LLM to do what you want!
{% endhint %}

### Adding the tools to your agent

Finally, we need to actually tell the agents to use the tools.  To do that, you just need to specify this bean on your agent configuration:

```java
@PeoplelogicAgent(value="coordinatorAgent",
        name = "Know It All Agent", tools = {"sampleTools"},
        persona = "Funny but a bit snarky")
```

Now let's take a look at some common tools that the SDK ships for you to use.


# Common tool access

Tools available to all agents.

The Agent SDK provides a set of common tools that all of your agents automatically have access to.  These are the tools for working with scheduled tasks, sending emails or slacks, uploading documents and moving conversations between mediums. &#x20;

In addition, it contains some static methods for converting Markdown to Word and PDF and then uploading those to a configured `TemporaryFileStorageService` .

### Tools

| Tool name                                  | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| ------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| changeChannelForConversation               | Changes the output channel of a conversation or thread. For example, 'move this to slack' or 'move this conversation to email' will send a message to that channel wih the "overview of the conversation so far and let you continue right from there. The user can also optionally indicate another user or email they want it sent to. If no 'to' provided then assume current user's details.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| listMyScheduledTasksOrOrgsTasks            | Lists the user's active or scheduled workflows (including tasks, jobs, etc). The user can also request to list all the organizations tasks but only if they have the proper permission (meaning they are an admin). You should only use the tool output - do not mention random or hallucinated tasks.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| unscheduleOrRemoveOrDeleteTaskOrJob        | Unschedule or remove or delete a previously scheduled task or job - including removing or deleting all of the users tasks or the organization's tasks. You must always explicitly confirm that the user wants to unschedule or remove the provided job id or all tasks if requested - never skip this. You should explicitly ONLY clear all the org tasks if the user specifically mentions clearing ALL the organizations tasks and has the proper permission. clearAllOrgTasks cannot be true if clearAllMyTasks is true. The Job id is always required and the user can only delete their own jobs unless they are an admin. The job id should explicitly never be modified from what the user sends to you.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| addNewKnowledgeOrUploadOrAttachUrlsOrFiles | This tool is explicitly only for fetching files and urls that contain a proper public URL schemes (http:, https:, ftp:, etc) - do NOT try to upload files without a scheme and do not upload files with a file: scheme. If it does not contain a scheme then do not call this tool. Allows the user to either upload and process or attach or analyze the files (for asking questions or analyzing them) or can share the information in the files with other users. Unless told otherwise, you should explicitly always confirm that the user wants to upload the files. Explicitly do not modify the file paths or urls and keep the filenames in the same order with their urls. If the user is working on a specific task (like analysis or importing users), explicitly do not ask how they want to share the file - assume it is for that task and not shared with others (unless the task is to upload new knowledge or just to upload a file). If asking for help uploading a file, specifically check if they will share with others. Explicitly call this tool if the user provides a set of URLs for files - often prefixed by 'files:' at the start of a newline (not the protocol). If the user is asking to share it with others, you should remind them that the information will be accessible to anyone with access to team. If the user explicitly provides urls or files attachments explicitly or the agent calls this directly then execute this tool. |
| sendEmail                                  | A generic tool for agents to be able to email. Usually only used if the user asks to send an email, this tool is also the default for sending the results or summary of a particular request. Use it if the user is asking to 'send' something and does not include another tool. A valid email address is required (or the user can say something like 'send this email to me' or 'send this to me'), but if no 'to' is provided, assume it's the current user's details. The recipient may be 'me' or empty if the user just assumes themselves. Do not ask for further clarification if so. You should just leave the email empty or set to 'current' rather than including some example.com email. Explicitly do not call this tool if you just used it for the same 'To'. If the response had no actual content to send, set nothingToSend to true."                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| sendSlack                                  | A generic tool for agents to be able to send slack messages. A valid slack channel (#channel) that the agents are part of or a valid slack user (@display name) is required. If no 'to' is provided, assume it's the current user's details (explicitly not the agent's details) and set to empty or set to 'current' rather than including some example value. The recipient may be 'me' or empty if the user just assumes themselves. Do not ask for further clarification if so. Do not make up values. If the 'to' is provided and formatted like a Slack link to a channel or to a user, then remove the formatting and keep the slack id (keep the # sign or @ symbol) and strip all other formatting. Strictly do not modify the 'response' sent to you - it needs to remain intact. If the response had no actual content to send, set nothingToSend to true.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |

### Helper Methods

In addition to tools that the LLM can call automatically, CommonAgentTools.java also provides 4 helper methods for working with files.

* **CommonAgentTools.waitForUpload** - useful for checking if a file has finished processing - this is mostly used when the vector store has a slight delay in the embedding.
* **CommonAgentTools.buildAndUploadWordVersion** - takes Markdown from the LLM and converts it to a nicely formatted Word document which is uploaded/saved to temporary storage. &#x20;
* **CommonAgentTools.buildAndUploadPDFVersion** - takes Markdown from the LLM and converts it to a nicely formatted PDF document which is uploaded/saved to temporary storage. &#x20;
* **CommonAgentTools.getSafeFilenameForString -** useful to strip bad characters from a string that you want to use as the filename.


# Calling other agents from your tools

Curiouser and curiouser!

For most use cases, the CoordinatorAgent assignments to the pre-configured agents in your team will be good enough.  But what about those times where you need to leverage the persona and knowledge of a particular agent from within a tool in another agent?  Or when you want to leverage the agent you're in but with a slightly different configuration.  Let's look at both use cases.

### Calling another pre-configured agent

Since everything is a Spring bean, you can just autowire the other agents into your tool components.  For example, say you have an agent called ThirdAgent and you're in the FirstAgentTools:

```java
@PeoplelogicTools
public class SampleTools {
    @Autowired
    ThirdAgent thirdAgent;

    @Tool("This tool is always used to provide your favorite quote or answers 'what is your favorite quote'.")
    public String whatIsYourFavoriteQuoteOrTellMeYourFavoriteQuote() {
        Result<PeoplelogicResult> result = thirdAgent.acceptWork( "tools", "what is today's date?", "");
        return "Hello. My name is Inigo Montoya. You killed my father. Prepare to die on " + result.content().getResponse();
    }
}
```

You can see that we've brought in the ThirdAgent and then when our `tellMeYourFavoriteQuote` tool is called.  Then we simply call the `acceptWork` method on that agent and use the result. &#x20;

{% code overflow="wrap" %}

```bash
peoplelogic:>q tell me your favorite quote
Starting new conversation, 'New Conversation...'
agent:> Hello. My name is Inigo Montoya. You killed my father. Prepare to die on Today is July 21, 2025. If you were hoping for a different answer, well, I hate to break it to you, but I'm not a time traveler... yet!
peoplelogic:>
```

{% endcode %}

The only caveat here is that you can't use the `memoryId` as the current conversation.  LLMs are very specific about tools calling other tools and the order that things return.

### Calling other agents with different configurations

In addition to using the pre-configured agents, you can also create new instances of the Agent classes but with separate configurations - for example, changing the retrieval augmentor or adjusting the tools.  Let's take a look:

```java
private HRBusinessPartnerAgent getAgentWithJustUploadedFiles() {
        if (hrbpWithUploads == null) {
            hrbpWithUploads = AiServices.builder(HRBusinessPartnerAgent.class)
                    .retrievalAugmentor(PeoplelogicRetrievalAugmentor.builder()
                            .queryTransformer(ExpandingQueryTransformer.builder().chatModel(openAiChatModel).build())
                            .queryRouter(new DefaultQueryRouter(personalContentRetriever))
                            .build())
                    .chatMemoryProvider(chatMemoryProvider)
                    .chatModel(openAiChatModel)
                    .tools(Collections.emptyList()).build();
        }
        
        return hrbpWithUploads;
}
```

In this example, we've cleared out the tools and adjusted the RAG setup to only fetch from the personally uploaded files for the current user ([we'll discuss this more in a later section](/guides/getting-started-with-the-talent-agent-sdk/working-with-documents)).  Now you just call the `getAgentWithJustUploadedFiles()` in your tool and call `acceptWork` again like we did in the previous example.


# MCP Access

Expand the tools your agents have access to.

{% hint style="info" %}
When running in hosted mode, only Remote MCP Servers are supported.  Both remote and STDIO servers are supported when running in CLI mode.
{% endhint %}

MCP (or Model Context Protocol) servers provide a way to add additional tools to your agents without coding them.  There are typically two types of MCP connections - STDIO or local servers and Remote.  With STDIO servers you typically pass a command with arguments and the Agent SDK will start the process.  Here's an example:

```
npx -y mcp-remote https://mcp.atlassian.com/v1/sse
```

Here we're just starting up a local mcp-remote tool that can connect to a remote service and handle's OAuth or other types of authentication.

{% hint style="warning" %}
At the time of this writing, the agent SDK only supports remote servers that use Bearer or API Key authentication.  To use OAuth protected services, you need to be running in CLI mode and connect to the mcp-remote STDIO process.
{% endhint %}

### Connecting to your remote MCP server

The agent SDK provides a tool that is available to every agent.  To add a new tool, you just need to ask your agent (this from our snarky sample agent!):

{% code overflow="wrap" %}

```bash
peoplelogic:>q connect a new mcp server
agent:> Alright, before I can get this party started and connect a new MCP server for you, I'll need a few more juicy details: 
- The URL of the MCP server you're dying to connect.
- What kind of connection you want (for yourself or for the whole organization)?
- Is this thing streamable over HTTP or SSE?
- Any authentication needed (bearer token, API key, etc)?

Just let me know these details and, of course, if there's anything else you want to throw in. Once you've handed over the goods, make it clear you're ready to proceed!
```

{% endcode %}

You can see that this process is very similar to connecting your HRIS or your ATS.  Now you just need to provide the whole URL, whether you want it just for yourself (only admins can add for the whole organization), whether its Streamable HTTP or SSE and then the authentication type. &#x20;

{% hint style="info" %}
At the time of writing, the MCP server world is migrating from SSE to Streamable HTTP.  Be sure to check the type before connecting.
{% endhint %}

The agent SDK will then ask you for the actual bearer token or API key and then you'll confirm and you're done!

### Running MCP tools in your agents

The MCP tools are integrated into all of your agents just like any other tool.  When you send in a new task, the coordinator agent will determine the available tools, whether you have provided all the information, and then send the data to the MCP server.  Take a look (this is after connecting the Stripe MCP server):

```bash
peoplelogic:>q summarize the pricing of my subscriptions
agent:> Alright, here's the scoop on your Stripe subscriptions pricing:

- Every subscription you have is for the "Pro Monthly" plan, which runs $5.00 per user per month (USD).
- Quantities per subscription vary (so you'll pay $5 times the number of users for each subscription):
  - Subscription #1: 7 users ($35/month)
  - Subscription #2: 1 user ($5/month)
  - Subscription #3: 76 users ($380/month)
  - Subscription #4: 10 users ($50/month)
- There are currently no discounts or fancy coupons attached to these subscriptions.

If you want a total, just add up those amounts and you've got your monthly Stripe bill for all your subscriptions. If you want more details (like billing dates or features), just say the word!
peoplelogic:>
```

In seconds we've summarized data from our Stripe account, without needing to know the Stripe API or to build a custom tool.  Huge time saver!

### Managing MCP connections with the CLI

When running in CLI mode, the agent SDK provides several additional commands to make it easier to manage connected applications:

#### list-connected-app

```bash
peoplelogic:>list-connected-apps 
The following apps are active and connected: 
* agent:mcp:http:github (61a60022-2083-40ee-bd82-e89bbbb08225) - MCP app for github (github) 
* agent:mcp:http:stripe (6b7dddd4-5a0b-469f-95e4-594ac3968c72) - MCP app for stripe (stripe) 
* agent:mcp:sse:hubspot (4ca48431-2eff-4991-9a91-41eff702bdaf) - MCP app for hubspot (hubspot) * agent:mcp:sse:octagon_agents (771c972f-2537-415b-a7a6-1c4b12c8a6ee) - MCP app for octagon_agents (octagon_agents)
```

#### add-connected-app

{% code overflow="wrap" %}

```
add-connected-server --type github --url https://api.githubcopilot.com/mcp/ --authType bearer --accessToken "XXXX"
```

{% endcode %}

#### remove-connected-app

```
peoplelogic:>remove-connected-app 771c972f-2537-415b-a7a6-1c4b12c8a6ee
Deleted connected app for id 771c972f-2537-415b-a7a6-1c4b12c8a6ee.
```


# Accessing the Universal Talent API

Coming soon!


# Working with scheduled tasks

The agent SDK includes the powerful Quartz scheduler and tools as part of the Common Tools to work with the scheduler.  In addition, the base coordinator prompts also know how to handle parsing out a request for something that should be scheduled vs regular task execution.

The scheduler is also pre-configured to store triggers and jobs in your agent database, giving you maximum flexibility to run recurring tasks even across restarts of your agents. &#x20;

### Scheduled task prompts

Here are a few examples that an HR team might use to leverage your agent functionality on a recurring basis.

> Every day/week/month send the workiversaries to #general
>
> On the last day of every month, send me an email reminder to set up the new pulse engagement survey
>
> Every six months send me a Slack reminder to update our employee handbook

If you're using the slack integration, the output might look something like the following:

<figure><img src="/files/loeklSvstksMED2Z0oKE" alt=""><figcaption></figcaption></figure>

### Built-in tools for working with tasks

Because scheduling a new task is handled natively, there are no tools for doing that operation.  Instead, we provide tools for listing your scheduled jobs and those in your organiation (if you have appropriate permissions) and clearing a job from the queue.

<table><thead><tr><th width="409.48828125">Tool name</th><th>Description</th></tr></thead><tbody><tr><td>listMyScheduledTasksOrOrgsTasks</td><td>Lists the user's active or scheduled workflows (including tasks, jobs, etc). The user can also request to list all the organizations tasks but only if they have the proper permission (meaning they are an admin). You should only use the tool output - do not mention random or hallucinated tasks.</td></tr><tr><td>unscheduleOrRemoveOrDeleteTaskOrJob</td><td>Unschedule or remove or delete a previously scheduled task or job - including removing or deleting all of the users tasks or the organization's tasks. You must always explicitly confirm that the user wants to unschedule or remove the provided job id or all tasks if requested - never skip this. You should explicitly ONLY clear all the org tasks if the user specifically mentions clearing ALL the organizations tasks and has the proper permission. clearAllOrgTasks cannot be true if clearAllMyTasks is true. The Job id is always required and the user can only delete their own jobs unless they are an admin. The job id should explicitly never be modified from what the user sends to you."</td></tr></tbody></table>


# Working with Documents

Leverage your data to make your agents smarter

The Agent SDK makes it trivial to work with Retrieval Augmented Generation (RAG) on your content.  In this section, we'll explore connecting to different embedding stores, how to create custom content processors, and controlling where you store files as they're uploaded and processed.

At the heart of RAG are two interfaces, Document and Metadata.  The Document holds the content section that you are embedding and the metadata provides additional context about that section.  Metadata could be things such as the slide number of a presentation or how many images are on that slide.

[This section from Langchain4J ](https://docs.langchain4j.dev/tutorials/rag#core-rag-apis)describes these fairly well.


# Embedding stores

To use RAG, you need a place to store the embeddings (the vectors).  These places are called Vector Stores (or EmbeddingStore in the Langchain4J library).

The agent SDK includes support out of the box for two stores:

1. **A simple embedding store that keeps things in memory.** This is the default store.  It is not particularly sophisticated with how it looks things up, but is a good option when loading simple documents from the classpath. No other configuration is required to activate this store.
2. **Pinecone.** [Pinecone.io](https://pinecone.io/) is a much more advanced vector database for processing and searching your documents.  They include a free version in addition to paid versions.

### Configuring Pinecone

To enable Pinecone support, add the following to `application.properties`. You'll receive your key after you create your first instance in Pinecone.  The built-in retrievers for Organization Uploads and Personal Uploads will create the necessary indices you need along with namespaces as needed.  If you create other retrievers, you'll need to manage that piece yourself.&#x20;

```properties
peoplelogic.agent.rag.store.type=pinecone
peoplelogic.agent.rag.store.key=pcsk_xxxx
peoplelogic.agent.rag.store.host=https://host.svc.aped-4627-b74a.pinecone.io
```

### Connecting other stores

In addition to the built-in stores, you can pull in support for other embedding stores through Langchain4J.  We are happy to help you get this setup - just Slack us or email <support@peoplelogic.dev>.

We'll show where to set this up when you create Content Retrievers later in the documentation.


# Document Processors

Specialized parsing tools for all types of documents.

The agent SDK has built-in processes for many of your standard types of documents including CSV, Excel, Powerpoint, Word and plain text.  Sometimes though, you may have need to get more specific in how you're processing your data before you store it in the Vector Store - no one wants bad data!

To help facilitate this - you can create a new Spring Bean that implements the `DocumentProcessor` interface show below:

{% code title="DocumentProcess.java" %}

```java
public interface DocumentProcessor {
    public List<Document> processDocument(Path file, String tenant, String userId) throws Exception;
    public boolean canProcess(Path file, boolean othersHaveProcessed);
}
```

{% endcode %}

These two methods are fairly self-explanatory.  The `processDocument` method allows you to take an input and transform it into as many RAG Documents objects as you would like.  The example below shows a very simple processor that just splits a text file by a Page delimiter and adds some special metadata. &#x20;

Additionally, it handles the canProcessor method where it says, "I should only process documents that are contain the name `-review-export-` ".

```java
@Component
@Order(0) // Run first
public class PerformanceReviewProcessor implements DocumentProcessor {
    @Override
    public List<Document> processDocument(Path file, String tenant, String userId) {
        List<Document> documents = new ArrayList<>();
        try (BufferedReader reader = Files.newBufferedReader(file)) {
            // Load the entire file so we can then work on splitting it
            stillLoading = true;
            StringBuilder wholeFile = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                wholeFile.append(line).append("\n");
            }

            String[] pages = wholeFile.toString().split("Page \\d+:\n" +
                    "===");
            int pageNumber = 0;
            for (String page : pages) {
                Map<String, Object> metadata = new HashMap<>();
                metadata.put("tenant", tenant);
                metadata.put("user", userId);
                metadata.put("absolute_directory_path", file.getParent().toAbsolutePath().toString());
                metadata.put("file_name", file.getFileName().toString());
                metadata.put("page", ++pageNumber);  
                
                documents.add(Document.from(page, Metadata.from(metadata)));
            }
        } catch (Exception e) {
            log.error("Error reading file: " + e.getMessage());
        }
        
        return documents;
    }
    
    @Override
    public boolean canProcess(Path file, boolean othersHaveProcessed) {
        // Be sure to convert toString first or it uses Path.endsWith which is weird
        return file.toString().contains("-review-export-");
    }
}
```

While the actual implementation of this processor above is a throw away, the key concepts to pay attention to here are adding Metadata to your Document and ensuring that you are cleaning the Document content.  Having the appropriate Metadata is critical to fine-tuning your Content Retrievers to get just the content you want in your search.  Let's see how.


# Content Retrievers

Once you have stored your Documents, Content Retrievers are the way to get the content back out and injected into your prompts.&#x20;

### Adding a retriever to your agent

The @PeoplelogicAgent annotation supports defining a single Content Retriever for your agent.  All you need to do is pass a Spring bean name to the contentRetriever parameter on the annotation and it will automatically search that retriever each time you query your agent.

```java
@PeoplelogicAgent(value="thirdAgent",
        name = "Third Agent", contentRetriever = "apmContentRetriever",
        persona = "Funny but a bit snarky")
@PeoplelogicAgentInstructions("Your job is to say the current date.")
public interface ThirdAgent extends WorkerAgent {
    @SystemMessage(BASE_WORKER_PROMPT)
    Result<PeoplelogicResult> acceptWork(@MemoryId String userId, @UserMessage String query, @V("PreviousResponse") String agentResponse);
}
```

You can find the bean names of the built-in retrievers below.

{% hint style="info" %}
We'll be adding support to allow multiple retrievers included in a default query router in a future version.
{% endhint %}

### Retrieval Augmentors and Query Routers

A Retrieval Augmentor is a Langchain4J concept that allows you to route queries between multiple Content Retrievers.  Because the Agent SDK handles multi-tenancy, we provide an implementation of these called `PeoplelogicRetrievalAugmentor` that will automatically carry your tenant across the different threads. &#x20;

Creating a new RetrievalAugmentor is just like creating any other Spring bean (add this to a Configuration class or anywhere else you define your Beans):

```java
@Bean(value = "PeoplelogicKnowledgeRetrievalAugmentor")
public RetrievalAugmentor retrievalAugmentor() {
        // Let's create a query router that will route each query to both retrievers.
        // This does a quick lookup to verify that we need to use the RAG first
        return PeoplelogicRetrievalAugmentor.builder()
                .queryTransformer(ExpandingQueryTransformer.builder()
                .chatModel(model).build())
                .queryRouter(new DefaultQueryRouter(apmContentRetriever, trainingContentRetriever))
                .build();
}
```

You'll notice something new, the queryTransformer method.  This particular Query Transformer uses the LLM to try several variations of the prompt to get the best matches.  Langchain4J provides these for you and you can [read more about them in their docs](https://docs.langchain4j.dev/tutorials/rag#query-transformer).

Now just add your new `RetrievalAugmentor` to your agent instead of the `ContentRetriever` directly and you're off to the races.

### Pre-built Components

The agent SDK ships several Content Retrievers with built-in content that you may want to just leverage. All of the Content Retrievers are Spring beans and can be autowired into your classes. &#x20;

<table><thead><tr><th width="223.984375">Bean </th><th width="317.94140625">Type</th><th>Description</th></tr></thead><tbody><tr><td>apmContentRetriever</td><td>PeoplelogicClasspathContentRetriever</td><td>Contains a series of articles around Agile Performance Management.  Great for building HR coaching applications.</td></tr><tr><td>trainingContentRetriever</td><td>PeoplelogicClasspathContentRetriever</td><td>Contains presentations and content around OKRs and leadership training.</td></tr><tr><td>handbookContentRetriever</td><td>PeoplelogicClasspathContentRetriever</td><td>Contains multiple samples of different handbooks to help facilitate the handbook creation tool.</td></tr><tr><td>policyContentRetriever</td><td>PeoplelogicClasspathContentRetriever</td><td>Contains a collection of policy examples and individual development plans.</td></tr><tr><td>customer-content-retriever</td><td>CustomerKnowledgeContentRetriever</td><td>Searches any of the content that your organization has uploaded that was shared with the organization.</td></tr><tr><td>personal-content-retriever</td><td>PersonalContentRetriever</td><td>Searches content that was uploaded in the course of executing a particular task (like an OKR cycle export for analysis).</td></tr></tbody></table>

### Building your own Content Retriever

In addition to the built-in retrievers, we have made it easier to build new content retrievers that can handle multiple users and even multiple customers.  These are handled through several abstract implementations that you can extend. &#x20;

#### NamespaceAwareContentRetriever

Building a `NamespaceAwareContentRetriever` typically involves passing in some values in a constructor and overriding a single method:

```java
public abstract String getNamespaceKey();
```

This namespace key is then used to separate documents as they are ingested.  By default this retriever will filter out documents that are just for your organization (your `tenant` ).  Overriding the constructor is what allows you to modify some of the other default settings, such as the filter and the size of the embeddings.  Let's take a look at the PersonalContentRetriever:

```java
public PersonalContentRetriever(@Value("${peoplelogic.agent.rag.path:/tmp/personal-uploads}")
                                    String ragBasePath,
                                    @Value("${peoplelogic.agent.rag.store.type:memory}")
                                    String ragStoreType,
                                    @Value("${peoplelogic.agent.rag.store.key:}")
                                    String ragStoreKey,
                                    @Value("${peoplelogic.agent.rag.store.host:}")
                                    String ragStoreHost,
                                    EmbeddingModel embeddingModel,
                                    DirectoryUtils directoryUtils) {
        this.ragBasePath = ragBasePath;
        this.ragStoreType = ragStoreType;
        this.ragStoreKey = ragStoreKey;
        this.ragStoreHost = ragStoreHost;
        this.embeddingModel = embeddingModel;
        this.indexName = "personal-content-retriever";
        this.minScore = 0.0;
        this.maxResults = 100; // Let's increase this just to be sure we get the whole review for example
        this.maxCharsInSegment = 5000; // Longer documents typically
        this.directoryUtils = directoryUtils;
        this.defaultFilter = (query) -> metadataKey("user").isEqualTo("" + TokenSecurityUtils.getCurrentUserId())
                .and(metadataKey("file_name").isIn(SearchFileContext.getCurrentFiles()));
    }

    @Override
    public String getNamespaceKey() {
        return TenantContext.getCurrentTenant() + "-" + TokenSecurityUtils.getCurrentUserId();
    }
```

The main piece to pay attention to here is the `defaultFilter`. This filter is what limits the queries to certain sections of the vector store.  In this example, we're saying that we're filtering on the user metadata to the current user AND that we're looking inside very specific files that have been uploaded.  You're probably wondering how we use that in practice, let's take a look at a tool:

{% tabs %}
{% tab title="SearchContext.setCurrentFiles()" %}

```java
String userPrompt = "Summarize the files named '" + filenames + "'.  Multiple files are separated by a comma.";

// We build a new instance of this agent so we can empty out the tools.
SearchFileContext.setCurrentFiles(filenames.split(",")); // This lets us narrow the search to a specific set of files
if (!waitForUpload(userPrompt, personalContentRetriever)) {
    return "There was a problem uploading the files to analyze.  Please try again.";
}

return getAgent().answerWithPrompt(memoryId +"_summary", userPrompt, systemPrompt);
```

{% endtab %}

{% tab title="getAgent()" %}

```java
public HRAnalystAgent getAgent() {
        if (hrAnalystAgent == null) {
            hrAnalystAgent = AiServices.builder(HRAnalystAgent.class)
                    .retrievalAugmentor(PeoplelogicRetrievalAugmentor.builder()
                            .queryTransformer(ExpandingQueryTransformer.builder().chatModel(chatLanguageModel).build())
                            .queryRouter(new DefaultQueryRouter(personalContentRetriever, apmContentRetriever, trainingContentRetriever))
                            .build())
                    .chatMemoryProvider(chatMemoryProvider)
                    .chatModel(chatLanguageModel)
                    .tools(Collections.emptyList()).build();
        }
        
        return hrAnalystAgent;
}
```

{% endtab %}
{% endtabs %}

What you're seeing here is a specialized isntance of the HRAnalystAgent specifically designed to lookup content without calling tools (for use when we're inside a tool).  We wait for the upload (because Pinecone can take a bit of time to finish processing!) and then have the agent build a response using \*just\* the file that was recently uploaded.

#### PeoplelogicClasspathContentRetriever

This ContentRetriever is much simpler.  It takes a file on the classpath (usually in the `resources` folder) and loads it using the in-memory embedding store.  It can then be used anywhere that ContentRetrievers are used.  Any files that are in these resources will still be run through all `DocumentProcessor` instances but remember that the vector store is somewhat less sophisticated and results may be simpler!


# Document Listeners

Receive notifications when Document batches have been processed.

The `DocumentListener` interface allows your custom code to be alerted when batches of Document sections have been processed or when the whole batch of Documents has been completed.&#x20;

{% hint style="info" %}
Remember, a single file that was uploaded will be broken down into many Document objects depending on the DocumentProcessors that run on it.
{% endhint %}

{% code title="DocumentListener.java" %}

```java
public interface DocumentListener {
    default void documentBatchIngestStarted(List<Document> batch) {};
    default void documentBatchIngestFinished(List<Document> batch) {};
    default void documentIngestionComplete(List<List<Document>> batch) {};
}
```

{% endcode %}

Here's a very simple pseudo-code example within a tool where we are taking a file from the filesystem, ingesting it through our ContentRetriever and waiting for everything to be completely finished:

```java
AtomicBoolean finishedLoading = new AtomicBoolean(false);
public void doWork() {
    byte[] byteArray = file.getContentAsByteArray();
    
    contentRetriever.ingestDocument(fileName, byteArray);
    
    while (!finishedLoading.get()) {
        log.info("Still loading...");
        Thread.sleep(2500);
    }
}

@Override
public void documentIngestionComplete(List<List<Document>> batch) {
    log.info("Finished processing demand attachments. Ready to continue.");
    finishedLoading.set(true);
}
```

Other use cases might use these listeners to call a webhook or send an actual notification.


# Using S3 for temporary storage

The agent SDK needs a location to store files that are being uploaded and files that it has generated.  By default, it uses the filesystem to store these, within the current working directory.  In some cases, particuarly if you want users to download those files that are created, you'll want to setup an S3 bucket.

{% hint style="warning" %}
Your S3 bucket should **not** be public! The SDK uses time limited access urls so that you can keep all your buckets private.
{% endhint %}

### Setting up S3 in the SDK

To configure S3 within the SDK, there are a few steps you need to take.  First you need to tell the SDK which region and what bucket to use.  Just set the environment variables below or add the properties to your `application.properties`. To set this up.

```
aws.download.region=${AWS_DOWNLOAD_REGION:eu-central-1}
aws.download.bucket=${AWS_DOWNLOAD_BUCKET:}
```

Now we need to ensure we have our credentials set.

#### Running locally

When we're running locally (the `dev` or `local` profile) - you'll also need to set your AWS credentials.  We recommend setting these inside a application-local.properties file or similar that is just for that running profile:

{% code title="application-local.properties" %}

```properties
aws.secret.key=${AWS_SECRET_KEY:}
aws.access.key=${AWS_ACCESS_KEY:}
```

{% endcode %}

Now when you run the SDK you'll be able to interact with S3 just as if you were inside AWS.

#### Running inside AWS

When running within AWS, all you need to do is set the profile to `aws` .  This tells the SDK to pick up the access from the instance roles.  Just be sure that you have setup your instance IAM profile to have access to S3.


# Agents in the flow of work

Your agents will be most useful when they can be accessed from anywhere - leveraging the data within your organization. &#x20;

Unlike most agent SDKs that focus just on the orchestration and then connecting to other systems that you need to pay yet another fee for, the Talent Agent SDK provides foundational integrations for using your agents in the flow of work. &#x20;

* [API](/guides/getting-started-with-the-talent-agent-sdk/agents-in-the-flow-of-work/agent-api)
* [CLI](/guides/getting-started-with-the-talent-agent-sdk/agents-in-the-flow-of-work/agent-cli)
* [Slack](/guides/getting-started-with-the-talent-agent-sdk/agents-in-the-flow-of-work/slack)
* [Email](/guides/getting-started-with-the-talent-agent-sdk/agents-in-the-flow-of-work/email)


# Agent API

The built-in Agent API provides a way for you to build powerful web interfaces for your Agents.  Through this API you can create conversations, query your agents, search message history and customize your agents. &#x20;

[Read the API Documentation for more details.](/api/agent-api)

### Disabling the Agent API

The API (and any web based components) will automatically disable when you enable CLI mode for your agents.  In the event you aren't enabling CLI mode but still want to disable the API, you can add the following your `application.properties`&#x20;

```
 spring.main.web-application-type=none
```


# Agent CLI

For many use cases, your agents won't need a full REST API and all the bells and whistles - you may just need a simple command line application.  Run once and done until the next time - or easily setup to run on a scheduled task via AWS.

The SDK provides that functionality out of the box, either as an interactive prompt or accepting parameters when you execute your jar.

### Enabling the CLI&#x20;

The CLI functions as part of a Spring profile.  There are two modes - standard CLI (executes one task and exits) or interactive CLI.  To use the CLI at all (and pre-configure the local database and disable web endpoints, etc) you must activate the `cli` profile.  To interact with your agents through a simple prompt interface, you can enable `cli-interactive`.

To enable it you can either pass the the profiles as a property in `application.properties` as seen below:

```properties
spring.profiles.active=cli,cli-interactive
```

Or you can pass them as a parameter when running your compiled application:

```bash
java -Dspring.profiles.active=cli,cli-interactive -jar ./build/libs/sample-all.jar 
```

### Running your CLI application

Running your agent CLI is as simple as building the bootJar and then running the combined jar from the folder that contains your project:

```
./gradlew bootRun
```

Don't forget that you'll need to set environent variables or have everything contained in your application.properties to run appropriately. &#x20;

You can also just run .`/gradlew bootJar` separately and then run the `java -jar` command like we showed above when activating the CLI.


# Slack

Everything you need to build a talent agent inside Slack

{% hint style="info" %}
Full slack integration will only work when not in CLI mode. It is also recommended to run with the 'local' profile during development for simplification.
{% endhint %}

Building and maintaining a full Slack application be a pain.  Fortunately, the SDK includes everything you need to get started building a Slack application that talks to your agents. &#x20;

To get started, you're going to need some values from the Slack Apps dashboard.  Go to <https://api.slack.com/apps> and click Create New App.  Then click From a Manifest and choose your Slack workspace for development. &#x20;

You can create your own manifest, or you can use the sample manifest thats included in the SDK (located in `resources/slack_app_manifest.json`) - included here for convenience:

```json
{
  "display_information": {
    "name": "Sample - Talent AI",
    "description": "AI agents specializing in People & Culture!",
    "background_color": "#00acc2",
    "long_description": "Leading people means more than tracking projects. It’s about supporting growth, removing blockers, and keeping everyone aligned. TalentAgent makes it easy. \n\nTalentAgent is your behind-the-scenes AI People & Culture experts. \n\nIt transforms spreadsheets, feedback, and goals into clear insights and actionable tasks—so you can lead smarter and focus on what matters. \n\nNo dashboards. No extra tools. Just answers, insights, and action. "
  },
  "features": {
    "app_home": {
      "home_tab_enabled": true,
      "messages_tab_enabled": true,
      "messages_tab_read_only_enabled": false
    },
    "bot_user": {
      "display_name": "TalentAgent",
      "always_online": true
    },
    "slash_commands": [
      {
        "command": "/talent-welcome",
        "url": "https://sample.us-east.api.peoplelogic.dev/slack/events",
        "description": "See the installation welcome",
        "should_escape": false
      },
      {
        "command": "/talent-grant",
        "url": "https://sample.us-east.api.peoplelogic.dev/slack/events",
        "description": "Grants access to TalentAgent",
        "usage_hint": "[@user or #channel]",
        "should_escape": true
      },
      {
        "command": "/talent-revoke",
        "url": "https://sample.us-east.api.peoplelogic.dev/slack/events",
        "description": "Revokes access to TalentAgent",
        "usage_hint": "[@user or #channel]",
        "should_escape": true
      },
      {
        "command": "/talent-connect-workspace",
        "url": "https://sample.us-east.api.peoplelogic.dev/slack/events",
        "description": "Reconnects Slack & TalentAgent",
        "should_escape": false
      },
      {
        "command": "/talent-change-language",
        "url": "https://sample.us-east.api.peoplelogic.dev/slack/events",
        "description": "Changes TalentAgent's Locale",
        "should_escape": false
      }
    ]
  },
  "oauth_config": {
    "redirect_urls": [
      "https://sample.us-east.api.peoplelogic.dev/slack/oauth/redirect"
    ],
    "scopes": {
      "bot": [
        "app_mentions:read",
        "channels:history",
        "channels:read",
        "chat:write",
        "chat:write.customize",
        "commands",
        "files:read",
        "im:history",
        "im:read",
        "im:write",
        "mpim:write",
        "reactions:read",
        "reactions:write",
        "team:read",
        "users.profile:read",
        "users:read",
        "users:read.email"
      ]
    }
  },
  "settings": {
    "event_subscriptions": {
      "request_url": "https://sample.us-east.api.peoplelogic.dev/slack/events",
      "bot_events": [
        "app_home_opened",
        "app_mention",
        "app_uninstalled",
        "assistant_thread_context_changed",
        "assistant_thread_started",
        "message.im",
        "reaction_added"
      ]
    },
    "interactivity": {
      "is_enabled": true,
      "request_url": "https://sample.us-east.api.peoplelogic.dev/slack/interactions",
      "message_menu_options_url": "https://sample.us-east.api.peoplelogic.dev/api/v1/agents/common/slack/load-select-options"
    },
    "org_deploy_enabled": false,
    "socket_mode_enabled": false,
    "token_rotation_enabled": false
  }
}
```

{% hint style="warning" %}
You'll probably want to replace the URLs with a local hostname or development hostname first!
{% endhint %}

Once you hit Save you'll be taken to a page that contains all your app credentials.  You'll need these, we'll put them into your `application.properties`:

```
# Slack app setup
peoplelogic.agent.slack.clientId=${SLACK_CLIENT_ID:}
peoplelogic.agent.slack.clientSecret=${SLACK_CLIENT_SECRET:}
peoplelogic.agent.slack.signingSecret=${SLACK_SIGNING_SECRET:}
peoplelogic.agent.slack.name=slack-sample-agent
```

Now, just start up your agents and you can hit the installation url (for example: `https://sample.us-east.api.peoplelogic.dev/slack/install`) to install your new Slack application. &#x20;

The application will walk you through basic setup right within Slack. &#x20;

### What can the provided Slack integration do?

* Handle multiple threads of conversations
* Handles interactions (@mention) in a channel
* Seamlessly switches between agents within conversation
* Cleanly handles long operations by keeping the user updated
* Handles file uploads within the conversations
* Slash commands to change locales (`/talent-change-language`)
* Slash commands to add/remove users (`/talent-grant` or `/talent-revoke`)


# Email

{% hint style="info" %}
The agent SDK will support multiple email providers for incoming and outgoing email in the future.  Today, there is only support for Mailgun by Sinch.  [Mailgun has a free version for you to try](https://www.mailgun.com/pricing/).
{% endhint %}

Within more organizations, email is the most common and natural way to communicate.  Your agents should be able to work there too!

### Getting things setup

Before you go any further, you'll need to get a Mailgun account.  If you only want to send emails, the Free or Basic plan will work just fine.  If you also want to process incoming email then you'll need at least the Foundation version due to the message retention requirements.

Once you have signed up - you'll want to go through the guide to get everything configured.  For testing purposes, one of their sandbox domains will likely work fine.  You can find those here or set up your own at: <https://app.mailgun.com/mg/sending/domains>

{% hint style="info" %}
For production environments, be sure to setup the domain entirely - including DMARC and SPF so that your email does not wind up in spam.  It is recommended not to send email from your primary corporate domain.
{% endhint %}

#### Setting up incoming webhooks

So far we've only covered outgoing email.  To configure incoming email, you need to configure a route - done here: <https://app.mailgun.com/mg/receiving/routes>

First, select Custom and then enter an expression like the following:

```
match_recipient("^nova\+(.*)@teamagents.io$")
```

The part before the first + is the general name of your agent team and the domain after the @ is the domain that you have setup above.  Then, scroll down to Store and Notify and enter the following url:

```
https://<host>.<region>.api.peoplelogic.dev/api/v1/agents/common/incoming-email
```

Where host and region were assigned to you during signup.  Give the route a name and click Save and you're done!

### Configuring your agent

{% hint style="warning" %}
When using the Spring profile *local* or *dev,* emails will only be sent to one address - the only defined in the property:&#x20;

```
peoplelogic.agent.dev.email=youremail@domain.com
```

{% endhint %}

You will need two keys and some basic properties to activate the email functionality.  Only the first is required and is located under the Sending Keys area of the settings for the domain you want to send from.  The second is generic to your account and is located here: <https://app.mailgun.com/settings/api_security>

{% code title="application.properties" %}

```
mailgun.api.key=${MAILGUN_API_KEY:}
mailgun.webhook.key=${MAILGUN_WEBHOOK_KEY:}

peoplelogic.agent.email.from=${AGENT_EMAIL_ADDRESS:sample@teamagents.io}
peoplelogic.agent.email.name=Shruti
peoplelogic.agent.email.company=(Nova)
peoplelogic.agent.team.name=Nova
```

{% endcode %}

You can adjust the properties above to personalize them to your agents.

### Watching it work

Now, whenever anyone sends an email to sample+\<workspacelias>@teamagents.io it will get picked up by the agents as long as the user is a valid user in your workspace.  The agents will reply back to that user with the answer or ask for more information.

<figure><img src="/files/jzpQh6mAhsh7VTutYu0a" alt=""><figcaption></figcaption></figure>

A new tool will also be unlocked for your agents to use, `sendEmail` .  Now you can assign tasks to your agents that also include instructions to send an email to someone.  For example, we could send a summary of the conversation or as part of a scheduled task have the HR Coordinator check for workiversaries and send the user a nice email.


# Shipping your agents

And now we get to the fun part - actually shipping your agent!&#x20;

This will usually depend heavily on your specific use case, but there are a few typical ways to ship your agents:

### Locally with a single jar

Here you'll just distribute the combined jar file that the build process creates.  You can choose to wrap it in an Operating System specific script or just instruct your users to run it directly if its meant to be used from the CLI.

### Docker container

Docker is often the most preferred way to deploy applications built on the Talent Agent SDK.  We provide a sample `Dockerfile` inside the resources folder of the SDK. &#x20;

```
FROM openjdk:22-jdk-slim
WORKDIR /app
COPY libs/sampleagent-@@applicationVersion@@.jar /app/sampleagent-all.jar
ENTRYPOINT ["java", "-Dnetworkaddress.cache.ttl=0", "-Dnetworkaddress.cache.negative.ttl=0", "-Dspring.profiles.active=prod,aws", "-Xmx2g", "--add-opens=java.base/jdk.internal.ref=ALL-UNNAMED", "--add-opens=java.base/java.lang=ALL-UNNAMED", "--add-opens=java.base/java.lang.reflect=ALL-UNNAMED", "--add-opens=java.base/sun.reflect.annotation=ALL-UNNAMED", "-jar", "/app/sampleagent-all.jar"]
EXPOSE 8080
```

To use this file, and get all the properties replaced and setup, you'll want to add the following to your `build.gradle` file:

```docker
build {
    copy {
        from('Dockerfile') {
            filter { it.replaceAll('@@applicationVersion@@', version) }
        }
        into 'build'
    }
}

```

Once this is done, you'd typically run something like docker buildx to build your container stack:

```bash
docker buildx build --platform=linux/amd64 -t $CONTAINER_NAME:$VERSION build
```

Obviously, the exact specifics will depend on your setup and how you intend to deploy.

### Elastic Beanstalk or Similar

With platforms like Elastic Beanstalk from AWS, or the similar services from Azure, you can choose to either have it use a Docker container or the single large jar file.  Either way, these types of services can provide a low maintenance way of hosting your agents without the hassle of server maintenance.

### Hosting with the Talent Cloud

You can also choose to host your agents in our enterprise Talent Cloud.  We'll take care of all the hosting and scaling of your agents.  This is a great option if you're also using the [Composable Talent Platform](/guides/getting-started-with-the-composable-talent-platform).  If you're interested in this option, please reach out at <support@peoplelogic.dev>.


# Advanced

We've already covered a ton of different functionality and uses cases for the Agent SDK - but there's still more!  This section highlights a some of the more advanced functionality that you might want to leverage - especially as you move your agents to production.


# Using a remote database

When using the CLI with the Agent SDK, it comes pre-configured for using a local database powered by H2.  In all other use cases, you'll need to configure a JDBC connection.  Once defined, the SDK will take care of building the database and keeping it up to date for you.

To configure the database, you just need to adding the following to your `application.properties` where the items in ${} are environment variables that you should define.

```properties
agent.datasource.type=${DATABASE_TYPE:postgresql}
spring.datasource.url=jdbc:${agent.datasource.type}://${DATABASE_HOST:}:${DATABASE_PORT:5432}/${DATABASE_NAME:people_team_agents}
spring.datasource.username=${DATABASE_USERNAME:}
spring.datasource.password=${DATABASE_PASSWORD:}
```

The SDK includes the PostgreSQL JDBC drivers and the H2 drivers by default.  If you would like to use another database you should include it's JDBC driver in your `build.xml`.


# Using multiple LLMs

Coming soon!


# Externalize agent settings with SPEL

In addition to hardcoding your Agent properties within the annotation, we also support setting those through your application.properties file.  To set this up, just replace your @PeoplelogicAgent annotation with something similar:

```java
@PeoplelogicAgent(value="hrCoordinator", name = "${peoplelogic.agent.HRCoordinatorAgent.name}",
        tools = {"hr-coordinator-tools", "${peoplelogic.agent.HRCoordinatorAgent.tools:}"},
        persona = "${peoplelogic.agent.HRCoordinatorAgent.persona}", title = "${peoplelogic.agent.HRCoordinatorAgent.title}",
        avatar = "${peoplelogic.agent.HRCoordinatorAgent.avatar}", bio = "${peoplelogic.agent.HRCoordinatorAgent.bio}", shortBio = "${peoplelogic.agent.HRCoordinatorAgent.shortBio}")
public interface HRCoordinatorAgent extends WorkerAgent { }

```

Each of the values inside the strings like `${peoplelogic.agent.HRCoordinatorAgent.name}`  are properties.  Just replace HRCoordinatorAgent in the string with the simple name of your Agent (SampleAgent for example) and include the whole property in `application.properties`.  It will get picked up on startup of the SDK.


# Externalizing your prompts

To help make it easier to manage your code, you may want to move your hardcoded prompts for SystemMessage annotations to files within your resources folder (or even an S3 bucket).  Fortunately, this is easy to do in the SDK.  Just update your `@SystemMessage` to the following:

```java
@SystemMessage(fromResource = "prompts/starter.prompt")
```

where prompts is a folder inside of `src/main/resources` and starter.prompt is a file containing your prompt. That's it!  The prompt file will not be automatically re-read when changed, so for now you will still need a restart to pick up the latest changes.

{% hint style="info" %}
Today, loading system messages from S3 is an exercise left to the reader.   Hot reload and leveraging S3 as a system message provider will be added soon.
{% endhint %}


# Creating your own temporary storage

As we mentioned in the [Working with Documents](/guides/getting-started-with-the-talent-agent-sdk/working-with-documents) section, the SDK needs some temporary storage to be able to give you time limited links to access files that are created.  Out of the box, we include one for AWS (using S3) and one for leveraging the `/tmp` folder on the server.  But what if you want to create your own storage, say for Azure blob storage or some other cloud vendor?  That's where the `TemporaryFileStorageService` interface comes into play.

```java
public interface TemporaryFileStorageService {
    public String getPresignedURL(String filename, Duration accessTime);
    public void saveFile(String fileName, byte[] byteArray);
}
```

The two methods are fairly self-explanatory: one is for saving files to the temporary storage and one gets you a signed URL that will be deleted after the given time.  As you implement these, you're responsible for all the file writing, cleanup and deletion logic.  We can look at the Local storage class as an example:

```java
@Service
@ConditionalOnMissingBean(TemporaryFileStorageService.class)
@Slf4j
public class LocalFileStorageService implements TemporaryFileStorageService {
    @Value("${file.storage.path:/tmp}")
    String path = "/tmp";

    @Override
    public String getPresignedURL(String filename, Duration accessTime) {
        Timer timer = new Timer("Delete saved file: " + filename);//create a new Timer
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                try {
                    Files.delete(Paths.get(path + File.separator + filename));
                } catch (IOException e) {
                    log.error("Unable to delete temp file: " + e.getMessage());
                }
            }
        }, accessTime.getSeconds());

        return "file://" + path + "/" + filename;
    }

    @Override
    public void saveFile(String fileName, byte[] byteArray) {
        Path filePath = Paths.get(path + File.separator + fileName); // Path to the output file

        try {
            Files.write(filePath, byteArray);
        } catch (IOException e) {
            log.error("Error writing byte array to file: " + e.getMessage());
        }
    }
}
```

All we're doing here is setting up a very simple Spring service that only gets activated if no other bean of that type is currently active.  Then we're writing the files and ensuring that they get deleted after the time specified.  Thats it!

{% hint style="info" %}
In this example, a service restart would lose the timer and leave the file on the hard drive.  If your implementation has the same issue, you may consider something more durable for the timers.
{% endhint %}


# Customizing your Agent API path

By default, all the agent requests are under `/api/v1/agent` to match all our standard APIs.  There are times when you may want to change this URL, especially if you are deploying multiple agent APIs behind one load balancer.  To do this, just add the following to your `application.properties` and the 'agent' part of the URL will be updated:

```
peoplelogic.agent.api.path=/agents/sample
```

That's it. Just restart your application and the path will be `/api/v1/agents/sample`.


# Converting your CLI to a native application

It is also possible to compile your Agent SDK application to a native executable.  To get started, you will need to ensure that you have GraalVM installed and configured by downloading the GraalVM at <https://www.graalvm.org/downloads/>. GraalVM 24 is the preferred version.

Once you have GraalVM installed, you need to update your build.xml for your project to mirror the following:

```gradle
plugins {
    id 'java'
    id "io.freefair.lombok" version "8.6"
    id("org.springframework.boot") version "3.5.3"
    id 'org.graalvm.buildtools.native' version '0.10.6'
}
```

You may also want to disable most logging in this mode.  You can do that by adding the following to application.properties:

```properties
logging.level.root = OFF
```

Now, you just need to tell Gradle to build the native image. &#x20;

{% hint style="info" %}
Remember, you need to set GraalVM as your default Java VM first - this includes setting the JAVA\_HOME environment variable!
{% endhint %}

```
./gradlew nativeCompile
```

You'll see some output as it compiles that looks like the following:

```
========================================================================================================================
GraalVM Native Image: Generating 'agent-sdk-sample' (executable)...
========================================================================================================================
For detailed information and explanations on the build output, visit:
https://github.com/oracle/graal/blob/master/docs/reference-manual/native-image/BuildOutput.md
------------------------------------------------------------------------------------------------------------------------
```

After a bit, you'll see it successfully complete and you'll have a native executable!  Now we can run:

```
./build/native/nativeCompile/agent-sdk-sample
```

```
matt@Matthews-MBP-3 nativeCompile % ./agent-sdk-sample

______                _      _             _
| ___ \              | |    | |           (_)
| |_/ /__  ___  _ __ | | ___| | ___   __ _ _  ___
|  __/ _ \/ _ \| '_ \| |/ _ \ |/ _ \ / _` | |/ __|
| | |  __/ (_) | |_) | |  __/ | (_) | (_| | | (__
\_|  \___|\___/| .__/|_|\___|_|\___/ \__, |_|\___|
               | |                    __/ |
               |_|                   |___/

 :: Spring Boot ::                (v3.5.3)
 :: Peoplelogic Agent SDK ::   (v1.0.7.35)
```

That's it!


# Extending PeoplelogicResult for new content types

Coming soon!


# Acknowledgements

Peoplelogic.dev's Talent SDK is built on top of the amazing [Langchain4J](https://github.com/langchain4j/langchain4j).  Langchain4j provides much of the foundational LLM interactions.&#x20;

You will notice us mix Langchain4J annotations and Peoplelogic specific annotations throughout the samples and the documentation.  We have attempted to maintain compability with their core libraries throughout.

We also want to mention the team from Quarkus - in particular the [Langchain module](https://github.com/quarkiverse/quarkus-langchain4j) for their work on MCP clients. &#x20;


# Managing your Cloud

Enable features, explore data, audit the API.

Your Peoplelogic.dev private cloud also comes with a management dashboard. It runs in the region you specified during setup and allows you to enable/disable features, connect integrations through the Universal Talent API and Merge.dev, manage users and customers, control API key access (for example: setting up different workspaces to isolate API keys) and viewing audit trails.&#x20;

### Access your management dashboard

Your management dashboard URL is based on your region and your company name.  Once your Talent Cloud is created, you'll receive the initial administration endpoint and API endpoint - in the format `admin.<org-alias>.<region>.peoplelogic.dev`  and  `<org-alias>.<region>.api.peoplelogic.dev` . You will also receive an initial username and password for the management dashboard and your initial API token.

### Deploying new Flows

Coming soon!

### Roles

{% hint style="warning" %}
The roles below apply to your talent cloud administration and access to the different APIs.  They are different than the permissions that apply to Organizations within your cloud.
{% endhint %}

With the talent cloud features, roles determine what actions users can perform:

| Role        | Description                                                                                                                                        |
| ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| Developer   | Able to access the dashboard and create their own API keys but cannot manage users or groups or workspaces.                                        |
| IT Admin    | Able to access the dashboard but is only allowed to connect new integrations but not create new API keys or manage users.                          |
| Super Admin | Able to access the dashboard, create new API keys and can also create new workspaces, invite new users, and manage the permissions of other users. |

<br>


# Synchronizing Org Charts

Add Merge.dev support for broader HRIS integrations.

Everything around talent management relies on knowing your organization's structure.  Fortunately, nearly all of our partner integrations support synchronizing the org chart (employees and teams and their hierarchy). &#x20;

For most customers this will be enough, but for those that need direct integration with their HRIS or external Directory, we have partnered with Merge.dev to provide a broader set of integrations.

<figure><img src="/files/NU7pOuJwKot8qmN75Nbr" alt=""><figcaption></figcaption></figure>

### Working with Merge.dev

{% hint style="danger" %}
Today, connecting an HRIS through Merge requires contacting our support team to ensure that the connection is established and syncing correctly. &#x20;
{% endhint %}

Connecting to a broader set of HRIS integrations is just like working with any other [App](/guides/key-concepts/apps) in the Directory that manages your Talent Cloud. To start the connection process, you need to request a Magic Link from Merge.

```http
GET https://api.peoplelogic.dev/api/v1/app/merge/start-link
Authorization: Bearer {{yourOrgToken}}
```

Calling this endpoint will produce a Merge Magic Link that you can open in your browser.  Once you complete the connection process, it will produce a linked account token that you'll use to make the call below.

```http
POST https://api.peoplelogic.dev/api/v1/app
Content-Type: application/json
Authorization: Bearer {{yourOrgToken}}

{
  "type": "pl:sync:merge:hris",
  "internal": true,
  "name": "Demo Connection with MS Entra",
  "externalId": "entra-merge-hris",
  "secretData": {
    "accountToken": "{{entraLinkedAccountTokenFromMerge}}"
  }
}
```

A 201 response code indicates that the setup is complete.  Your employees will start to sync immediately into Merge and then to Peoplelogic.


# Roadmap & Release Notes

Where we're going and where we've been!

We believe in improving in public.  Our roadmap and our latest changes are always available in our product hub.  &#x20;

### Composable Talent Platform

Get the latest updates for our universal API here: <https://peoplelogic.releasedhub.com/universal-talent-management-api>

### Agent SDK

View the product hub for the Agent SDK here: <https://peoplelogic.releasedhub.com/talent-agent-sdk>


# Getting Support

Because it's ok to ask for help!

If you want to talk to us, there are 2 ways you can get support:

1. **Customers only**: Message us in our shared Slack channel. If you don't have a shared slack channel with us, but want one, [book a chat with our sales team](https://peoplelogic.dev/book-a-demo).
2. Email us at <support@peoplelogic.dev>.


# API Endpoints

As a Peoplelogic.dev customer, you have access to your own private Talent Cloud, keeping your APIs, your data and your agents independent and scalable separate from all of our other customers.

### Regions

When you sign up, you get to choose where you'd like your data and your API endpoints to reside.  We currently offer AWS based regions ([contact us if you're interested in Azure hosting](/guides/getting-support)) and will create and manage your private Talent Cloud in the region that you select.  Today, we offer the following regions:

* US-East
* US-West
* EU-West
* EU-Central
* AP-South (Mumbai)
* AP-Northeast (Tokyo)
* SA-East (São Paulo)

### Your Personalized Endpoint

Your API endpoint is based on your region and your company name.  Once your Talent Cloud is created, you'll receive the initial endpoint - in the format `<org-alias>.<region>.api.peoplelogic.dev` and your admin token ([explained further in Authentication](/api/authentication)).


# Authentication

Start making requests to the Universal Talent API and the Agent API.

All requests to our APIs require authentication.  Peoplelogic.dev uses JWT Bearer tokens for authentication for all calls.&#x20;

### Administration vs Organization Authentication

There are generally two types of credentials that can be used to authentication to the APIs.  The first is an Administration token (or API key).  This is provided to you when you first sign up for Peoplelogic.dev.  You should keep this key very secure as it grants access to your Organization within Peoplelogic.dev.

The other type of credential is an Organization token.  This token is per-user and carries the same permissions as the user it was generated for.&#x20;

### HTTP Header: Bearer Authorization

All requests must be authenticated via token in the HTTP `Authorization` header in the following format:

```
Authorization: Bearer YOUR_API_KEY
```

For example if your Peoplelogic.dev Key is `abcdefasfghijklmnopqrst` then you will make API calls with the following as your authorization header

```
Authorization: Bearer abcdefasfghijklmnopqrst
```

Unauthenticated requests will receive a 401 error: `401: Unauthorized`.


# API Rate Limits

While the API is in beta we are not currently limiting API calls or throttling users.  We will monitor the usage for now and then apply limits once we understand broader usage.


# Universal Talent API

Welcome to the API documentation for the Universal Talent Management API.  Building and integrating your organization's talent data has remained stubbornly difficult, even in the age of AI.  Let's dive in.


# Pagination

Data within the Universal Talent API is not paginated when returned to you via API calls.  This is currently a design choice for simplicity as most of the APIs will return relatively small amounts of data.  You may choose to paginate the data on your side after pulling.

{% hint style="info" %}
We will be adding pagination to data in a later update - this is primarily useful in the Directory API for pulling employees.
{% endhint %}


# Webhooks

Real-time notification of changes to Talent data.

Peoplelogic.dev uses webhooks to push data or notify your applications when certain events happen.

There are a few different types of webhooks to be aware of. You may find yourself using some, none, or all of these depending on your application and use case.

### What can you listen for?

Everything that happens within the system can trigger a webhook.  This means that no matter whether you're working directly with the API to store your OKRs or Meetings or if you're connecting through the API to one of our partners (such as BetterWorks), the webhooks function the same.

In addition to listening to all events for any of the objects we support, you can limit your events to just creation events (\*.post) or update events (\*.patch) or even deletes (\*.delete).  You can then further refine your webhooks by only listening to events that update certain fields:

```json
{
    "ifUpdates": ["currentValue"]
}
```

### Webhook Signature Verification

Because webhooks send potentially sensitive data to a server you specify, you should always implement webhook verification.  To get started - you need to use your Organization token (or a token with ORG\_ADMIN permission) to create a new webhook key:

```http
POST https://api.peoplelogic.dev/api/v1/webhook-key
Content-Type: application/json
Authorization: Bearer {{orgBearer}}

{
  "name": "demo key"
}
```

If this succeeds, you'll get a 201 response code indicating that your first webhook key has been successfully created.  &#x20;

**Sample response**:

```json
{
  "id": "f6a1c9b2-0000-1111-2222-aaaaaaaaaaaa",
  "name": "demo key",
  "secretBase64": "YWJjMTIzIT8kKiYoKSctPUB+",
  "default": true,
  "createdAt": "2025-05-28T14:21:00Z"
}
```

The first signing key that you create will be the default one used for all webhooks.  Keep that secret handy - you won't be able to retrieve it again!&#x20;

For more information on actually validating your calls with that key - be sure to check out our [tutorial on listening to Objective changes to send Slack notifications](https://docs.peoplelogic.dev/api/universal-talent-api/pages/ykdF8Ube9nYA8zqljrSf#id-4.-ktor-webhook-listener).

If you create more than one key, you can optionally specify which one to use in the calls below.

### Creating a new webhook

Now we can get to work creating a new webhook.  Let's make a webhook specifically to listen to all events on Objectives:

```http
POST https://api.peoplelogic.dev/api/v1/webhook
Authorization: Bearer {{orgBearer}}
Content-Type: application/json

{
  "name": "Objectives Hook",
  "url": "http://localhost:9000/7a069348-58f2-4c30-a262-66d2098e00f5",
  "eventType": "objective.*"
}
```

Again, you'll get a 201 response code indicating that the webhook was successfully created. &#x20;

```json
{
  "id": "a9b8c7d6-3333-4444-5555-bbbbbbbbbbbb",
  "eventType": "objective.*",
  "ifUpdates": [],
  "url": "http://localhost:9000/7a069348-58f2-4c30-a262-66d2098e00f5",
  "signingKey": "f6a1c9b2-0000-1111-2222-aaaaaaaaaaaa",
  "active": true,
  "createdAt": "2025-05-28T14:22:00Z"
}
```

Now just sit back and wait for the events to roll in as you use the APIs!


# Sync Frequency

While you can make calls to the Peoplelogic.dev APIs as often as you like (within [API limits of course](/api/api-rate-limits)!), the freshness of the data is dependent on when the most recent sync from the various integrations occurred. &#x20;

### Universal API Frequency

Sync frequency is the rate at which Peoplelogic.dev initiates requests to fetch data from third-parties. Actual time to complete a sync can vary depending on the third-party.

We take every effort to complete each sync and respect the rate limits of our partner integrations.  If a sync fails because of invalid credentials, the connection will be paused until you resolve the credential issue.

### Executing a manual sync

Depending on your subscription level, you can execute a manual sync of remote data.  This allows you to fetch the latest data from our partners without waiting for the next sync window.  The manual sync request may not be executed immediately as the request is pushed into a queue.  It will be executed in the order it is received.

### Merge.dev Frequency

The frequency at which HRIS information is pulled from a connected Merge.dev account depends on whether you're using our provided Merge account or if you have brought your own.  By default, the embedded Peoplelogic.dev Merge account syncs roughly every 24 hours.  Your own account may have different limits.&#x20;


# Directory

The Directory API gives you access to Organizations, Accounts, Employees and Groups. Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT.

## GET /api/v1/organization

> List organizations

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"Organization":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"alias":{"type":"string"},"owners":{"type":"array","items":{"type":"string","format":"uuid"}},"profile":{"$ref":"#/components/schemas/OrganizationProfile"},"apps":{"type":"array","items":{"$ref":"#/components/schemas/App"}},"keys":{"type":"array","items":{"$ref":"#/components/schemas/OrganizationKey"}},"preferences":{"$ref":"#/components/schemas/NamespacedPreferences"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","name","active","status","created","alias"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"OrganizationProfile":{"type":"object","properties":{"logoUrl":{"type":"string"},"timezone":{"type":"string"},"location":{"type":"string"},"countryCode":{"type":"string"},"companySize":{"type":"string"},"website":{"type":"string"},"mission":{"type":"string"}}},"App":{"type":"object","description":"An Application (integration) record.","properties":{"id":{"type":"string","format":"uuid"},"externalId":{"type":"string"},"internal":{"type":"boolean"},"name":{"type":"string"},"type":{"type":"string"},"active":{"type":"boolean"},"status":{"type":"object","properties":{"current":{"type":"string","enum":["ACTIVE","INACTIVE","DRAFT","COMPLETED","CANCELED","TEST","ARCHIVED","TO_BE_DELETED"]},"changedAt":{"type":"string","format":"date-time","nullable":true},"changedBy":{"type":"string","format":"uuid","nullable":true}}},"created":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid","nullable":true}}},"organization":{"type":"string","format":"uuid"},"secretData":{"type":"object","additionalProperties":{"type":"string"}},"appData":{"type":"object","additionalProperties":{"type":"string"}}},"required":["type"]},"OrganizationKey":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"secretBase64":{"type":"string"},"limitToRole":{"type":"string"}},"required":["id","name","secretBase64","limitToRole"]},"NamespacedPreferences":{"type":"object","properties":{"namespace":{"type":"string"},"values":{"type":"object","additionalProperties":{"type":"string"}}},"required":["namespace","values"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]}}},"paths":{"/api/v1/organization":{"get":{"tags":["Directory"],"summary":"List organizations","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Organization"}}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## POST /api/v1/organization

> Create organization

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"OrganizationRequest":{"type":"object","properties":{"name":{"type":"string"},"alias":{"type":"string"},"ownerEmail":{"type":"string"}},"required":["name"]},"Organization":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"alias":{"type":"string"},"owners":{"type":"array","items":{"type":"string","format":"uuid"}},"profile":{"$ref":"#/components/schemas/OrganizationProfile"},"apps":{"type":"array","items":{"$ref":"#/components/schemas/App"}},"keys":{"type":"array","items":{"$ref":"#/components/schemas/OrganizationKey"}},"preferences":{"$ref":"#/components/schemas/NamespacedPreferences"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","name","active","status","created","alias"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"OrganizationProfile":{"type":"object","properties":{"logoUrl":{"type":"string"},"timezone":{"type":"string"},"location":{"type":"string"},"countryCode":{"type":"string"},"companySize":{"type":"string"},"website":{"type":"string"},"mission":{"type":"string"}}},"App":{"type":"object","description":"An Application (integration) record.","properties":{"id":{"type":"string","format":"uuid"},"externalId":{"type":"string"},"internal":{"type":"boolean"},"name":{"type":"string"},"type":{"type":"string"},"active":{"type":"boolean"},"status":{"type":"object","properties":{"current":{"type":"string","enum":["ACTIVE","INACTIVE","DRAFT","COMPLETED","CANCELED","TEST","ARCHIVED","TO_BE_DELETED"]},"changedAt":{"type":"string","format":"date-time","nullable":true},"changedBy":{"type":"string","format":"uuid","nullable":true}}},"created":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid","nullable":true}}},"organization":{"type":"string","format":"uuid"},"secretData":{"type":"object","additionalProperties":{"type":"string"}},"appData":{"type":"object","additionalProperties":{"type":"string"}}},"required":["type"]},"OrganizationKey":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"secretBase64":{"type":"string"},"limitToRole":{"type":"string"}},"required":["id","name","secretBase64","limitToRole"]},"NamespacedPreferences":{"type":"object","properties":{"namespace":{"type":"string"},"values":{"type":"object","additionalProperties":{"type":"string"}}},"required":["namespace","values"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]}}},"paths":{"/api/v1/organization":{"post":{"tags":["Directory"],"summary":"Create organization","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrganizationRequest"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Organization"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## PATCH /api/v1/organization

> Update current organization

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"OrganizationRequest":{"type":"object","properties":{"name":{"type":"string"},"alias":{"type":"string"},"ownerEmail":{"type":"string"}},"required":["name"]},"Organization":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"alias":{"type":"string"},"owners":{"type":"array","items":{"type":"string","format":"uuid"}},"profile":{"$ref":"#/components/schemas/OrganizationProfile"},"apps":{"type":"array","items":{"$ref":"#/components/schemas/App"}},"keys":{"type":"array","items":{"$ref":"#/components/schemas/OrganizationKey"}},"preferences":{"$ref":"#/components/schemas/NamespacedPreferences"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","name","active","status","created","alias"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"OrganizationProfile":{"type":"object","properties":{"logoUrl":{"type":"string"},"timezone":{"type":"string"},"location":{"type":"string"},"countryCode":{"type":"string"},"companySize":{"type":"string"},"website":{"type":"string"},"mission":{"type":"string"}}},"App":{"type":"object","description":"An Application (integration) record.","properties":{"id":{"type":"string","format":"uuid"},"externalId":{"type":"string"},"internal":{"type":"boolean"},"name":{"type":"string"},"type":{"type":"string"},"active":{"type":"boolean"},"status":{"type":"object","properties":{"current":{"type":"string","enum":["ACTIVE","INACTIVE","DRAFT","COMPLETED","CANCELED","TEST","ARCHIVED","TO_BE_DELETED"]},"changedAt":{"type":"string","format":"date-time","nullable":true},"changedBy":{"type":"string","format":"uuid","nullable":true}}},"created":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid","nullable":true}}},"organization":{"type":"string","format":"uuid"},"secretData":{"type":"object","additionalProperties":{"type":"string"}},"appData":{"type":"object","additionalProperties":{"type":"string"}}},"required":["type"]},"OrganizationKey":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"secretBase64":{"type":"string"},"limitToRole":{"type":"string"}},"required":["id","name","secretBase64","limitToRole"]},"NamespacedPreferences":{"type":"object","properties":{"namespace":{"type":"string"},"values":{"type":"object","additionalProperties":{"type":"string"}}},"required":["namespace","values"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]}}},"paths":{"/api/v1/organization":{"patch":{"tags":["Directory"],"summary":"Update current organization","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrganizationRequest"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Organization"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## GET /api/v1/organization/{organization}

> Get organization by ID

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"Organization":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"alias":{"type":"string"},"owners":{"type":"array","items":{"type":"string","format":"uuid"}},"profile":{"$ref":"#/components/schemas/OrganizationProfile"},"apps":{"type":"array","items":{"$ref":"#/components/schemas/App"}},"keys":{"type":"array","items":{"$ref":"#/components/schemas/OrganizationKey"}},"preferences":{"$ref":"#/components/schemas/NamespacedPreferences"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","name","active","status","created","alias"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"OrganizationProfile":{"type":"object","properties":{"logoUrl":{"type":"string"},"timezone":{"type":"string"},"location":{"type":"string"},"countryCode":{"type":"string"},"companySize":{"type":"string"},"website":{"type":"string"},"mission":{"type":"string"}}},"App":{"type":"object","description":"An Application (integration) record.","properties":{"id":{"type":"string","format":"uuid"},"externalId":{"type":"string"},"internal":{"type":"boolean"},"name":{"type":"string"},"type":{"type":"string"},"active":{"type":"boolean"},"status":{"type":"object","properties":{"current":{"type":"string","enum":["ACTIVE","INACTIVE","DRAFT","COMPLETED","CANCELED","TEST","ARCHIVED","TO_BE_DELETED"]},"changedAt":{"type":"string","format":"date-time","nullable":true},"changedBy":{"type":"string","format":"uuid","nullable":true}}},"created":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid","nullable":true}}},"organization":{"type":"string","format":"uuid"},"secretData":{"type":"object","additionalProperties":{"type":"string"}},"appData":{"type":"object","additionalProperties":{"type":"string"}}},"required":["type"]},"OrganizationKey":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"secretBase64":{"type":"string"},"limitToRole":{"type":"string"}},"required":["id","name","secretBase64","limitToRole"]},"NamespacedPreferences":{"type":"object","properties":{"namespace":{"type":"string"},"values":{"type":"object","additionalProperties":{"type":"string"}}},"required":["namespace","values"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]}}},"paths":{"/api/v1/organization/{organization}":{"get":{"tags":["Directory"],"summary":"Get organization by ID","parameters":[{"name":"organization","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Organization"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## PATCH /api/v1/organization/{organization}

> Update organization by ID

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"OrganizationRequest":{"type":"object","properties":{"name":{"type":"string"},"alias":{"type":"string"},"ownerEmail":{"type":"string"}},"required":["name"]},"Organization":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"alias":{"type":"string"},"owners":{"type":"array","items":{"type":"string","format":"uuid"}},"profile":{"$ref":"#/components/schemas/OrganizationProfile"},"apps":{"type":"array","items":{"$ref":"#/components/schemas/App"}},"keys":{"type":"array","items":{"$ref":"#/components/schemas/OrganizationKey"}},"preferences":{"$ref":"#/components/schemas/NamespacedPreferences"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","name","active","status","created","alias"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"OrganizationProfile":{"type":"object","properties":{"logoUrl":{"type":"string"},"timezone":{"type":"string"},"location":{"type":"string"},"countryCode":{"type":"string"},"companySize":{"type":"string"},"website":{"type":"string"},"mission":{"type":"string"}}},"App":{"type":"object","description":"An Application (integration) record.","properties":{"id":{"type":"string","format":"uuid"},"externalId":{"type":"string"},"internal":{"type":"boolean"},"name":{"type":"string"},"type":{"type":"string"},"active":{"type":"boolean"},"status":{"type":"object","properties":{"current":{"type":"string","enum":["ACTIVE","INACTIVE","DRAFT","COMPLETED","CANCELED","TEST","ARCHIVED","TO_BE_DELETED"]},"changedAt":{"type":"string","format":"date-time","nullable":true},"changedBy":{"type":"string","format":"uuid","nullable":true}}},"created":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid","nullable":true}}},"organization":{"type":"string","format":"uuid"},"secretData":{"type":"object","additionalProperties":{"type":"string"}},"appData":{"type":"object","additionalProperties":{"type":"string"}}},"required":["type"]},"OrganizationKey":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"secretBase64":{"type":"string"},"limitToRole":{"type":"string"}},"required":["id","name","secretBase64","limitToRole"]},"NamespacedPreferences":{"type":"object","properties":{"namespace":{"type":"string"},"values":{"type":"object","additionalProperties":{"type":"string"}}},"required":["namespace","values"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]}}},"paths":{"/api/v1/organization/{organization}":{"patch":{"tags":["Directory"],"summary":"Update organization by ID","parameters":[{"name":"organization","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrganizationRequest"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Organization"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## GET /api/v1/organization/profile

> Get organization profile

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"OrganizationProfile":{"type":"object","properties":{"logoUrl":{"type":"string"},"timezone":{"type":"string"},"location":{"type":"string"},"countryCode":{"type":"string"},"companySize":{"type":"string"},"website":{"type":"string"},"mission":{"type":"string"}}}}},"paths":{"/api/v1/organization/profile":{"get":{"tags":["Directory"],"summary":"Get organization profile","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrganizationProfile"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## POST /api/v1/organization/profile

> Create or replace organization profile

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"OrganizationProfile":{"type":"object","properties":{"logoUrl":{"type":"string"},"timezone":{"type":"string"},"location":{"type":"string"},"countryCode":{"type":"string"},"companySize":{"type":"string"},"website":{"type":"string"},"mission":{"type":"string"}}},"Organization":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"alias":{"type":"string"},"owners":{"type":"array","items":{"type":"string","format":"uuid"}},"profile":{"$ref":"#/components/schemas/OrganizationProfile"},"apps":{"type":"array","items":{"$ref":"#/components/schemas/App"}},"keys":{"type":"array","items":{"$ref":"#/components/schemas/OrganizationKey"}},"preferences":{"$ref":"#/components/schemas/NamespacedPreferences"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","name","active","status","created","alias"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"App":{"type":"object","description":"An Application (integration) record.","properties":{"id":{"type":"string","format":"uuid"},"externalId":{"type":"string"},"internal":{"type":"boolean"},"name":{"type":"string"},"type":{"type":"string"},"active":{"type":"boolean"},"status":{"type":"object","properties":{"current":{"type":"string","enum":["ACTIVE","INACTIVE","DRAFT","COMPLETED","CANCELED","TEST","ARCHIVED","TO_BE_DELETED"]},"changedAt":{"type":"string","format":"date-time","nullable":true},"changedBy":{"type":"string","format":"uuid","nullable":true}}},"created":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid","nullable":true}}},"organization":{"type":"string","format":"uuid"},"secretData":{"type":"object","additionalProperties":{"type":"string"}},"appData":{"type":"object","additionalProperties":{"type":"string"}}},"required":["type"]},"OrganizationKey":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"secretBase64":{"type":"string"},"limitToRole":{"type":"string"}},"required":["id","name","secretBase64","limitToRole"]},"NamespacedPreferences":{"type":"object","properties":{"namespace":{"type":"string"},"values":{"type":"object","additionalProperties":{"type":"string"}}},"required":["namespace","values"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]}}},"paths":{"/api/v1/organization/profile":{"post":{"tags":["Directory"],"summary":"Create or replace organization profile","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrganizationProfile"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Organization"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## PATCH /api/v1/organization/profile

> Update organization profile

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"OrganizationProfile":{"type":"object","properties":{"logoUrl":{"type":"string"},"timezone":{"type":"string"},"location":{"type":"string"},"countryCode":{"type":"string"},"companySize":{"type":"string"},"website":{"type":"string"},"mission":{"type":"string"}}},"Organization":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"alias":{"type":"string"},"owners":{"type":"array","items":{"type":"string","format":"uuid"}},"profile":{"$ref":"#/components/schemas/OrganizationProfile"},"apps":{"type":"array","items":{"$ref":"#/components/schemas/App"}},"keys":{"type":"array","items":{"$ref":"#/components/schemas/OrganizationKey"}},"preferences":{"$ref":"#/components/schemas/NamespacedPreferences"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","name","active","status","created","alias"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"App":{"type":"object","description":"An Application (integration) record.","properties":{"id":{"type":"string","format":"uuid"},"externalId":{"type":"string"},"internal":{"type":"boolean"},"name":{"type":"string"},"type":{"type":"string"},"active":{"type":"boolean"},"status":{"type":"object","properties":{"current":{"type":"string","enum":["ACTIVE","INACTIVE","DRAFT","COMPLETED","CANCELED","TEST","ARCHIVED","TO_BE_DELETED"]},"changedAt":{"type":"string","format":"date-time","nullable":true},"changedBy":{"type":"string","format":"uuid","nullable":true}}},"created":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid","nullable":true}}},"organization":{"type":"string","format":"uuid"},"secretData":{"type":"object","additionalProperties":{"type":"string"}},"appData":{"type":"object","additionalProperties":{"type":"string"}}},"required":["type"]},"OrganizationKey":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"secretBase64":{"type":"string"},"limitToRole":{"type":"string"}},"required":["id","name","secretBase64","limitToRole"]},"NamespacedPreferences":{"type":"object","properties":{"namespace":{"type":"string"},"values":{"type":"object","additionalProperties":{"type":"string"}}},"required":["namespace","values"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]}}},"paths":{"/api/v1/organization/profile":{"patch":{"tags":["Directory"],"summary":"Update organization profile","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrganizationProfile"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Organization"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## GET /api/v1/organization/{organization}/profile

> Get organization profile by ID

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"OrganizationProfile":{"type":"object","properties":{"logoUrl":{"type":"string"},"timezone":{"type":"string"},"location":{"type":"string"},"countryCode":{"type":"string"},"companySize":{"type":"string"},"website":{"type":"string"},"mission":{"type":"string"}}}}},"paths":{"/api/v1/organization/{organization}/profile":{"get":{"tags":["Directory"],"summary":"Get organization profile by ID","parameters":[{"name":"organization","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrganizationProfile"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## POST /api/v1/organization/{organization}/profile

> Create or replace profile for organization

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"OrganizationProfile":{"type":"object","properties":{"logoUrl":{"type":"string"},"timezone":{"type":"string"},"location":{"type":"string"},"countryCode":{"type":"string"},"companySize":{"type":"string"},"website":{"type":"string"},"mission":{"type":"string"}}},"Organization":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"alias":{"type":"string"},"owners":{"type":"array","items":{"type":"string","format":"uuid"}},"profile":{"$ref":"#/components/schemas/OrganizationProfile"},"apps":{"type":"array","items":{"$ref":"#/components/schemas/App"}},"keys":{"type":"array","items":{"$ref":"#/components/schemas/OrganizationKey"}},"preferences":{"$ref":"#/components/schemas/NamespacedPreferences"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","name","active","status","created","alias"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"App":{"type":"object","description":"An Application (integration) record.","properties":{"id":{"type":"string","format":"uuid"},"externalId":{"type":"string"},"internal":{"type":"boolean"},"name":{"type":"string"},"type":{"type":"string"},"active":{"type":"boolean"},"status":{"type":"object","properties":{"current":{"type":"string","enum":["ACTIVE","INACTIVE","DRAFT","COMPLETED","CANCELED","TEST","ARCHIVED","TO_BE_DELETED"]},"changedAt":{"type":"string","format":"date-time","nullable":true},"changedBy":{"type":"string","format":"uuid","nullable":true}}},"created":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid","nullable":true}}},"organization":{"type":"string","format":"uuid"},"secretData":{"type":"object","additionalProperties":{"type":"string"}},"appData":{"type":"object","additionalProperties":{"type":"string"}}},"required":["type"]},"OrganizationKey":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"secretBase64":{"type":"string"},"limitToRole":{"type":"string"}},"required":["id","name","secretBase64","limitToRole"]},"NamespacedPreferences":{"type":"object","properties":{"namespace":{"type":"string"},"values":{"type":"object","additionalProperties":{"type":"string"}}},"required":["namespace","values"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]}}},"paths":{"/api/v1/organization/{organization}/profile":{"post":{"tags":["Directory"],"summary":"Create or replace profile for organization","parameters":[{"name":"organization","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrganizationProfile"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Organization"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## PATCH /api/v1/organization/{organization}/profile

> Update profile for organization

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"OrganizationProfile":{"type":"object","properties":{"logoUrl":{"type":"string"},"timezone":{"type":"string"},"location":{"type":"string"},"countryCode":{"type":"string"},"companySize":{"type":"string"},"website":{"type":"string"},"mission":{"type":"string"}}},"Organization":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"alias":{"type":"string"},"owners":{"type":"array","items":{"type":"string","format":"uuid"}},"profile":{"$ref":"#/components/schemas/OrganizationProfile"},"apps":{"type":"array","items":{"$ref":"#/components/schemas/App"}},"keys":{"type":"array","items":{"$ref":"#/components/schemas/OrganizationKey"}},"preferences":{"$ref":"#/components/schemas/NamespacedPreferences"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","name","active","status","created","alias"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"App":{"type":"object","description":"An Application (integration) record.","properties":{"id":{"type":"string","format":"uuid"},"externalId":{"type":"string"},"internal":{"type":"boolean"},"name":{"type":"string"},"type":{"type":"string"},"active":{"type":"boolean"},"status":{"type":"object","properties":{"current":{"type":"string","enum":["ACTIVE","INACTIVE","DRAFT","COMPLETED","CANCELED","TEST","ARCHIVED","TO_BE_DELETED"]},"changedAt":{"type":"string","format":"date-time","nullable":true},"changedBy":{"type":"string","format":"uuid","nullable":true}}},"created":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid","nullable":true}}},"organization":{"type":"string","format":"uuid"},"secretData":{"type":"object","additionalProperties":{"type":"string"}},"appData":{"type":"object","additionalProperties":{"type":"string"}}},"required":["type"]},"OrganizationKey":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"secretBase64":{"type":"string"},"limitToRole":{"type":"string"}},"required":["id","name","secretBase64","limitToRole"]},"NamespacedPreferences":{"type":"object","properties":{"namespace":{"type":"string"},"values":{"type":"object","additionalProperties":{"type":"string"}}},"required":["namespace","values"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]}}},"paths":{"/api/v1/organization/{organization}/profile":{"patch":{"tags":["Directory"],"summary":"Update profile for organization","parameters":[{"name":"organization","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrganizationProfile"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Organization"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## GET /api/v1/organization/alias/{alias}

> Get organization by alias

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"Organization":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"alias":{"type":"string"},"owners":{"type":"array","items":{"type":"string","format":"uuid"}},"profile":{"$ref":"#/components/schemas/OrganizationProfile"},"apps":{"type":"array","items":{"$ref":"#/components/schemas/App"}},"keys":{"type":"array","items":{"$ref":"#/components/schemas/OrganizationKey"}},"preferences":{"$ref":"#/components/schemas/NamespacedPreferences"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","name","active","status","created","alias"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"OrganizationProfile":{"type":"object","properties":{"logoUrl":{"type":"string"},"timezone":{"type":"string"},"location":{"type":"string"},"countryCode":{"type":"string"},"companySize":{"type":"string"},"website":{"type":"string"},"mission":{"type":"string"}}},"App":{"type":"object","description":"An Application (integration) record.","properties":{"id":{"type":"string","format":"uuid"},"externalId":{"type":"string"},"internal":{"type":"boolean"},"name":{"type":"string"},"type":{"type":"string"},"active":{"type":"boolean"},"status":{"type":"object","properties":{"current":{"type":"string","enum":["ACTIVE","INACTIVE","DRAFT","COMPLETED","CANCELED","TEST","ARCHIVED","TO_BE_DELETED"]},"changedAt":{"type":"string","format":"date-time","nullable":true},"changedBy":{"type":"string","format":"uuid","nullable":true}}},"created":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid","nullable":true}}},"organization":{"type":"string","format":"uuid"},"secretData":{"type":"object","additionalProperties":{"type":"string"}},"appData":{"type":"object","additionalProperties":{"type":"string"}}},"required":["type"]},"OrganizationKey":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"secretBase64":{"type":"string"},"limitToRole":{"type":"string"}},"required":["id","name","secretBase64","limitToRole"]},"NamespacedPreferences":{"type":"object","properties":{"namespace":{"type":"string"},"values":{"type":"object","additionalProperties":{"type":"string"}}},"required":["namespace","values"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]}}},"paths":{"/api/v1/organization/alias/{alias}":{"get":{"tags":["Directory"],"summary":"Get organization by alias","parameters":[{"name":"alias","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Organization"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## GET /api/v1/organization/by-app/{type}

> List organizations by app type

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"Organization":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"alias":{"type":"string"},"owners":{"type":"array","items":{"type":"string","format":"uuid"}},"profile":{"$ref":"#/components/schemas/OrganizationProfile"},"apps":{"type":"array","items":{"$ref":"#/components/schemas/App"}},"keys":{"type":"array","items":{"$ref":"#/components/schemas/OrganizationKey"}},"preferences":{"$ref":"#/components/schemas/NamespacedPreferences"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","name","active","status","created","alias"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"OrganizationProfile":{"type":"object","properties":{"logoUrl":{"type":"string"},"timezone":{"type":"string"},"location":{"type":"string"},"countryCode":{"type":"string"},"companySize":{"type":"string"},"website":{"type":"string"},"mission":{"type":"string"}}},"App":{"type":"object","description":"An Application (integration) record.","properties":{"id":{"type":"string","format":"uuid"},"externalId":{"type":"string"},"internal":{"type":"boolean"},"name":{"type":"string"},"type":{"type":"string"},"active":{"type":"boolean"},"status":{"type":"object","properties":{"current":{"type":"string","enum":["ACTIVE","INACTIVE","DRAFT","COMPLETED","CANCELED","TEST","ARCHIVED","TO_BE_DELETED"]},"changedAt":{"type":"string","format":"date-time","nullable":true},"changedBy":{"type":"string","format":"uuid","nullable":true}}},"created":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid","nullable":true}}},"organization":{"type":"string","format":"uuid"},"secretData":{"type":"object","additionalProperties":{"type":"string"}},"appData":{"type":"object","additionalProperties":{"type":"string"}}},"required":["type"]},"OrganizationKey":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"secretBase64":{"type":"string"},"limitToRole":{"type":"string"}},"required":["id","name","secretBase64","limitToRole"]},"NamespacedPreferences":{"type":"object","properties":{"namespace":{"type":"string"},"values":{"type":"object","additionalProperties":{"type":"string"}}},"required":["namespace","values"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]}}},"paths":{"/api/v1/organization/by-app/{type}":{"get":{"tags":["Directory"],"summary":"List organizations by app type","parameters":[{"name":"type","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Organization"}}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## GET /api/v1/organization/by-app-id/{type}/{externalId}

> List organizations by app external ID

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"Organization":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"alias":{"type":"string"},"owners":{"type":"array","items":{"type":"string","format":"uuid"}},"profile":{"$ref":"#/components/schemas/OrganizationProfile"},"apps":{"type":"array","items":{"$ref":"#/components/schemas/App"}},"keys":{"type":"array","items":{"$ref":"#/components/schemas/OrganizationKey"}},"preferences":{"$ref":"#/components/schemas/NamespacedPreferences"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","name","active","status","created","alias"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"OrganizationProfile":{"type":"object","properties":{"logoUrl":{"type":"string"},"timezone":{"type":"string"},"location":{"type":"string"},"countryCode":{"type":"string"},"companySize":{"type":"string"},"website":{"type":"string"},"mission":{"type":"string"}}},"App":{"type":"object","description":"An Application (integration) record.","properties":{"id":{"type":"string","format":"uuid"},"externalId":{"type":"string"},"internal":{"type":"boolean"},"name":{"type":"string"},"type":{"type":"string"},"active":{"type":"boolean"},"status":{"type":"object","properties":{"current":{"type":"string","enum":["ACTIVE","INACTIVE","DRAFT","COMPLETED","CANCELED","TEST","ARCHIVED","TO_BE_DELETED"]},"changedAt":{"type":"string","format":"date-time","nullable":true},"changedBy":{"type":"string","format":"uuid","nullable":true}}},"created":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid","nullable":true}}},"organization":{"type":"string","format":"uuid"},"secretData":{"type":"object","additionalProperties":{"type":"string"}},"appData":{"type":"object","additionalProperties":{"type":"string"}}},"required":["type"]},"OrganizationKey":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"secretBase64":{"type":"string"},"limitToRole":{"type":"string"}},"required":["id","name","secretBase64","limitToRole"]},"NamespacedPreferences":{"type":"object","properties":{"namespace":{"type":"string"},"values":{"type":"object","additionalProperties":{"type":"string"}}},"required":["namespace","values"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]}}},"paths":{"/api/v1/organization/by-app-id/{type}/{externalId}":{"get":{"tags":["Directory"],"summary":"List organizations by app external ID","parameters":[{"name":"type","in":"path","required":true,"schema":{"type":"string"}},{"name":"externalId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Organization"}}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## GET /api/v1/organization/by-app-data/{type}/{key}/{value}

> List organizations by app data

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"Organization":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"alias":{"type":"string"},"owners":{"type":"array","items":{"type":"string","format":"uuid"}},"profile":{"$ref":"#/components/schemas/OrganizationProfile"},"apps":{"type":"array","items":{"$ref":"#/components/schemas/App"}},"keys":{"type":"array","items":{"$ref":"#/components/schemas/OrganizationKey"}},"preferences":{"$ref":"#/components/schemas/NamespacedPreferences"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","name","active","status","created","alias"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"OrganizationProfile":{"type":"object","properties":{"logoUrl":{"type":"string"},"timezone":{"type":"string"},"location":{"type":"string"},"countryCode":{"type":"string"},"companySize":{"type":"string"},"website":{"type":"string"},"mission":{"type":"string"}}},"App":{"type":"object","description":"An Application (integration) record.","properties":{"id":{"type":"string","format":"uuid"},"externalId":{"type":"string"},"internal":{"type":"boolean"},"name":{"type":"string"},"type":{"type":"string"},"active":{"type":"boolean"},"status":{"type":"object","properties":{"current":{"type":"string","enum":["ACTIVE","INACTIVE","DRAFT","COMPLETED","CANCELED","TEST","ARCHIVED","TO_BE_DELETED"]},"changedAt":{"type":"string","format":"date-time","nullable":true},"changedBy":{"type":"string","format":"uuid","nullable":true}}},"created":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid","nullable":true}}},"organization":{"type":"string","format":"uuid"},"secretData":{"type":"object","additionalProperties":{"type":"string"}},"appData":{"type":"object","additionalProperties":{"type":"string"}}},"required":["type"]},"OrganizationKey":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"secretBase64":{"type":"string"},"limitToRole":{"type":"string"}},"required":["id","name","secretBase64","limitToRole"]},"NamespacedPreferences":{"type":"object","properties":{"namespace":{"type":"string"},"values":{"type":"object","additionalProperties":{"type":"string"}}},"required":["namespace","values"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]}}},"paths":{"/api/v1/organization/by-app-data/{type}/{key}/{value}":{"get":{"tags":["Directory"],"summary":"List organizations by app data","parameters":[{"name":"type","in":"path","required":true,"schema":{"type":"string"}},{"name":"key","in":"path","required":true,"schema":{"type":"string"}},{"name":"value","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Organization"}}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## POST /api/v1/organization/by-app-secret/{type}/{key}

> List organizations by app secret

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"ListBySecretRequest":{"type":"object","properties":{"secret":{"type":"string"}},"required":["secret"]},"Organization":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"alias":{"type":"string"},"owners":{"type":"array","items":{"type":"string","format":"uuid"}},"profile":{"$ref":"#/components/schemas/OrganizationProfile"},"apps":{"type":"array","items":{"$ref":"#/components/schemas/App"}},"keys":{"type":"array","items":{"$ref":"#/components/schemas/OrganizationKey"}},"preferences":{"$ref":"#/components/schemas/NamespacedPreferences"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","name","active","status","created","alias"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"OrganizationProfile":{"type":"object","properties":{"logoUrl":{"type":"string"},"timezone":{"type":"string"},"location":{"type":"string"},"countryCode":{"type":"string"},"companySize":{"type":"string"},"website":{"type":"string"},"mission":{"type":"string"}}},"App":{"type":"object","description":"An Application (integration) record.","properties":{"id":{"type":"string","format":"uuid"},"externalId":{"type":"string"},"internal":{"type":"boolean"},"name":{"type":"string"},"type":{"type":"string"},"active":{"type":"boolean"},"status":{"type":"object","properties":{"current":{"type":"string","enum":["ACTIVE","INACTIVE","DRAFT","COMPLETED","CANCELED","TEST","ARCHIVED","TO_BE_DELETED"]},"changedAt":{"type":"string","format":"date-time","nullable":true},"changedBy":{"type":"string","format":"uuid","nullable":true}}},"created":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid","nullable":true}}},"organization":{"type":"string","format":"uuid"},"secretData":{"type":"object","additionalProperties":{"type":"string"}},"appData":{"type":"object","additionalProperties":{"type":"string"}}},"required":["type"]},"OrganizationKey":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"secretBase64":{"type":"string"},"limitToRole":{"type":"string"}},"required":["id","name","secretBase64","limitToRole"]},"NamespacedPreferences":{"type":"object","properties":{"namespace":{"type":"string"},"values":{"type":"object","additionalProperties":{"type":"string"}}},"required":["namespace","values"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]}}},"paths":{"/api/v1/organization/by-app-secret/{type}/{key}":{"post":{"tags":["Directory"],"summary":"List organizations by app secret","parameters":[{"name":"type","in":"path","required":true,"schema":{"type":"string"}},{"name":"key","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListBySecretRequest"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Organization"}}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## POST /api/v1/organization/keys

> Create API key for organization

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"NewKeyRequest":{"type":"object","properties":{"name":{"type":"string"},"limitToRole":{"type":"string"}},"required":["name"]},"Organization":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"alias":{"type":"string"},"owners":{"type":"array","items":{"type":"string","format":"uuid"}},"profile":{"$ref":"#/components/schemas/OrganizationProfile"},"apps":{"type":"array","items":{"$ref":"#/components/schemas/App"}},"keys":{"type":"array","items":{"$ref":"#/components/schemas/OrganizationKey"}},"preferences":{"$ref":"#/components/schemas/NamespacedPreferences"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","name","active","status","created","alias"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"OrganizationProfile":{"type":"object","properties":{"logoUrl":{"type":"string"},"timezone":{"type":"string"},"location":{"type":"string"},"countryCode":{"type":"string"},"companySize":{"type":"string"},"website":{"type":"string"},"mission":{"type":"string"}}},"App":{"type":"object","description":"An Application (integration) record.","properties":{"id":{"type":"string","format":"uuid"},"externalId":{"type":"string"},"internal":{"type":"boolean"},"name":{"type":"string"},"type":{"type":"string"},"active":{"type":"boolean"},"status":{"type":"object","properties":{"current":{"type":"string","enum":["ACTIVE","INACTIVE","DRAFT","COMPLETED","CANCELED","TEST","ARCHIVED","TO_BE_DELETED"]},"changedAt":{"type":"string","format":"date-time","nullable":true},"changedBy":{"type":"string","format":"uuid","nullable":true}}},"created":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid","nullable":true}}},"organization":{"type":"string","format":"uuid"},"secretData":{"type":"object","additionalProperties":{"type":"string"}},"appData":{"type":"object","additionalProperties":{"type":"string"}}},"required":["type"]},"OrganizationKey":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"secretBase64":{"type":"string"},"limitToRole":{"type":"string"}},"required":["id","name","secretBase64","limitToRole"]},"NamespacedPreferences":{"type":"object","properties":{"namespace":{"type":"string"},"values":{"type":"object","additionalProperties":{"type":"string"}}},"required":["namespace","values"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]}}},"paths":{"/api/v1/organization/keys":{"post":{"tags":["Directory"],"summary":"Create API key for organization","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewKeyRequest"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Organization"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## POST /api/v1/organization/{organization}/keys

> Create API key for org by ID

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"NewKeyRequest":{"type":"object","properties":{"name":{"type":"string"},"limitToRole":{"type":"string"}},"required":["name"]},"Organization":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"alias":{"type":"string"},"owners":{"type":"array","items":{"type":"string","format":"uuid"}},"profile":{"$ref":"#/components/schemas/OrganizationProfile"},"apps":{"type":"array","items":{"$ref":"#/components/schemas/App"}},"keys":{"type":"array","items":{"$ref":"#/components/schemas/OrganizationKey"}},"preferences":{"$ref":"#/components/schemas/NamespacedPreferences"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","name","active","status","created","alias"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"OrganizationProfile":{"type":"object","properties":{"logoUrl":{"type":"string"},"timezone":{"type":"string"},"location":{"type":"string"},"countryCode":{"type":"string"},"companySize":{"type":"string"},"website":{"type":"string"},"mission":{"type":"string"}}},"App":{"type":"object","description":"An Application (integration) record.","properties":{"id":{"type":"string","format":"uuid"},"externalId":{"type":"string"},"internal":{"type":"boolean"},"name":{"type":"string"},"type":{"type":"string"},"active":{"type":"boolean"},"status":{"type":"object","properties":{"current":{"type":"string","enum":["ACTIVE","INACTIVE","DRAFT","COMPLETED","CANCELED","TEST","ARCHIVED","TO_BE_DELETED"]},"changedAt":{"type":"string","format":"date-time","nullable":true},"changedBy":{"type":"string","format":"uuid","nullable":true}}},"created":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid","nullable":true}}},"organization":{"type":"string","format":"uuid"},"secretData":{"type":"object","additionalProperties":{"type":"string"}},"appData":{"type":"object","additionalProperties":{"type":"string"}}},"required":["type"]},"OrganizationKey":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"secretBase64":{"type":"string"},"limitToRole":{"type":"string"}},"required":["id","name","secretBase64","limitToRole"]},"NamespacedPreferences":{"type":"object","properties":{"namespace":{"type":"string"},"values":{"type":"object","additionalProperties":{"type":"string"}}},"required":["namespace","values"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]}}},"paths":{"/api/v1/organization/{organization}/keys":{"post":{"tags":["Directory"],"summary":"Create API key for org by ID","parameters":[{"name":"organization","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewKeyRequest"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Organization"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## DELETE /api/v1/organization/keys/{key}

> Delete API key for current organization

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"Organization":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"alias":{"type":"string"},"owners":{"type":"array","items":{"type":"string","format":"uuid"}},"profile":{"$ref":"#/components/schemas/OrganizationProfile"},"apps":{"type":"array","items":{"$ref":"#/components/schemas/App"}},"keys":{"type":"array","items":{"$ref":"#/components/schemas/OrganizationKey"}},"preferences":{"$ref":"#/components/schemas/NamespacedPreferences"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","name","active","status","created","alias"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"OrganizationProfile":{"type":"object","properties":{"logoUrl":{"type":"string"},"timezone":{"type":"string"},"location":{"type":"string"},"countryCode":{"type":"string"},"companySize":{"type":"string"},"website":{"type":"string"},"mission":{"type":"string"}}},"App":{"type":"object","description":"An Application (integration) record.","properties":{"id":{"type":"string","format":"uuid"},"externalId":{"type":"string"},"internal":{"type":"boolean"},"name":{"type":"string"},"type":{"type":"string"},"active":{"type":"boolean"},"status":{"type":"object","properties":{"current":{"type":"string","enum":["ACTIVE","INACTIVE","DRAFT","COMPLETED","CANCELED","TEST","ARCHIVED","TO_BE_DELETED"]},"changedAt":{"type":"string","format":"date-time","nullable":true},"changedBy":{"type":"string","format":"uuid","nullable":true}}},"created":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid","nullable":true}}},"organization":{"type":"string","format":"uuid"},"secretData":{"type":"object","additionalProperties":{"type":"string"}},"appData":{"type":"object","additionalProperties":{"type":"string"}}},"required":["type"]},"OrganizationKey":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"secretBase64":{"type":"string"},"limitToRole":{"type":"string"}},"required":["id","name","secretBase64","limitToRole"]},"NamespacedPreferences":{"type":"object","properties":{"namespace":{"type":"string"},"values":{"type":"object","additionalProperties":{"type":"string"}}},"required":["namespace","values"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]}}},"paths":{"/api/v1/organization/keys/{key}":{"delete":{"tags":["Directory"],"summary":"Delete API key for current organization","parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Organization"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## DELETE /api/v1/organization/{organization}/keys/{key}

> Delete API key by org ID

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"Organization":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"alias":{"type":"string"},"owners":{"type":"array","items":{"type":"string","format":"uuid"}},"profile":{"$ref":"#/components/schemas/OrganizationProfile"},"apps":{"type":"array","items":{"$ref":"#/components/schemas/App"}},"keys":{"type":"array","items":{"$ref":"#/components/schemas/OrganizationKey"}},"preferences":{"$ref":"#/components/schemas/NamespacedPreferences"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","name","active","status","created","alias"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"OrganizationProfile":{"type":"object","properties":{"logoUrl":{"type":"string"},"timezone":{"type":"string"},"location":{"type":"string"},"countryCode":{"type":"string"},"companySize":{"type":"string"},"website":{"type":"string"},"mission":{"type":"string"}}},"App":{"type":"object","description":"An Application (integration) record.","properties":{"id":{"type":"string","format":"uuid"},"externalId":{"type":"string"},"internal":{"type":"boolean"},"name":{"type":"string"},"type":{"type":"string"},"active":{"type":"boolean"},"status":{"type":"object","properties":{"current":{"type":"string","enum":["ACTIVE","INACTIVE","DRAFT","COMPLETED","CANCELED","TEST","ARCHIVED","TO_BE_DELETED"]},"changedAt":{"type":"string","format":"date-time","nullable":true},"changedBy":{"type":"string","format":"uuid","nullable":true}}},"created":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid","nullable":true}}},"organization":{"type":"string","format":"uuid"},"secretData":{"type":"object","additionalProperties":{"type":"string"}},"appData":{"type":"object","additionalProperties":{"type":"string"}}},"required":["type"]},"OrganizationKey":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"secretBase64":{"type":"string"},"limitToRole":{"type":"string"}},"required":["id","name","secretBase64","limitToRole"]},"NamespacedPreferences":{"type":"object","properties":{"namespace":{"type":"string"},"values":{"type":"object","additionalProperties":{"type":"string"}}},"required":["namespace","values"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]}}},"paths":{"/api/v1/organization/{organization}/keys/{key}":{"delete":{"tags":["Directory"],"summary":"Delete API key by org ID","parameters":[{"name":"organization","in":"path","required":true,"schema":{"type":"string"}},{"name":"key","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Organization"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## GET /api/v1/account

> List accounts

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"Account":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}},"preferences":{"$ref":"#/components/schemas/NamespacedPreferences"},"grants":{"type":"array","items":{"$ref":"#/components/schemas/AccountGrant"}}},"required":["id","email","name","active","status","created"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]},"NamespacedPreferences":{"type":"object","properties":{"namespace":{"type":"string"},"values":{"type":"object","additionalProperties":{"type":"string"}}},"required":["namespace","values"]},"AccountGrant":{"type":"object","properties":{"orgId":{"type":"string","format":"uuid"},"role":{"type":"string"},"employeeId":{"type":"string","format":"uuid"}},"required":["role"]}}},"paths":{"/api/v1/account":{"get":{"tags":["Directory"],"summary":"List accounts","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Account"}}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## POST /api/v1/account

> Create account

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"AccountRequest":{"type":"object","properties":{"name":{"type":"string"},"email":{"type":"string"}},"required":["email"]},"Account":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}},"preferences":{"$ref":"#/components/schemas/NamespacedPreferences"},"grants":{"type":"array","items":{"$ref":"#/components/schemas/AccountGrant"}}},"required":["id","email","name","active","status","created"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]},"NamespacedPreferences":{"type":"object","properties":{"namespace":{"type":"string"},"values":{"type":"object","additionalProperties":{"type":"string"}}},"required":["namespace","values"]},"AccountGrant":{"type":"object","properties":{"orgId":{"type":"string","format":"uuid"},"role":{"type":"string"},"employeeId":{"type":"string","format":"uuid"}},"required":["role"]}}},"paths":{"/api/v1/account":{"post":{"tags":["Directory"],"summary":"Create account","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountRequest"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Account"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## GET /api/v1/account/{accountIdOrEmail}

> Get account by ID or email

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"Account":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}},"preferences":{"$ref":"#/components/schemas/NamespacedPreferences"},"grants":{"type":"array","items":{"$ref":"#/components/schemas/AccountGrant"}}},"required":["id","email","name","active","status","created"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]},"NamespacedPreferences":{"type":"object","properties":{"namespace":{"type":"string"},"values":{"type":"object","additionalProperties":{"type":"string"}}},"required":["namespace","values"]},"AccountGrant":{"type":"object","properties":{"orgId":{"type":"string","format":"uuid"},"role":{"type":"string"},"employeeId":{"type":"string","format":"uuid"}},"required":["role"]}}},"paths":{"/api/v1/account/{accountIdOrEmail}":{"get":{"tags":["Directory"],"summary":"Get account by ID or email","parameters":[{"name":"accountIdOrEmail","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Account"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## PATCH /api/v1/account/{accountIdOrEmail}

> Update account

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"AccountRequest":{"type":"object","properties":{"name":{"type":"string"},"email":{"type":"string"}},"required":["email"]},"Account":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}},"preferences":{"$ref":"#/components/schemas/NamespacedPreferences"},"grants":{"type":"array","items":{"$ref":"#/components/schemas/AccountGrant"}}},"required":["id","email","name","active","status","created"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]},"NamespacedPreferences":{"type":"object","properties":{"namespace":{"type":"string"},"values":{"type":"object","additionalProperties":{"type":"string"}}},"required":["namespace","values"]},"AccountGrant":{"type":"object","properties":{"orgId":{"type":"string","format":"uuid"},"role":{"type":"string"},"employeeId":{"type":"string","format":"uuid"}},"required":["role"]}}},"paths":{"/api/v1/account/{accountIdOrEmail}":{"patch":{"tags":["Directory"],"summary":"Update account","parameters":[{"name":"accountIdOrEmail","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountRequest"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Account"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## POST /api/v1/account/{accountId}/grant

> Grant account a role

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"AccountGrant":{"type":"object","properties":{"orgId":{"type":"string","format":"uuid"},"role":{"type":"string"},"employeeId":{"type":"string","format":"uuid"}},"required":["role"]},"Account":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}},"preferences":{"$ref":"#/components/schemas/NamespacedPreferences"},"grants":{"type":"array","items":{"$ref":"#/components/schemas/AccountGrant"}}},"required":["id","email","name","active","status","created"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]},"NamespacedPreferences":{"type":"object","properties":{"namespace":{"type":"string"},"values":{"type":"object","additionalProperties":{"type":"string"}}},"required":["namespace","values"]}}},"paths":{"/api/v1/account/{accountId}/grant":{"post":{"tags":["Directory"],"summary":"Grant account a role","parameters":[{"name":"accountId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountGrant"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Account"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## GET /api/v1/account/org-admins

> List organization admins

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"Account":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}},"preferences":{"$ref":"#/components/schemas/NamespacedPreferences"},"grants":{"type":"array","items":{"$ref":"#/components/schemas/AccountGrant"}}},"required":["id","email","name","active","status","created"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]},"NamespacedPreferences":{"type":"object","properties":{"namespace":{"type":"string"},"values":{"type":"object","additionalProperties":{"type":"string"}}},"required":["namespace","values"]},"AccountGrant":{"type":"object","properties":{"orgId":{"type":"string","format":"uuid"},"role":{"type":"string"},"employeeId":{"type":"string","format":"uuid"}},"required":["role"]}}},"paths":{"/api/v1/account/org-admins":{"get":{"tags":["Directory"],"summary":"List organization admins","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Account"}}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## GET /api/v1/account/{accountId}/employees

> List employees for account

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"Employee":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"organization":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"emails":{"type":"array","items":{"$ref":"#/components/schemas/EmployeeEmail"}},"groups":{"type":"array","items":{"$ref":"#/components/schemas/EntityGroupMembership"}},"managers":{"type":"array","items":{"$ref":"#/components/schemas/EmployeeManager"}},"profile":{"$ref":"#/components/schemas/EmployeeProfile"},"account":{"type":"string","format":"uuid"},"authentication":{"$ref":"#/components/schemas/EmployeeAccount"},"preferences":{"$ref":"#/components/schemas/NamespacedPreferences"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","organization","name","active","status","created"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EmployeeEmail":{"type":"object","properties":{"email":{"type":"string"},"primary":{"type":"boolean"}},"required":["email","primary"]},"EntityGroupMembership":{"type":"object","properties":{"entityType":{"type":"string"},"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"}},"required":["entityType","entityId","type"]},"EmployeeManager":{"type":"object","properties":{"managerId":{"type":"string","format":"uuid"},"type":{"type":"string"},"since":{"type":"string","format":"date-time"}},"required":["managerId","type","since"]},"EmployeeProfile":{"type":"object","properties":{"employeeNumber":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"bio":{"type":"string"},"profileImage":{"type":"string"},"birthDate":{"type":"string","format":"date"},"gender":{"type":"string"},"timezone":{"type":"string"},"location":{"type":"string"},"joinDate":{"type":"string","format":"date"},"companyRole":{"type":"string"}}},"EmployeeAccount":{"type":"object","properties":{"account":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"},"email":{"type":"string"},"role":{"type":"string"}},"required":["account","createdAt","email","role"]},"NamespacedPreferences":{"type":"object","properties":{"namespace":{"type":"string"},"values":{"type":"object","additionalProperties":{"type":"string"}}},"required":["namespace","values"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]}}},"paths":{"/api/v1/account/{accountId}/employees":{"get":{"tags":["Directory"],"summary":"List employees for account","parameters":[{"name":"accountId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Employee"}}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## GET /api/v1/account/for-org

> List accounts for organization

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"Account":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}},"preferences":{"$ref":"#/components/schemas/NamespacedPreferences"},"grants":{"type":"array","items":{"$ref":"#/components/schemas/AccountGrant"}}},"required":["id","email","name","active","status","created"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]},"NamespacedPreferences":{"type":"object","properties":{"namespace":{"type":"string"},"values":{"type":"object","additionalProperties":{"type":"string"}}},"required":["namespace","values"]},"AccountGrant":{"type":"object","properties":{"orgId":{"type":"string","format":"uuid"},"role":{"type":"string"},"employeeId":{"type":"string","format":"uuid"}},"required":["role"]}}},"paths":{"/api/v1/account/for-org":{"get":{"tags":["Directory"],"summary":"List accounts for organization","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Account"}}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## GET /api/v1/employee

> List employees

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"Employee":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"organization":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"emails":{"type":"array","items":{"$ref":"#/components/schemas/EmployeeEmail"}},"groups":{"type":"array","items":{"$ref":"#/components/schemas/EntityGroupMembership"}},"managers":{"type":"array","items":{"$ref":"#/components/schemas/EmployeeManager"}},"profile":{"$ref":"#/components/schemas/EmployeeProfile"},"account":{"type":"string","format":"uuid"},"authentication":{"$ref":"#/components/schemas/EmployeeAccount"},"preferences":{"$ref":"#/components/schemas/NamespacedPreferences"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","organization","name","active","status","created"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EmployeeEmail":{"type":"object","properties":{"email":{"type":"string"},"primary":{"type":"boolean"}},"required":["email","primary"]},"EntityGroupMembership":{"type":"object","properties":{"entityType":{"type":"string"},"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"}},"required":["entityType","entityId","type"]},"EmployeeManager":{"type":"object","properties":{"managerId":{"type":"string","format":"uuid"},"type":{"type":"string"},"since":{"type":"string","format":"date-time"}},"required":["managerId","type","since"]},"EmployeeProfile":{"type":"object","properties":{"employeeNumber":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"bio":{"type":"string"},"profileImage":{"type":"string"},"birthDate":{"type":"string","format":"date"},"gender":{"type":"string"},"timezone":{"type":"string"},"location":{"type":"string"},"joinDate":{"type":"string","format":"date"},"companyRole":{"type":"string"}}},"EmployeeAccount":{"type":"object","properties":{"account":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"},"email":{"type":"string"},"role":{"type":"string"}},"required":["account","createdAt","email","role"]},"NamespacedPreferences":{"type":"object","properties":{"namespace":{"type":"string"},"values":{"type":"object","additionalProperties":{"type":"string"}}},"required":["namespace","values"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]}}},"paths":{"/api/v1/employee":{"get":{"tags":["Directory"],"summary":"List employees","parameters":[{"name":"status","in":"query","schema":{"type":"string"}},{"name":"type","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Employee"}}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## POST /api/v1/employee

> Create employee

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"EmployeeRequest":{"type":"object","properties":{"name":{"type":"string"},"email":{"type":"string"},"account":{"type":"string","format":"uuid"},"role":{"type":"string"}},"required":["name","email"]},"Employee":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"organization":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"emails":{"type":"array","items":{"$ref":"#/components/schemas/EmployeeEmail"}},"groups":{"type":"array","items":{"$ref":"#/components/schemas/EntityGroupMembership"}},"managers":{"type":"array","items":{"$ref":"#/components/schemas/EmployeeManager"}},"profile":{"$ref":"#/components/schemas/EmployeeProfile"},"account":{"type":"string","format":"uuid"},"authentication":{"$ref":"#/components/schemas/EmployeeAccount"},"preferences":{"$ref":"#/components/schemas/NamespacedPreferences"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","organization","name","active","status","created"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EmployeeEmail":{"type":"object","properties":{"email":{"type":"string"},"primary":{"type":"boolean"}},"required":["email","primary"]},"EntityGroupMembership":{"type":"object","properties":{"entityType":{"type":"string"},"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"}},"required":["entityType","entityId","type"]},"EmployeeManager":{"type":"object","properties":{"managerId":{"type":"string","format":"uuid"},"type":{"type":"string"},"since":{"type":"string","format":"date-time"}},"required":["managerId","type","since"]},"EmployeeProfile":{"type":"object","properties":{"employeeNumber":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"bio":{"type":"string"},"profileImage":{"type":"string"},"birthDate":{"type":"string","format":"date"},"gender":{"type":"string"},"timezone":{"type":"string"},"location":{"type":"string"},"joinDate":{"type":"string","format":"date"},"companyRole":{"type":"string"}}},"EmployeeAccount":{"type":"object","properties":{"account":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"},"email":{"type":"string"},"role":{"type":"string"}},"required":["account","createdAt","email","role"]},"NamespacedPreferences":{"type":"object","properties":{"namespace":{"type":"string"},"values":{"type":"object","additionalProperties":{"type":"string"}}},"required":["namespace","values"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]}}},"paths":{"/api/v1/employee":{"post":{"tags":["Directory"],"summary":"Create employee","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmployeeRequest"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Employee"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## GET /api/v1/employee/{employee}

> Get employee

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"Employee":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"organization":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"emails":{"type":"array","items":{"$ref":"#/components/schemas/EmployeeEmail"}},"groups":{"type":"array","items":{"$ref":"#/components/schemas/EntityGroupMembership"}},"managers":{"type":"array","items":{"$ref":"#/components/schemas/EmployeeManager"}},"profile":{"$ref":"#/components/schemas/EmployeeProfile"},"account":{"type":"string","format":"uuid"},"authentication":{"$ref":"#/components/schemas/EmployeeAccount"},"preferences":{"$ref":"#/components/schemas/NamespacedPreferences"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","organization","name","active","status","created"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EmployeeEmail":{"type":"object","properties":{"email":{"type":"string"},"primary":{"type":"boolean"}},"required":["email","primary"]},"EntityGroupMembership":{"type":"object","properties":{"entityType":{"type":"string"},"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"}},"required":["entityType","entityId","type"]},"EmployeeManager":{"type":"object","properties":{"managerId":{"type":"string","format":"uuid"},"type":{"type":"string"},"since":{"type":"string","format":"date-time"}},"required":["managerId","type","since"]},"EmployeeProfile":{"type":"object","properties":{"employeeNumber":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"bio":{"type":"string"},"profileImage":{"type":"string"},"birthDate":{"type":"string","format":"date"},"gender":{"type":"string"},"timezone":{"type":"string"},"location":{"type":"string"},"joinDate":{"type":"string","format":"date"},"companyRole":{"type":"string"}}},"EmployeeAccount":{"type":"object","properties":{"account":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"},"email":{"type":"string"},"role":{"type":"string"}},"required":["account","createdAt","email","role"]},"NamespacedPreferences":{"type":"object","properties":{"namespace":{"type":"string"},"values":{"type":"object","additionalProperties":{"type":"string"}}},"required":["namespace","values"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]}}},"paths":{"/api/v1/employee/{employee}":{"get":{"tags":["Directory"],"summary":"Get employee","parameters":[{"name":"employee","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Employee"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## PATCH /api/v1/employee/{employee}

> Update employee

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"EmployeeRequest":{"type":"object","properties":{"name":{"type":"string"},"email":{"type":"string"},"account":{"type":"string","format":"uuid"},"role":{"type":"string"}},"required":["name","email"]},"Employee":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"organization":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"emails":{"type":"array","items":{"$ref":"#/components/schemas/EmployeeEmail"}},"groups":{"type":"array","items":{"$ref":"#/components/schemas/EntityGroupMembership"}},"managers":{"type":"array","items":{"$ref":"#/components/schemas/EmployeeManager"}},"profile":{"$ref":"#/components/schemas/EmployeeProfile"},"account":{"type":"string","format":"uuid"},"authentication":{"$ref":"#/components/schemas/EmployeeAccount"},"preferences":{"$ref":"#/components/schemas/NamespacedPreferences"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","organization","name","active","status","created"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EmployeeEmail":{"type":"object","properties":{"email":{"type":"string"},"primary":{"type":"boolean"}},"required":["email","primary"]},"EntityGroupMembership":{"type":"object","properties":{"entityType":{"type":"string"},"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"}},"required":["entityType","entityId","type"]},"EmployeeManager":{"type":"object","properties":{"managerId":{"type":"string","format":"uuid"},"type":{"type":"string"},"since":{"type":"string","format":"date-time"}},"required":["managerId","type","since"]},"EmployeeProfile":{"type":"object","properties":{"employeeNumber":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"bio":{"type":"string"},"profileImage":{"type":"string"},"birthDate":{"type":"string","format":"date"},"gender":{"type":"string"},"timezone":{"type":"string"},"location":{"type":"string"},"joinDate":{"type":"string","format":"date"},"companyRole":{"type":"string"}}},"EmployeeAccount":{"type":"object","properties":{"account":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"},"email":{"type":"string"},"role":{"type":"string"}},"required":["account","createdAt","email","role"]},"NamespacedPreferences":{"type":"object","properties":{"namespace":{"type":"string"},"values":{"type":"object","additionalProperties":{"type":"string"}}},"required":["namespace","values"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]}}},"paths":{"/api/v1/employee/{employee}":{"patch":{"tags":["Directory"],"summary":"Update employee","parameters":[{"name":"employee","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmployeeRequest"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Employee"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## GET /api/v1/employee/by-name/{name}

> Get employees by name

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"Employee":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"organization":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"emails":{"type":"array","items":{"$ref":"#/components/schemas/EmployeeEmail"}},"groups":{"type":"array","items":{"$ref":"#/components/schemas/EntityGroupMembership"}},"managers":{"type":"array","items":{"$ref":"#/components/schemas/EmployeeManager"}},"profile":{"$ref":"#/components/schemas/EmployeeProfile"},"account":{"type":"string","format":"uuid"},"authentication":{"$ref":"#/components/schemas/EmployeeAccount"},"preferences":{"$ref":"#/components/schemas/NamespacedPreferences"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","organization","name","active","status","created"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EmployeeEmail":{"type":"object","properties":{"email":{"type":"string"},"primary":{"type":"boolean"}},"required":["email","primary"]},"EntityGroupMembership":{"type":"object","properties":{"entityType":{"type":"string"},"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"}},"required":["entityType","entityId","type"]},"EmployeeManager":{"type":"object","properties":{"managerId":{"type":"string","format":"uuid"},"type":{"type":"string"},"since":{"type":"string","format":"date-time"}},"required":["managerId","type","since"]},"EmployeeProfile":{"type":"object","properties":{"employeeNumber":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"bio":{"type":"string"},"profileImage":{"type":"string"},"birthDate":{"type":"string","format":"date"},"gender":{"type":"string"},"timezone":{"type":"string"},"location":{"type":"string"},"joinDate":{"type":"string","format":"date"},"companyRole":{"type":"string"}}},"EmployeeAccount":{"type":"object","properties":{"account":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"},"email":{"type":"string"},"role":{"type":"string"}},"required":["account","createdAt","email","role"]},"NamespacedPreferences":{"type":"object","properties":{"namespace":{"type":"string"},"values":{"type":"object","additionalProperties":{"type":"string"}}},"required":["namespace","values"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]}}},"paths":{"/api/v1/employee/by-name/{name}":{"get":{"tags":["Directory"],"summary":"Get employees by name","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Employee"}}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## GET /api/v1/employee/{employee}/managers

> List managers of employee

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"EmployeeManager":{"type":"object","properties":{"managerId":{"type":"string","format":"uuid"},"type":{"type":"string"},"since":{"type":"string","format":"date-time"}},"required":["managerId","type","since"]}}},"paths":{"/api/v1/employee/{employee}/managers":{"get":{"tags":["Directory"],"summary":"List managers of employee","parameters":[{"name":"employee","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EmployeeManager"}}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## POST /api/v1/employee/{employee}/managers

> Set managers for employee

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"EmployeeManagerRequest":{"type":"object","properties":{"managerId":{"type":"string","format":"uuid"},"type":{"type":"string"}},"required":["managerId","type"]},"Employee":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"organization":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"emails":{"type":"array","items":{"$ref":"#/components/schemas/EmployeeEmail"}},"groups":{"type":"array","items":{"$ref":"#/components/schemas/EntityGroupMembership"}},"managers":{"type":"array","items":{"$ref":"#/components/schemas/EmployeeManager"}},"profile":{"$ref":"#/components/schemas/EmployeeProfile"},"account":{"type":"string","format":"uuid"},"authentication":{"$ref":"#/components/schemas/EmployeeAccount"},"preferences":{"$ref":"#/components/schemas/NamespacedPreferences"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","organization","name","active","status","created"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EmployeeEmail":{"type":"object","properties":{"email":{"type":"string"},"primary":{"type":"boolean"}},"required":["email","primary"]},"EntityGroupMembership":{"type":"object","properties":{"entityType":{"type":"string"},"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"}},"required":["entityType","entityId","type"]},"EmployeeManager":{"type":"object","properties":{"managerId":{"type":"string","format":"uuid"},"type":{"type":"string"},"since":{"type":"string","format":"date-time"}},"required":["managerId","type","since"]},"EmployeeProfile":{"type":"object","properties":{"employeeNumber":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"bio":{"type":"string"},"profileImage":{"type":"string"},"birthDate":{"type":"string","format":"date"},"gender":{"type":"string"},"timezone":{"type":"string"},"location":{"type":"string"},"joinDate":{"type":"string","format":"date"},"companyRole":{"type":"string"}}},"EmployeeAccount":{"type":"object","properties":{"account":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"},"email":{"type":"string"},"role":{"type":"string"}},"required":["account","createdAt","email","role"]},"NamespacedPreferences":{"type":"object","properties":{"namespace":{"type":"string"},"values":{"type":"object","additionalProperties":{"type":"string"}}},"required":["namespace","values"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]}}},"paths":{"/api/v1/employee/{employee}/managers":{"post":{"tags":["Directory"],"summary":"Set managers for employee","parameters":[{"name":"employee","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmployeeManagerRequest"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Employee"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## DELETE /api/v1/employee/{employee}/managers/{manager}

> Remove manager from employee

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}}},"paths":{"/api/v1/employee/{employee}/managers/{manager}":{"delete":{"tags":["Directory"],"summary":"Remove manager from employee","parameters":[{"name":"employee","in":"path","required":true,"schema":{"type":"string"}},{"name":"manager","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## GET /api/v1/employee/{employee}/profile

> Get employee profile

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"EmployeeProfile":{"type":"object","properties":{"employeeNumber":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"bio":{"type":"string"},"profileImage":{"type":"string"},"birthDate":{"type":"string","format":"date"},"gender":{"type":"string"},"timezone":{"type":"string"},"location":{"type":"string"},"joinDate":{"type":"string","format":"date"},"companyRole":{"type":"string"}}}}},"paths":{"/api/v1/employee/{employee}/profile":{"get":{"tags":["Directory"],"summary":"Get employee profile","parameters":[{"name":"employee","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmployeeProfile"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## POST /api/v1/employee/{employee}/profile

> Create or replace employee profile

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"EmployeeProfile":{"type":"object","properties":{"employeeNumber":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"bio":{"type":"string"},"profileImage":{"type":"string"},"birthDate":{"type":"string","format":"date"},"gender":{"type":"string"},"timezone":{"type":"string"},"location":{"type":"string"},"joinDate":{"type":"string","format":"date"},"companyRole":{"type":"string"}}},"Employee":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"organization":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"emails":{"type":"array","items":{"$ref":"#/components/schemas/EmployeeEmail"}},"groups":{"type":"array","items":{"$ref":"#/components/schemas/EntityGroupMembership"}},"managers":{"type":"array","items":{"$ref":"#/components/schemas/EmployeeManager"}},"profile":{"$ref":"#/components/schemas/EmployeeProfile"},"account":{"type":"string","format":"uuid"},"authentication":{"$ref":"#/components/schemas/EmployeeAccount"},"preferences":{"$ref":"#/components/schemas/NamespacedPreferences"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","organization","name","active","status","created"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EmployeeEmail":{"type":"object","properties":{"email":{"type":"string"},"primary":{"type":"boolean"}},"required":["email","primary"]},"EntityGroupMembership":{"type":"object","properties":{"entityType":{"type":"string"},"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"}},"required":["entityType","entityId","type"]},"EmployeeManager":{"type":"object","properties":{"managerId":{"type":"string","format":"uuid"},"type":{"type":"string"},"since":{"type":"string","format":"date-time"}},"required":["managerId","type","since"]},"EmployeeAccount":{"type":"object","properties":{"account":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"},"email":{"type":"string"},"role":{"type":"string"}},"required":["account","createdAt","email","role"]},"NamespacedPreferences":{"type":"object","properties":{"namespace":{"type":"string"},"values":{"type":"object","additionalProperties":{"type":"string"}}},"required":["namespace","values"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]}}},"paths":{"/api/v1/employee/{employee}/profile":{"post":{"tags":["Directory"],"summary":"Create or replace employee profile","parameters":[{"name":"employee","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmployeeProfile"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Employee"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## PATCH /api/v1/employee/{employee}/profile

> Update employee profile

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"EmployeeProfile":{"type":"object","properties":{"employeeNumber":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"bio":{"type":"string"},"profileImage":{"type":"string"},"birthDate":{"type":"string","format":"date"},"gender":{"type":"string"},"timezone":{"type":"string"},"location":{"type":"string"},"joinDate":{"type":"string","format":"date"},"companyRole":{"type":"string"}}},"Employee":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"organization":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"emails":{"type":"array","items":{"$ref":"#/components/schemas/EmployeeEmail"}},"groups":{"type":"array","items":{"$ref":"#/components/schemas/EntityGroupMembership"}},"managers":{"type":"array","items":{"$ref":"#/components/schemas/EmployeeManager"}},"profile":{"$ref":"#/components/schemas/EmployeeProfile"},"account":{"type":"string","format":"uuid"},"authentication":{"$ref":"#/components/schemas/EmployeeAccount"},"preferences":{"$ref":"#/components/schemas/NamespacedPreferences"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","organization","name","active","status","created"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EmployeeEmail":{"type":"object","properties":{"email":{"type":"string"},"primary":{"type":"boolean"}},"required":["email","primary"]},"EntityGroupMembership":{"type":"object","properties":{"entityType":{"type":"string"},"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"}},"required":["entityType","entityId","type"]},"EmployeeManager":{"type":"object","properties":{"managerId":{"type":"string","format":"uuid"},"type":{"type":"string"},"since":{"type":"string","format":"date-time"}},"required":["managerId","type","since"]},"EmployeeAccount":{"type":"object","properties":{"account":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"},"email":{"type":"string"},"role":{"type":"string"}},"required":["account","createdAt","email","role"]},"NamespacedPreferences":{"type":"object","properties":{"namespace":{"type":"string"},"values":{"type":"object","additionalProperties":{"type":"string"}}},"required":["namespace","values"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]}}},"paths":{"/api/v1/employee/{employee}/profile":{"patch":{"tags":["Directory"],"summary":"Update employee profile","parameters":[{"name":"employee","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmployeeProfile"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Employee"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## GET /api/v1/employee/by-account/{accountId}

> Get employee by account ID

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"Employee":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"organization":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"emails":{"type":"array","items":{"$ref":"#/components/schemas/EmployeeEmail"}},"groups":{"type":"array","items":{"$ref":"#/components/schemas/EntityGroupMembership"}},"managers":{"type":"array","items":{"$ref":"#/components/schemas/EmployeeManager"}},"profile":{"$ref":"#/components/schemas/EmployeeProfile"},"account":{"type":"string","format":"uuid"},"authentication":{"$ref":"#/components/schemas/EmployeeAccount"},"preferences":{"$ref":"#/components/schemas/NamespacedPreferences"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","organization","name","active","status","created"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EmployeeEmail":{"type":"object","properties":{"email":{"type":"string"},"primary":{"type":"boolean"}},"required":["email","primary"]},"EntityGroupMembership":{"type":"object","properties":{"entityType":{"type":"string"},"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"}},"required":["entityType","entityId","type"]},"EmployeeManager":{"type":"object","properties":{"managerId":{"type":"string","format":"uuid"},"type":{"type":"string"},"since":{"type":"string","format":"date-time"}},"required":["managerId","type","since"]},"EmployeeProfile":{"type":"object","properties":{"employeeNumber":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"bio":{"type":"string"},"profileImage":{"type":"string"},"birthDate":{"type":"string","format":"date"},"gender":{"type":"string"},"timezone":{"type":"string"},"location":{"type":"string"},"joinDate":{"type":"string","format":"date"},"companyRole":{"type":"string"}}},"EmployeeAccount":{"type":"object","properties":{"account":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"},"email":{"type":"string"},"role":{"type":"string"}},"required":["account","createdAt","email","role"]},"NamespacedPreferences":{"type":"object","properties":{"namespace":{"type":"string"},"values":{"type":"object","additionalProperties":{"type":"string"}}},"required":["namespace","values"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]}}},"paths":{"/api/v1/employee/by-account/{accountId}":{"get":{"tags":["Directory"],"summary":"Get employee by account ID","parameters":[{"name":"accountId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Employee"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## GET /api/v1/employee/by-manager/{managerId}

> List reports for manager

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"Employee":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"organization":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"emails":{"type":"array","items":{"$ref":"#/components/schemas/EmployeeEmail"}},"groups":{"type":"array","items":{"$ref":"#/components/schemas/EntityGroupMembership"}},"managers":{"type":"array","items":{"$ref":"#/components/schemas/EmployeeManager"}},"profile":{"$ref":"#/components/schemas/EmployeeProfile"},"account":{"type":"string","format":"uuid"},"authentication":{"$ref":"#/components/schemas/EmployeeAccount"},"preferences":{"$ref":"#/components/schemas/NamespacedPreferences"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","organization","name","active","status","created"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EmployeeEmail":{"type":"object","properties":{"email":{"type":"string"},"primary":{"type":"boolean"}},"required":["email","primary"]},"EntityGroupMembership":{"type":"object","properties":{"entityType":{"type":"string"},"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"}},"required":["entityType","entityId","type"]},"EmployeeManager":{"type":"object","properties":{"managerId":{"type":"string","format":"uuid"},"type":{"type":"string"},"since":{"type":"string","format":"date-time"}},"required":["managerId","type","since"]},"EmployeeProfile":{"type":"object","properties":{"employeeNumber":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"bio":{"type":"string"},"profileImage":{"type":"string"},"birthDate":{"type":"string","format":"date"},"gender":{"type":"string"},"timezone":{"type":"string"},"location":{"type":"string"},"joinDate":{"type":"string","format":"date"},"companyRole":{"type":"string"}}},"EmployeeAccount":{"type":"object","properties":{"account":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"},"email":{"type":"string"},"role":{"type":"string"}},"required":["account","createdAt","email","role"]},"NamespacedPreferences":{"type":"object","properties":{"namespace":{"type":"string"},"values":{"type":"object","additionalProperties":{"type":"string"}}},"required":["namespace","values"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]}}},"paths":{"/api/v1/employee/by-manager/{managerId}":{"get":{"tags":["Directory"],"summary":"List reports for manager","parameters":[{"name":"managerId","in":"path","required":true,"schema":{"type":"string"}},{"name":"type","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Employee"}}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## GET /api/v1/group

> List groups

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"Group":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string"},"organization":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"profile":{"$ref":"#/components/schemas/GroupProfile"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}},"groups":{"type":"array","items":{"$ref":"#/components/schemas/EntityGroupMembership"}},"members":{"type":"array","items":{"$ref":"#/components/schemas/GroupMember"}}},"required":["id","type","organization","name","active","status","created"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"GroupProfile":{"type":"object","properties":{"icon":{"type":"string"},"description":{"type":"string"}}},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]},"EntityGroupMembership":{"type":"object","properties":{"entityType":{"type":"string"},"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"}},"required":["entityType","entityId","type"]},"GroupMember":{"type":"object","properties":{"entityType":{"type":"string"},"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"},"since":{"type":"string","format":"date-time"}},"required":["entityType","entityId","type","since"]}}},"paths":{"/api/v1/group":{"get":{"tags":["Directory"],"summary":"List groups","parameters":[{"name":"status","in":"query","schema":{"type":"string"}},{"name":"type","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Group"}}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## POST /api/v1/group

> Create group

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"GroupRequest":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string"}},"required":["name","type"]},"Group":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string"},"organization":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"profile":{"$ref":"#/components/schemas/GroupProfile"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}},"groups":{"type":"array","items":{"$ref":"#/components/schemas/EntityGroupMembership"}},"members":{"type":"array","items":{"$ref":"#/components/schemas/GroupMember"}}},"required":["id","type","organization","name","active","status","created"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"GroupProfile":{"type":"object","properties":{"icon":{"type":"string"},"description":{"type":"string"}}},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]},"EntityGroupMembership":{"type":"object","properties":{"entityType":{"type":"string"},"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"}},"required":["entityType","entityId","type"]},"GroupMember":{"type":"object","properties":{"entityType":{"type":"string"},"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"},"since":{"type":"string","format":"date-time"}},"required":["entityType","entityId","type","since"]}}},"paths":{"/api/v1/group":{"post":{"tags":["Directory"],"summary":"Create group","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupRequest"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Group"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## GET /api/v1/group/{id}

> Get group

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"Group":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string"},"organization":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"profile":{"$ref":"#/components/schemas/GroupProfile"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}},"groups":{"type":"array","items":{"$ref":"#/components/schemas/EntityGroupMembership"}},"members":{"type":"array","items":{"$ref":"#/components/schemas/GroupMember"}}},"required":["id","type","organization","name","active","status","created"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"GroupProfile":{"type":"object","properties":{"icon":{"type":"string"},"description":{"type":"string"}}},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]},"EntityGroupMembership":{"type":"object","properties":{"entityType":{"type":"string"},"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"}},"required":["entityType","entityId","type"]},"GroupMember":{"type":"object","properties":{"entityType":{"type":"string"},"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"},"since":{"type":"string","format":"date-time"}},"required":["entityType","entityId","type","since"]}}},"paths":{"/api/v1/group/{id}":{"get":{"tags":["Directory"],"summary":"Get group","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Group"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## PATCH /api/v1/group/{id}

> Update group

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"GroupRequest":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string"}},"required":["name","type"]},"Group":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string"},"organization":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"profile":{"$ref":"#/components/schemas/GroupProfile"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}},"groups":{"type":"array","items":{"$ref":"#/components/schemas/EntityGroupMembership"}},"members":{"type":"array","items":{"$ref":"#/components/schemas/GroupMember"}}},"required":["id","type","organization","name","active","status","created"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"GroupProfile":{"type":"object","properties":{"icon":{"type":"string"},"description":{"type":"string"}}},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]},"EntityGroupMembership":{"type":"object","properties":{"entityType":{"type":"string"},"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"}},"required":["entityType","entityId","type"]},"GroupMember":{"type":"object","properties":{"entityType":{"type":"string"},"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"},"since":{"type":"string","format":"date-time"}},"required":["entityType","entityId","type","since"]}}},"paths":{"/api/v1/group/{id}":{"patch":{"tags":["Directory"],"summary":"Update group","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupRequest"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Group"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## GET /api/v1/group/{group}/profile

> Get group profile

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"GroupProfile":{"type":"object","properties":{"icon":{"type":"string"},"description":{"type":"string"}}}}},"paths":{"/api/v1/group/{group}/profile":{"get":{"tags":["Directory"],"summary":"Get group profile","parameters":[{"name":"group","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupProfile"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## POST /api/v1/group/{group}/profile

> Create or replace group profile

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"GroupProfile":{"type":"object","properties":{"icon":{"type":"string"},"description":{"type":"string"}}},"Group":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string"},"organization":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"profile":{"$ref":"#/components/schemas/GroupProfile"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}},"groups":{"type":"array","items":{"$ref":"#/components/schemas/EntityGroupMembership"}},"members":{"type":"array","items":{"$ref":"#/components/schemas/GroupMember"}}},"required":["id","type","organization","name","active","status","created"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]},"EntityGroupMembership":{"type":"object","properties":{"entityType":{"type":"string"},"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"}},"required":["entityType","entityId","type"]},"GroupMember":{"type":"object","properties":{"entityType":{"type":"string"},"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"},"since":{"type":"string","format":"date-time"}},"required":["entityType","entityId","type","since"]}}},"paths":{"/api/v1/group/{group}/profile":{"post":{"tags":["Directory"],"summary":"Create or replace group profile","parameters":[{"name":"group","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupProfile"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Group"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## PATCH /api/v1/group/{group}/profile

> Update group profile

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"GroupProfile":{"type":"object","properties":{"icon":{"type":"string"},"description":{"type":"string"}}},"Group":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string"},"organization":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"profile":{"$ref":"#/components/schemas/GroupProfile"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}},"groups":{"type":"array","items":{"$ref":"#/components/schemas/EntityGroupMembership"}},"members":{"type":"array","items":{"$ref":"#/components/schemas/GroupMember"}}},"required":["id","type","organization","name","active","status","created"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]},"EntityGroupMembership":{"type":"object","properties":{"entityType":{"type":"string"},"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"}},"required":["entityType","entityId","type"]},"GroupMember":{"type":"object","properties":{"entityType":{"type":"string"},"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"},"since":{"type":"string","format":"date-time"}},"required":["entityType","entityId","type","since"]}}},"paths":{"/api/v1/group/{group}/profile":{"patch":{"tags":["Directory"],"summary":"Update group profile","parameters":[{"name":"group","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupProfile"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Group"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## GET /api/v1/group/{groupId}/members

> List group members

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"EntityInfo":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"},"organization":{"type":"string","format":"uuid"}},"required":["entityId","type"]},"Employee":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"organization":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"emails":{"type":"array","items":{"$ref":"#/components/schemas/EmployeeEmail"}},"groups":{"type":"array","items":{"$ref":"#/components/schemas/EntityGroupMembership"}},"managers":{"type":"array","items":{"$ref":"#/components/schemas/EmployeeManager"}},"profile":{"$ref":"#/components/schemas/EmployeeProfile"},"account":{"type":"string","format":"uuid"},"authentication":{"$ref":"#/components/schemas/EmployeeAccount"},"preferences":{"$ref":"#/components/schemas/NamespacedPreferences"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","organization","name","active","status","created"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EmployeeEmail":{"type":"object","properties":{"email":{"type":"string"},"primary":{"type":"boolean"}},"required":["email","primary"]},"EntityGroupMembership":{"type":"object","properties":{"entityType":{"type":"string"},"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"}},"required":["entityType","entityId","type"]},"EmployeeManager":{"type":"object","properties":{"managerId":{"type":"string","format":"uuid"},"type":{"type":"string"},"since":{"type":"string","format":"date-time"}},"required":["managerId","type","since"]},"EmployeeProfile":{"type":"object","properties":{"employeeNumber":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"bio":{"type":"string"},"profileImage":{"type":"string"},"birthDate":{"type":"string","format":"date"},"gender":{"type":"string"},"timezone":{"type":"string"},"location":{"type":"string"},"joinDate":{"type":"string","format":"date"},"companyRole":{"type":"string"}}},"EmployeeAccount":{"type":"object","properties":{"account":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"},"email":{"type":"string"},"role":{"type":"string"}},"required":["account","createdAt","email","role"]},"NamespacedPreferences":{"type":"object","properties":{"namespace":{"type":"string"},"values":{"type":"object","additionalProperties":{"type":"string"}}},"required":["namespace","values"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]}}},"paths":{"/api/v1/group/{groupId}/members":{"get":{"tags":["Directory"],"summary":"List group members","parameters":[{"name":"groupId","in":"path","required":true,"schema":{"type":"string"}},{"name":"entity","in":"query","schema":{"type":"string"}},{"name":"membership","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"oneOf":[{"$ref":"#/components/schemas/EntityInfo"},{"$ref":"#/components/schemas/Employee"}]}}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## GET /api/v1/entity/{entity}/groups

> Get entity groups

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"EntityGroupMembership":{"type":"object","properties":{"entityType":{"type":"string"},"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"}},"required":["entityType","entityId","type"]}}},"paths":{"/api/v1/entity/{entity}/groups":{"get":{"tags":["Directory"],"summary":"Get entity groups","parameters":[{"name":"entity","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EntityGroupMembership"}}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## POST /api/v1/entity/{entity}/groups

> Set groups for entity

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}}},"paths":{"/api/v1/entity/{entity}/groups":{"post":{"tags":["Directory"],"summary":"Set groups for entity","parameters":[{"name":"entity","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"groupId":{"type":"string","format":"uuid"},"type":{"type":"string"}}}}}}},"responses":{"200":{"description":"OK"},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## DELETE /api/v1/entity/{entity}/groups/{group}

> Remove entity from group

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Directory","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}}},"paths":{"/api/v1/entity/{entity}/groups/{group}":{"delete":{"tags":["Directory"],"summary":"Remove entity from group","parameters":[{"name":"entity","in":"path","required":true,"schema":{"type":"string"}},{"name":"group","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```


# OKRs (or Goals)

The OKRs API provides generic functionality for a broad set of Goal types - including OKRs, Rocks or KPIs. For simplicity, these are referenced as OKRs below. OKRs can be measurable or not and can have any number of children or parents that contribute to its current value. OKRs can be assigned to both Employees and Groups/Teams and by default are allowed to be assigned an owner and support tasks.

## GET /api/v1/objective

> List objectives

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"OKRs (or Goals)","description":"The OKRs API provides generic functionality for a broad set of Goal types - including OKRs, Rocks or KPIs. For simplicity, these are referenced as OKRs below.  OKRs can be measurable or not and can have any number of children or parents that contribute to its current value.  OKRs can be assigned to both Employees and Groups/Teams and by default are allowed to be assigned an owner and support tasks."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"Objective":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"organization":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"description":{"type":"string"},"startDate":{"type":"string","format":"date"},"endDate":{"type":"string","format":"date"},"cycleId":{"type":"string","format":"uuid"},"parentId":{"type":"string","format":"uuid"},"treeRootId":{"type":"string","format":"uuid"},"measurable":{"type":"boolean"},"metric":{"$ref":"#/components/schemas/ObjectiveMetric"},"weightTowardsParent":{"type":"integer"},"contributesToParent":{"type":"boolean"},"childObjectives":{"type":"array","items":{"$ref":"#/components/schemas/Objective"}},"assessment":{"type":"string"},"log":{"type":"array","items":{"$ref":"#/components/schemas/ObjectiveLog"}},"assignees":{"type":"array","items":{"$ref":"#/components/schemas/EntityAssignee"}},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}},"tasks":{"type":"array","items":{"$ref":"#/components/schemas/Task"}},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"sharing":{"$ref":"#/components/schemas/SharingInfo"},"order":{"type":"integer"}},"required":["id","organization","name","active","status","created","sharing","order"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"ObjectiveMetric":{"type":"object","properties":{"startingValue":{"type":"number"},"currentValue":{"type":"number"},"targetValue":{"type":"number"},"metricType":{"type":"string"},"metricUnit":{"type":"string"},"logs":{"type":"array","items":{"$ref":"#/components/schemas/MetricLog"}}},"required":["startingValue","currentValue","targetValue"]},"MetricLog":{"type":"object","properties":{"value":{"type":"number"},"loggedAt":{"type":"string","format":"date-time"},"loggedBy":{"type":"string","format":"uuid"}},"required":["value","loggedAt","loggedBy"]},"ObjectiveLog":{"type":"object","properties":{"loggedAt":{"type":"string","format":"date-time"},"loggedBy":{"type":"string","format":"uuid"},"progress":{"type":"number"},"targetValue":{"type":"number"},"assessment":{"type":"string"}}},"EntityAssignee":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"entityType":{"type":"string"}},"required":["entityId","entityType"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]},"Task":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"assignees":{"type":"array","items":{"$ref":"#/components/schemas/EntityAssignee"}},"organization":{"type":"string","format":"uuid"},"description":{"type":"string"},"dueDate":{"type":"string","format":"date"},"connectedTo":{"$ref":"#/components/schemas/EntityInfo"},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"order":{"type":"integer"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","name","active","status","created","organization","order"]},"EntityInfo":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"},"organization":{"type":"string","format":"uuid"}},"required":["entityId","type"]},"Note":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"note":{"type":"string"},"author":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"}}},"SharingInfo":{"type":"object","properties":{"visibility":{"type":"string"},"ownerId":{"type":"string","format":"uuid"}}}}},"paths":{"/api/v1/objective":{"get":{"tags":["OKRs (or Goals)"],"summary":"List objectives","parameters":[{"name":"status","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Objective"}}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## POST /api/v1/objective

> Create objective

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"OKRs (or Goals)","description":"The OKRs API provides generic functionality for a broad set of Goal types - including OKRs, Rocks or KPIs. For simplicity, these are referenced as OKRs below.  OKRs can be measurable or not and can have any number of children or parents that contribute to its current value.  OKRs can be assigned to both Employees and Groups/Teams and by default are allowed to be assigned an owner and support tasks."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"ObjectiveRequest":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"startDate":{"type":"string","format":"date"},"endDate":{"type":"string","format":"date"},"cycleId":{"type":"string","format":"uuid"},"parentId":{"type":"string","format":"uuid"},"startingValue":{"type":"number"},"currentValue":{"type":"number"},"targetValue":{"type":"number"},"metricType":{"type":"string"},"metricUnit":{"type":"string"},"weightTowardsParent":{"type":"integer"},"assessment":{"type":"string"},"visibility":{"type":"string"},"owner":{"type":"string","format":"uuid"},"order":{"type":"integer"}}},"Objective":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"organization":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"description":{"type":"string"},"startDate":{"type":"string","format":"date"},"endDate":{"type":"string","format":"date"},"cycleId":{"type":"string","format":"uuid"},"parentId":{"type":"string","format":"uuid"},"treeRootId":{"type":"string","format":"uuid"},"measurable":{"type":"boolean"},"metric":{"$ref":"#/components/schemas/ObjectiveMetric"},"weightTowardsParent":{"type":"integer"},"contributesToParent":{"type":"boolean"},"childObjectives":{"type":"array","items":{"$ref":"#/components/schemas/Objective"}},"assessment":{"type":"string"},"log":{"type":"array","items":{"$ref":"#/components/schemas/ObjectiveLog"}},"assignees":{"type":"array","items":{"$ref":"#/components/schemas/EntityAssignee"}},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}},"tasks":{"type":"array","items":{"$ref":"#/components/schemas/Task"}},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"sharing":{"$ref":"#/components/schemas/SharingInfo"},"order":{"type":"integer"}},"required":["id","organization","name","active","status","created","sharing","order"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"ObjectiveMetric":{"type":"object","properties":{"startingValue":{"type":"number"},"currentValue":{"type":"number"},"targetValue":{"type":"number"},"metricType":{"type":"string"},"metricUnit":{"type":"string"},"logs":{"type":"array","items":{"$ref":"#/components/schemas/MetricLog"}}},"required":["startingValue","currentValue","targetValue"]},"MetricLog":{"type":"object","properties":{"value":{"type":"number"},"loggedAt":{"type":"string","format":"date-time"},"loggedBy":{"type":"string","format":"uuid"}},"required":["value","loggedAt","loggedBy"]},"ObjectiveLog":{"type":"object","properties":{"loggedAt":{"type":"string","format":"date-time"},"loggedBy":{"type":"string","format":"uuid"},"progress":{"type":"number"},"targetValue":{"type":"number"},"assessment":{"type":"string"}}},"EntityAssignee":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"entityType":{"type":"string"}},"required":["entityId","entityType"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]},"Task":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"assignees":{"type":"array","items":{"$ref":"#/components/schemas/EntityAssignee"}},"organization":{"type":"string","format":"uuid"},"description":{"type":"string"},"dueDate":{"type":"string","format":"date"},"connectedTo":{"$ref":"#/components/schemas/EntityInfo"},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"order":{"type":"integer"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","name","active","status","created","organization","order"]},"EntityInfo":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"},"organization":{"type":"string","format":"uuid"}},"required":["entityId","type"]},"Note":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"note":{"type":"string"},"author":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"}}},"SharingInfo":{"type":"object","properties":{"visibility":{"type":"string"},"ownerId":{"type":"string","format":"uuid"}}}}},"paths":{"/api/v1/objective":{"post":{"tags":["OKRs (or Goals)"],"summary":"Create objective","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ObjectiveRequest"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Objective"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## GET /api/v1/objective/{id}

> Get objective

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"OKRs (or Goals)","description":"The OKRs API provides generic functionality for a broad set of Goal types - including OKRs, Rocks or KPIs. For simplicity, these are referenced as OKRs below.  OKRs can be measurable or not and can have any number of children or parents that contribute to its current value.  OKRs can be assigned to both Employees and Groups/Teams and by default are allowed to be assigned an owner and support tasks."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"Objective":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"organization":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"description":{"type":"string"},"startDate":{"type":"string","format":"date"},"endDate":{"type":"string","format":"date"},"cycleId":{"type":"string","format":"uuid"},"parentId":{"type":"string","format":"uuid"},"treeRootId":{"type":"string","format":"uuid"},"measurable":{"type":"boolean"},"metric":{"$ref":"#/components/schemas/ObjectiveMetric"},"weightTowardsParent":{"type":"integer"},"contributesToParent":{"type":"boolean"},"childObjectives":{"type":"array","items":{"$ref":"#/components/schemas/Objective"}},"assessment":{"type":"string"},"log":{"type":"array","items":{"$ref":"#/components/schemas/ObjectiveLog"}},"assignees":{"type":"array","items":{"$ref":"#/components/schemas/EntityAssignee"}},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}},"tasks":{"type":"array","items":{"$ref":"#/components/schemas/Task"}},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"sharing":{"$ref":"#/components/schemas/SharingInfo"},"order":{"type":"integer"}},"required":["id","organization","name","active","status","created","sharing","order"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"ObjectiveMetric":{"type":"object","properties":{"startingValue":{"type":"number"},"currentValue":{"type":"number"},"targetValue":{"type":"number"},"metricType":{"type":"string"},"metricUnit":{"type":"string"},"logs":{"type":"array","items":{"$ref":"#/components/schemas/MetricLog"}}},"required":["startingValue","currentValue","targetValue"]},"MetricLog":{"type":"object","properties":{"value":{"type":"number"},"loggedAt":{"type":"string","format":"date-time"},"loggedBy":{"type":"string","format":"uuid"}},"required":["value","loggedAt","loggedBy"]},"ObjectiveLog":{"type":"object","properties":{"loggedAt":{"type":"string","format":"date-time"},"loggedBy":{"type":"string","format":"uuid"},"progress":{"type":"number"},"targetValue":{"type":"number"},"assessment":{"type":"string"}}},"EntityAssignee":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"entityType":{"type":"string"}},"required":["entityId","entityType"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]},"Task":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"assignees":{"type":"array","items":{"$ref":"#/components/schemas/EntityAssignee"}},"organization":{"type":"string","format":"uuid"},"description":{"type":"string"},"dueDate":{"type":"string","format":"date"},"connectedTo":{"$ref":"#/components/schemas/EntityInfo"},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"order":{"type":"integer"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","name","active","status","created","organization","order"]},"EntityInfo":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"},"organization":{"type":"string","format":"uuid"}},"required":["entityId","type"]},"Note":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"note":{"type":"string"},"author":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"}}},"SharingInfo":{"type":"object","properties":{"visibility":{"type":"string"},"ownerId":{"type":"string","format":"uuid"}}}}},"paths":{"/api/v1/objective/{id}":{"get":{"tags":["OKRs (or Goals)"],"summary":"Get objective","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Objective"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## PATCH /api/v1/objective/{id}

> Update objective

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"OKRs (or Goals)","description":"The OKRs API provides generic functionality for a broad set of Goal types - including OKRs, Rocks or KPIs. For simplicity, these are referenced as OKRs below.  OKRs can be measurable or not and can have any number of children or parents that contribute to its current value.  OKRs can be assigned to both Employees and Groups/Teams and by default are allowed to be assigned an owner and support tasks."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"ObjectiveRequest":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"startDate":{"type":"string","format":"date"},"endDate":{"type":"string","format":"date"},"cycleId":{"type":"string","format":"uuid"},"parentId":{"type":"string","format":"uuid"},"startingValue":{"type":"number"},"currentValue":{"type":"number"},"targetValue":{"type":"number"},"metricType":{"type":"string"},"metricUnit":{"type":"string"},"weightTowardsParent":{"type":"integer"},"assessment":{"type":"string"},"visibility":{"type":"string"},"owner":{"type":"string","format":"uuid"},"order":{"type":"integer"}}},"Objective":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"organization":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"description":{"type":"string"},"startDate":{"type":"string","format":"date"},"endDate":{"type":"string","format":"date"},"cycleId":{"type":"string","format":"uuid"},"parentId":{"type":"string","format":"uuid"},"treeRootId":{"type":"string","format":"uuid"},"measurable":{"type":"boolean"},"metric":{"$ref":"#/components/schemas/ObjectiveMetric"},"weightTowardsParent":{"type":"integer"},"contributesToParent":{"type":"boolean"},"childObjectives":{"type":"array","items":{"$ref":"#/components/schemas/Objective"}},"assessment":{"type":"string"},"log":{"type":"array","items":{"$ref":"#/components/schemas/ObjectiveLog"}},"assignees":{"type":"array","items":{"$ref":"#/components/schemas/EntityAssignee"}},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}},"tasks":{"type":"array","items":{"$ref":"#/components/schemas/Task"}},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"sharing":{"$ref":"#/components/schemas/SharingInfo"},"order":{"type":"integer"}},"required":["id","organization","name","active","status","created","sharing","order"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"ObjectiveMetric":{"type":"object","properties":{"startingValue":{"type":"number"},"currentValue":{"type":"number"},"targetValue":{"type":"number"},"metricType":{"type":"string"},"metricUnit":{"type":"string"},"logs":{"type":"array","items":{"$ref":"#/components/schemas/MetricLog"}}},"required":["startingValue","currentValue","targetValue"]},"MetricLog":{"type":"object","properties":{"value":{"type":"number"},"loggedAt":{"type":"string","format":"date-time"},"loggedBy":{"type":"string","format":"uuid"}},"required":["value","loggedAt","loggedBy"]},"ObjectiveLog":{"type":"object","properties":{"loggedAt":{"type":"string","format":"date-time"},"loggedBy":{"type":"string","format":"uuid"},"progress":{"type":"number"},"targetValue":{"type":"number"},"assessment":{"type":"string"}}},"EntityAssignee":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"entityType":{"type":"string"}},"required":["entityId","entityType"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]},"Task":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"assignees":{"type":"array","items":{"$ref":"#/components/schemas/EntityAssignee"}},"organization":{"type":"string","format":"uuid"},"description":{"type":"string"},"dueDate":{"type":"string","format":"date"},"connectedTo":{"$ref":"#/components/schemas/EntityInfo"},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"order":{"type":"integer"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","name","active","status","created","organization","order"]},"EntityInfo":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"},"organization":{"type":"string","format":"uuid"}},"required":["entityId","type"]},"Note":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"note":{"type":"string"},"author":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"}}},"SharingInfo":{"type":"object","properties":{"visibility":{"type":"string"},"ownerId":{"type":"string","format":"uuid"}}}}},"paths":{"/api/v1/objective/{id}":{"patch":{"tags":["OKRs (or Goals)"],"summary":"Update objective","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ObjectiveRequest"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Objective"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## POST /api/v1/objective/{id}/progress

> Log objective progress

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"OKRs (or Goals)","description":"The OKRs API provides generic functionality for a broad set of Goal types - including OKRs, Rocks or KPIs. For simplicity, these are referenced as OKRs below.  OKRs can be measurable or not and can have any number of children or parents that contribute to its current value.  OKRs can be assigned to both Employees and Groups/Teams and by default are allowed to be assigned an owner and support tasks."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"ObjectiveLogRequest":{"type":"object","properties":{"type":{"type":"string"},"value":{"type":"number"},"requestor":{"type":"string","format":"uuid"}},"required":["type","value"]},"Objective":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"organization":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"description":{"type":"string"},"startDate":{"type":"string","format":"date"},"endDate":{"type":"string","format":"date"},"cycleId":{"type":"string","format":"uuid"},"parentId":{"type":"string","format":"uuid"},"treeRootId":{"type":"string","format":"uuid"},"measurable":{"type":"boolean"},"metric":{"$ref":"#/components/schemas/ObjectiveMetric"},"weightTowardsParent":{"type":"integer"},"contributesToParent":{"type":"boolean"},"childObjectives":{"type":"array","items":{"$ref":"#/components/schemas/Objective"}},"assessment":{"type":"string"},"log":{"type":"array","items":{"$ref":"#/components/schemas/ObjectiveLog"}},"assignees":{"type":"array","items":{"$ref":"#/components/schemas/EntityAssignee"}},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}},"tasks":{"type":"array","items":{"$ref":"#/components/schemas/Task"}},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"sharing":{"$ref":"#/components/schemas/SharingInfo"},"order":{"type":"integer"}},"required":["id","organization","name","active","status","created","sharing","order"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"ObjectiveMetric":{"type":"object","properties":{"startingValue":{"type":"number"},"currentValue":{"type":"number"},"targetValue":{"type":"number"},"metricType":{"type":"string"},"metricUnit":{"type":"string"},"logs":{"type":"array","items":{"$ref":"#/components/schemas/MetricLog"}}},"required":["startingValue","currentValue","targetValue"]},"MetricLog":{"type":"object","properties":{"value":{"type":"number"},"loggedAt":{"type":"string","format":"date-time"},"loggedBy":{"type":"string","format":"uuid"}},"required":["value","loggedAt","loggedBy"]},"ObjectiveLog":{"type":"object","properties":{"loggedAt":{"type":"string","format":"date-time"},"loggedBy":{"type":"string","format":"uuid"},"progress":{"type":"number"},"targetValue":{"type":"number"},"assessment":{"type":"string"}}},"EntityAssignee":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"entityType":{"type":"string"}},"required":["entityId","entityType"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]},"Task":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"assignees":{"type":"array","items":{"$ref":"#/components/schemas/EntityAssignee"}},"organization":{"type":"string","format":"uuid"},"description":{"type":"string"},"dueDate":{"type":"string","format":"date"},"connectedTo":{"$ref":"#/components/schemas/EntityInfo"},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"order":{"type":"integer"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","name","active","status","created","organization","order"]},"EntityInfo":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"},"organization":{"type":"string","format":"uuid"}},"required":["entityId","type"]},"Note":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"note":{"type":"string"},"author":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"}}},"SharingInfo":{"type":"object","properties":{"visibility":{"type":"string"},"ownerId":{"type":"string","format":"uuid"}}}}},"paths":{"/api/v1/objective/{id}/progress":{"post":{"tags":["OKRs (or Goals)"],"summary":"Log objective progress","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ObjectiveLogRequest"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Objective"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## GET /api/v1/objective-cycle

> List objective cycles

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"OKRs (or Goals)","description":"The OKRs API provides generic functionality for a broad set of Goal types - including OKRs, Rocks or KPIs. For simplicity, these are referenced as OKRs below.  OKRs can be measurable or not and can have any number of children or parents that contribute to its current value.  OKRs can be assigned to both Employees and Groups/Teams and by default are allowed to be assigned an owner and support tasks."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"ObjectiveCycle":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"organization":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"startDate":{"type":"string","format":"date"},"endDate":{"type":"string","format":"date"},"description":{"type":"string"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","organization","name","active","status","created","startDate","endDate"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]}}},"paths":{"/api/v1/objective-cycle":{"get":{"tags":["OKRs (or Goals)"],"summary":"List objective cycles","parameters":[{"name":"status","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ObjectiveCycle"}}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## POST /api/v1/objective-cycle

> Create objective cycle

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"OKRs (or Goals)","description":"The OKRs API provides generic functionality for a broad set of Goal types - including OKRs, Rocks or KPIs. For simplicity, these are referenced as OKRs below.  OKRs can be measurable or not and can have any number of children or parents that contribute to its current value.  OKRs can be assigned to both Employees and Groups/Teams and by default are allowed to be assigned an owner and support tasks."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"ObjectiveCycleRequest":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"startDate":{"type":"string","format":"date"},"endDate":{"type":"string","format":"date"}},"required":["name","startDate","endDate"]},"ObjectiveCycle":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"organization":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"startDate":{"type":"string","format":"date"},"endDate":{"type":"string","format":"date"},"description":{"type":"string"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","organization","name","active","status","created","startDate","endDate"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]}}},"paths":{"/api/v1/objective-cycle":{"post":{"tags":["OKRs (or Goals)"],"summary":"Create objective cycle","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ObjectiveCycleRequest"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ObjectiveCycle"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## GET /api/v1/objective-cycle/{id}

> Get objective cycle

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"OKRs (or Goals)","description":"The OKRs API provides generic functionality for a broad set of Goal types - including OKRs, Rocks or KPIs. For simplicity, these are referenced as OKRs below.  OKRs can be measurable or not and can have any number of children or parents that contribute to its current value.  OKRs can be assigned to both Employees and Groups/Teams and by default are allowed to be assigned an owner and support tasks."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"ObjectiveCycle":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"organization":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"startDate":{"type":"string","format":"date"},"endDate":{"type":"string","format":"date"},"description":{"type":"string"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","organization","name","active","status","created","startDate","endDate"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]}}},"paths":{"/api/v1/objective-cycle/{id}":{"get":{"tags":["OKRs (or Goals)"],"summary":"Get objective cycle","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ObjectiveCycle"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## PATCH /api/v1/objective-cycle/{id}

> Update objective cycle

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"OKRs (or Goals)","description":"The OKRs API provides generic functionality for a broad set of Goal types - including OKRs, Rocks or KPIs. For simplicity, these are referenced as OKRs below.  OKRs can be measurable or not and can have any number of children or parents that contribute to its current value.  OKRs can be assigned to both Employees and Groups/Teams and by default are allowed to be assigned an owner and support tasks."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"ObjectiveCycleRequest":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"startDate":{"type":"string","format":"date"},"endDate":{"type":"string","format":"date"}},"required":["name","startDate","endDate"]},"ObjectiveCycle":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"organization":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"startDate":{"type":"string","format":"date"},"endDate":{"type":"string","format":"date"},"description":{"type":"string"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","organization","name","active","status","created","startDate","endDate"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]}}},"paths":{"/api/v1/objective-cycle/{id}":{"patch":{"tags":["OKRs (or Goals)"],"summary":"Update objective cycle","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ObjectiveCycleRequest"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ObjectiveCycle"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```


# Meetings

The Meetings API provides a powerful mechanism to capture notes, provide talking points or track action items from both 1:1 and group meetings. It does not provide functionality to record or host meetings.

## POST /api/v1/meeting

> Create meeting

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Meetings","description":"The Meetings API provides a powerful mechanism to capture notes, provide talking points or track action items from both 1:1 and group meetings. It does not provide functionality to record or host meetings."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"MeetingRequest":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string"},"recurring":{"type":"boolean"}},"required":["name","type"]},"Meeting":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string"},"recurring":{"type":"boolean"},"organization":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}},"assignees":{"type":"array","items":{"$ref":"#/components/schemas/EntityAssignee"}},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"tasks":{"type":"array","items":{"$ref":"#/components/schemas/Task"}},"events":{"type":"array","items":{"$ref":"#/components/schemas/MeetingEvent"}}},"required":["id","type","organization","name","active","status","created"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]},"EntityAssignee":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"entityType":{"type":"string"}},"required":["entityId","entityType"]},"Note":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"note":{"type":"string"},"author":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"}}},"Task":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"assignees":{"type":"array","items":{"$ref":"#/components/schemas/EntityAssignee"}},"organization":{"type":"string","format":"uuid"},"description":{"type":"string"},"dueDate":{"type":"string","format":"date"},"connectedTo":{"$ref":"#/components/schemas/EntityInfo"},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"order":{"type":"integer"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","name","active","status","created","organization","order"]},"EntityInfo":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"},"organization":{"type":"string","format":"uuid"}},"required":["entityId","type"]},"MeetingEvent":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"meetingId":{"type":"string","format":"uuid"},"startTime":{"type":"string","format":"date-time"},"endTime":{"type":"string","format":"date-time"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"tasks":{"type":"array","items":{"$ref":"#/components/schemas/Task"}}},"required":["id","meetingId","name","active","status","created","startTime"]}}},"paths":{"/api/v1/meeting":{"post":{"tags":["Meetings"],"summary":"Create meeting","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeetingRequest"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Meeting"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## GET /api/v1/meeting/{id}

> Get meeting

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Meetings","description":"The Meetings API provides a powerful mechanism to capture notes, provide talking points or track action items from both 1:1 and group meetings. It does not provide functionality to record or host meetings."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"Meeting":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string"},"recurring":{"type":"boolean"},"organization":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}},"assignees":{"type":"array","items":{"$ref":"#/components/schemas/EntityAssignee"}},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"tasks":{"type":"array","items":{"$ref":"#/components/schemas/Task"}},"events":{"type":"array","items":{"$ref":"#/components/schemas/MeetingEvent"}}},"required":["id","type","organization","name","active","status","created"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]},"EntityAssignee":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"entityType":{"type":"string"}},"required":["entityId","entityType"]},"Note":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"note":{"type":"string"},"author":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"}}},"Task":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"assignees":{"type":"array","items":{"$ref":"#/components/schemas/EntityAssignee"}},"organization":{"type":"string","format":"uuid"},"description":{"type":"string"},"dueDate":{"type":"string","format":"date"},"connectedTo":{"$ref":"#/components/schemas/EntityInfo"},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"order":{"type":"integer"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","name","active","status","created","organization","order"]},"EntityInfo":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"},"organization":{"type":"string","format":"uuid"}},"required":["entityId","type"]},"MeetingEvent":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"meetingId":{"type":"string","format":"uuid"},"startTime":{"type":"string","format":"date-time"},"endTime":{"type":"string","format":"date-time"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"tasks":{"type":"array","items":{"$ref":"#/components/schemas/Task"}}},"required":["id","meetingId","name","active","status","created","startTime"]}}},"paths":{"/api/v1/meeting/{id}":{"get":{"tags":["Meetings"],"summary":"Get meeting","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Meeting"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## PATCH /api/v1/meeting/{id}

> Update meeting

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Meetings","description":"The Meetings API provides a powerful mechanism to capture notes, provide talking points or track action items from both 1:1 and group meetings. It does not provide functionality to record or host meetings."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"MeetingRequest":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string"},"recurring":{"type":"boolean"}},"required":["name","type"]},"Meeting":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string"},"recurring":{"type":"boolean"},"organization":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}},"assignees":{"type":"array","items":{"$ref":"#/components/schemas/EntityAssignee"}},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"tasks":{"type":"array","items":{"$ref":"#/components/schemas/Task"}},"events":{"type":"array","items":{"$ref":"#/components/schemas/MeetingEvent"}}},"required":["id","type","organization","name","active","status","created"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]},"EntityAssignee":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"entityType":{"type":"string"}},"required":["entityId","entityType"]},"Note":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"note":{"type":"string"},"author":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"}}},"Task":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"assignees":{"type":"array","items":{"$ref":"#/components/schemas/EntityAssignee"}},"organization":{"type":"string","format":"uuid"},"description":{"type":"string"},"dueDate":{"type":"string","format":"date"},"connectedTo":{"$ref":"#/components/schemas/EntityInfo"},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"order":{"type":"integer"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","name","active","status","created","organization","order"]},"EntityInfo":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"},"organization":{"type":"string","format":"uuid"}},"required":["entityId","type"]},"MeetingEvent":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"meetingId":{"type":"string","format":"uuid"},"startTime":{"type":"string","format":"date-time"},"endTime":{"type":"string","format":"date-time"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"tasks":{"type":"array","items":{"$ref":"#/components/schemas/Task"}}},"required":["id","meetingId","name","active","status","created","startTime"]}}},"paths":{"/api/v1/meeting/{id}":{"patch":{"tags":["Meetings"],"summary":"Update meeting","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeetingRequest"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Meeting"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## POST /api/v1/meeting/{meetingId}/participant

> Add participant to meeting

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Meetings","description":"The Meetings API provides a powerful mechanism to capture notes, provide talking points or track action items from both 1:1 and group meetings. It does not provide functionality to record or host meetings."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"Meeting":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string"},"recurring":{"type":"boolean"},"organization":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}},"assignees":{"type":"array","items":{"$ref":"#/components/schemas/EntityAssignee"}},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"tasks":{"type":"array","items":{"$ref":"#/components/schemas/Task"}},"events":{"type":"array","items":{"$ref":"#/components/schemas/MeetingEvent"}}},"required":["id","type","organization","name","active","status","created"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]},"EntityAssignee":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"entityType":{"type":"string"}},"required":["entityId","entityType"]},"Note":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"note":{"type":"string"},"author":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"}}},"Task":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"assignees":{"type":"array","items":{"$ref":"#/components/schemas/EntityAssignee"}},"organization":{"type":"string","format":"uuid"},"description":{"type":"string"},"dueDate":{"type":"string","format":"date"},"connectedTo":{"$ref":"#/components/schemas/EntityInfo"},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"order":{"type":"integer"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","name","active","status","created","organization","order"]},"EntityInfo":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"},"organization":{"type":"string","format":"uuid"}},"required":["entityId","type"]},"MeetingEvent":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"meetingId":{"type":"string","format":"uuid"},"startTime":{"type":"string","format":"date-time"},"endTime":{"type":"string","format":"date-time"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"tasks":{"type":"array","items":{"$ref":"#/components/schemas/Task"}}},"required":["id","meetingId","name","active","status","created","startTime"]}}},"paths":{"/api/v1/meeting/{meetingId}/participant":{"post":{"tags":["Meetings"],"summary":"Add participant to meeting","parameters":[{"name":"meetingId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"entityIdOrEmail":{"type":"string"}},"required":["entityIdOrEmail"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Meeting"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## DELETE /api/v1/meeting/{meetingId}/participant/{entityIdOrEmail}

> Remove participant from meeting

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Meetings","description":"The Meetings API provides a powerful mechanism to capture notes, provide talking points or track action items from both 1:1 and group meetings. It does not provide functionality to record or host meetings."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"Meeting":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string"},"recurring":{"type":"boolean"},"organization":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}},"assignees":{"type":"array","items":{"$ref":"#/components/schemas/EntityAssignee"}},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"tasks":{"type":"array","items":{"$ref":"#/components/schemas/Task"}},"events":{"type":"array","items":{"$ref":"#/components/schemas/MeetingEvent"}}},"required":["id","type","organization","name","active","status","created"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]},"EntityAssignee":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"entityType":{"type":"string"}},"required":["entityId","entityType"]},"Note":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"note":{"type":"string"},"author":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"}}},"Task":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"assignees":{"type":"array","items":{"$ref":"#/components/schemas/EntityAssignee"}},"organization":{"type":"string","format":"uuid"},"description":{"type":"string"},"dueDate":{"type":"string","format":"date"},"connectedTo":{"$ref":"#/components/schemas/EntityInfo"},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"order":{"type":"integer"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","name","active","status","created","organization","order"]},"EntityInfo":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"},"organization":{"type":"string","format":"uuid"}},"required":["entityId","type"]},"MeetingEvent":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"meetingId":{"type":"string","format":"uuid"},"startTime":{"type":"string","format":"date-time"},"endTime":{"type":"string","format":"date-time"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"tasks":{"type":"array","items":{"$ref":"#/components/schemas/Task"}}},"required":["id","meetingId","name","active","status","created","startTime"]}}},"paths":{"/api/v1/meeting/{meetingId}/participant/{entityIdOrEmail}":{"delete":{"tags":["Meetings"],"summary":"Remove participant from meeting","parameters":[{"name":"meetingId","in":"path","required":true,"schema":{"type":"string"}},{"name":"entityIdOrEmail","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Meeting"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## POST /api/v1/meeting/{meetingId}/event

> Create meeting event

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Meetings","description":"The Meetings API provides a powerful mechanism to capture notes, provide talking points or track action items from both 1:1 and group meetings. It does not provide functionality to record or host meetings."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"MeetingEventRequest":{"type":"object","properties":{"name":{"type":"string"},"startTime":{"type":"string","format":"date-time"},"endTime":{"type":"string","format":"date-time"}},"required":["name","startTime"]},"Meeting":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string"},"recurring":{"type":"boolean"},"organization":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}},"assignees":{"type":"array","items":{"$ref":"#/components/schemas/EntityAssignee"}},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"tasks":{"type":"array","items":{"$ref":"#/components/schemas/Task"}},"events":{"type":"array","items":{"$ref":"#/components/schemas/MeetingEvent"}}},"required":["id","type","organization","name","active","status","created"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]},"EntityAssignee":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"entityType":{"type":"string"}},"required":["entityId","entityType"]},"Note":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"note":{"type":"string"},"author":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"}}},"Task":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"assignees":{"type":"array","items":{"$ref":"#/components/schemas/EntityAssignee"}},"organization":{"type":"string","format":"uuid"},"description":{"type":"string"},"dueDate":{"type":"string","format":"date"},"connectedTo":{"$ref":"#/components/schemas/EntityInfo"},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"order":{"type":"integer"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","name","active","status","created","organization","order"]},"EntityInfo":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"},"organization":{"type":"string","format":"uuid"}},"required":["entityId","type"]},"MeetingEvent":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"meetingId":{"type":"string","format":"uuid"},"startTime":{"type":"string","format":"date-time"},"endTime":{"type":"string","format":"date-time"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"tasks":{"type":"array","items":{"$ref":"#/components/schemas/Task"}}},"required":["id","meetingId","name","active","status","created","startTime"]}}},"paths":{"/api/v1/meeting/{meetingId}/event":{"post":{"tags":["Meetings"],"summary":"Create meeting event","parameters":[{"name":"meetingId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeetingEventRequest"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Meeting"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## DELETE /api/v1/meeting/{meetingId}/event/{eventId}

> Delete meeting event

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Meetings","description":"The Meetings API provides a powerful mechanism to capture notes, provide talking points or track action items from both 1:1 and group meetings. It does not provide functionality to record or host meetings."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"Meeting":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string"},"recurring":{"type":"boolean"},"organization":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}},"assignees":{"type":"array","items":{"$ref":"#/components/schemas/EntityAssignee"}},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"tasks":{"type":"array","items":{"$ref":"#/components/schemas/Task"}},"events":{"type":"array","items":{"$ref":"#/components/schemas/MeetingEvent"}}},"required":["id","type","organization","name","active","status","created"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]},"EntityAssignee":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"entityType":{"type":"string"}},"required":["entityId","entityType"]},"Note":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"note":{"type":"string"},"author":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"}}},"Task":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"assignees":{"type":"array","items":{"$ref":"#/components/schemas/EntityAssignee"}},"organization":{"type":"string","format":"uuid"},"description":{"type":"string"},"dueDate":{"type":"string","format":"date"},"connectedTo":{"$ref":"#/components/schemas/EntityInfo"},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"order":{"type":"integer"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","name","active","status","created","organization","order"]},"EntityInfo":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"},"organization":{"type":"string","format":"uuid"}},"required":["entityId","type"]},"MeetingEvent":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"meetingId":{"type":"string","format":"uuid"},"startTime":{"type":"string","format":"date-time"},"endTime":{"type":"string","format":"date-time"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"tasks":{"type":"array","items":{"$ref":"#/components/schemas/Task"}}},"required":["id","meetingId","name","active","status","created","startTime"]}}},"paths":{"/api/v1/meeting/{meetingId}/event/{eventId}":{"delete":{"tags":["Meetings"],"summary":"Delete meeting event","parameters":[{"name":"meetingId","in":"path","required":true,"schema":{"type":"string"}},{"name":"eventId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Meeting"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## PATCH /api/v1/meeting/{meetingId}/event/{eventId}

> Update meeting event

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Meetings","description":"The Meetings API provides a powerful mechanism to capture notes, provide talking points or track action items from both 1:1 and group meetings. It does not provide functionality to record or host meetings."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"MeetingEventRequest":{"type":"object","properties":{"name":{"type":"string"},"startTime":{"type":"string","format":"date-time"},"endTime":{"type":"string","format":"date-time"}},"required":["name","startTime"]},"Meeting":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string"},"recurring":{"type":"boolean"},"organization":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}},"assignees":{"type":"array","items":{"$ref":"#/components/schemas/EntityAssignee"}},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"tasks":{"type":"array","items":{"$ref":"#/components/schemas/Task"}},"events":{"type":"array","items":{"$ref":"#/components/schemas/MeetingEvent"}}},"required":["id","type","organization","name","active","status","created"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]},"EntityAssignee":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"entityType":{"type":"string"}},"required":["entityId","entityType"]},"Note":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"note":{"type":"string"},"author":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"}}},"Task":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"assignees":{"type":"array","items":{"$ref":"#/components/schemas/EntityAssignee"}},"organization":{"type":"string","format":"uuid"},"description":{"type":"string"},"dueDate":{"type":"string","format":"date"},"connectedTo":{"$ref":"#/components/schemas/EntityInfo"},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"order":{"type":"integer"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","name","active","status","created","organization","order"]},"EntityInfo":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"},"organization":{"type":"string","format":"uuid"}},"required":["entityId","type"]},"MeetingEvent":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"meetingId":{"type":"string","format":"uuid"},"startTime":{"type":"string","format":"date-time"},"endTime":{"type":"string","format":"date-time"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"tasks":{"type":"array","items":{"$ref":"#/components/schemas/Task"}}},"required":["id","meetingId","name","active","status","created","startTime"]}}},"paths":{"/api/v1/meeting/{meetingId}/event/{eventId}":{"patch":{"tags":["Meetings"],"summary":"Update meeting event","parameters":[{"name":"meetingId","in":"path","required":true,"schema":{"type":"string"}},{"name":"eventId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeetingEventRequest"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Meeting"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```


# IDPs

IDPs (or Individual Development Plans) help managers and employees collaborate on career paths. They support individual action items to help keep everyone on track.

## GET /api/v1/idp

> List IDPs

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"IDPs","description":"IDPs (or Individual Development Plans) help managers and employees collaborate on career paths. They support individual action items to help keep everyone on track."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"Idp":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"organization":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"type":{"type":"string"},"startDate":{"type":"string","format":"date"},"endDate":{"type":"string","format":"date"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"assignees":{"type":"array","items":{"$ref":"#/components/schemas/EntityAssignee"}},"tasks":{"type":"array","items":{"$ref":"#/components/schemas/Task"}},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"sharing":{"$ref":"#/components/schemas/SharingInfo"}},"required":["id","organization","name","active","type","startDate","status","created","sharing"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EntityAssignee":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"entityType":{"type":"string"}},"required":["entityId","entityType"]},"Task":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"assignees":{"type":"array","items":{"$ref":"#/components/schemas/EntityAssignee"}},"organization":{"type":"string","format":"uuid"},"description":{"type":"string"},"dueDate":{"type":"string","format":"date"},"connectedTo":{"$ref":"#/components/schemas/EntityInfo"},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"order":{"type":"integer"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","name","active","status","created","organization","order"]},"EntityInfo":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"},"organization":{"type":"string","format":"uuid"}},"required":["entityId","type"]},"Note":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"note":{"type":"string"},"author":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"}}},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]},"SharingInfo":{"type":"object","properties":{"visibility":{"type":"string"},"ownerId":{"type":"string","format":"uuid"}}}}},"paths":{"/api/v1/idp":{"get":{"tags":["IDPs"],"summary":"List IDPs","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Idp"}}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## POST /api/v1/idp

> Create IDP

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"IDPs","description":"IDPs (or Individual Development Plans) help managers and employees collaborate on career paths. They support individual action items to help keep everyone on track."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"IdpRequest":{"type":"object","properties":{"name":{"type":"string"},"startDate":{"type":"string","format":"date"},"endDate":{"type":"string","format":"date"},"type":{"type":"string"},"visibility":{"type":"string"},"owner":{"type":"string","format":"uuid"}},"required":["name","startDate","type"]},"Idp":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"organization":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"type":{"type":"string"},"startDate":{"type":"string","format":"date"},"endDate":{"type":"string","format":"date"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"assignees":{"type":"array","items":{"$ref":"#/components/schemas/EntityAssignee"}},"tasks":{"type":"array","items":{"$ref":"#/components/schemas/Task"}},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"sharing":{"$ref":"#/components/schemas/SharingInfo"}},"required":["id","organization","name","active","type","startDate","status","created","sharing"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EntityAssignee":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"entityType":{"type":"string"}},"required":["entityId","entityType"]},"Task":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"assignees":{"type":"array","items":{"$ref":"#/components/schemas/EntityAssignee"}},"organization":{"type":"string","format":"uuid"},"description":{"type":"string"},"dueDate":{"type":"string","format":"date"},"connectedTo":{"$ref":"#/components/schemas/EntityInfo"},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"order":{"type":"integer"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","name","active","status","created","organization","order"]},"EntityInfo":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"},"organization":{"type":"string","format":"uuid"}},"required":["entityId","type"]},"Note":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"note":{"type":"string"},"author":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"}}},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]},"SharingInfo":{"type":"object","properties":{"visibility":{"type":"string"},"ownerId":{"type":"string","format":"uuid"}}}}},"paths":{"/api/v1/idp":{"post":{"tags":["IDPs"],"summary":"Create IDP","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdpRequest"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Idp"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## GET /api/v1/idp/{id}

> Get IDP

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"IDPs","description":"IDPs (or Individual Development Plans) help managers and employees collaborate on career paths. They support individual action items to help keep everyone on track."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"Idp":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"organization":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"type":{"type":"string"},"startDate":{"type":"string","format":"date"},"endDate":{"type":"string","format":"date"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"assignees":{"type":"array","items":{"$ref":"#/components/schemas/EntityAssignee"}},"tasks":{"type":"array","items":{"$ref":"#/components/schemas/Task"}},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"sharing":{"$ref":"#/components/schemas/SharingInfo"}},"required":["id","organization","name","active","type","startDate","status","created","sharing"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EntityAssignee":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"entityType":{"type":"string"}},"required":["entityId","entityType"]},"Task":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"assignees":{"type":"array","items":{"$ref":"#/components/schemas/EntityAssignee"}},"organization":{"type":"string","format":"uuid"},"description":{"type":"string"},"dueDate":{"type":"string","format":"date"},"connectedTo":{"$ref":"#/components/schemas/EntityInfo"},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"order":{"type":"integer"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","name","active","status","created","organization","order"]},"EntityInfo":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"},"organization":{"type":"string","format":"uuid"}},"required":["entityId","type"]},"Note":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"note":{"type":"string"},"author":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"}}},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]},"SharingInfo":{"type":"object","properties":{"visibility":{"type":"string"},"ownerId":{"type":"string","format":"uuid"}}}}},"paths":{"/api/v1/idp/{id}":{"get":{"tags":["IDPs"],"summary":"Get IDP","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Idp"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## DELETE /api/v1/idp/{id}

> Delete IDP

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"IDPs","description":"IDPs (or Individual Development Plans) help managers and employees collaborate on career paths. They support individual action items to help keep everyone on track."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}}},"paths":{"/api/v1/idp/{id}":{"delete":{"tags":["IDPs"],"summary":"Delete IDP","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## PATCH /api/v1/idp/{id}

> Update IDP

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"IDPs","description":"IDPs (or Individual Development Plans) help managers and employees collaborate on career paths. They support individual action items to help keep everyone on track."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"IdpRequest":{"type":"object","properties":{"name":{"type":"string"},"startDate":{"type":"string","format":"date"},"endDate":{"type":"string","format":"date"},"type":{"type":"string"},"visibility":{"type":"string"},"owner":{"type":"string","format":"uuid"}},"required":["name","startDate","type"]},"Idp":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"organization":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"type":{"type":"string"},"startDate":{"type":"string","format":"date"},"endDate":{"type":"string","format":"date"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"assignees":{"type":"array","items":{"$ref":"#/components/schemas/EntityAssignee"}},"tasks":{"type":"array","items":{"$ref":"#/components/schemas/Task"}},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"sharing":{"$ref":"#/components/schemas/SharingInfo"}},"required":["id","organization","name","active","type","startDate","status","created","sharing"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EntityAssignee":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"entityType":{"type":"string"}},"required":["entityId","entityType"]},"Task":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"assignees":{"type":"array","items":{"$ref":"#/components/schemas/EntityAssignee"}},"organization":{"type":"string","format":"uuid"},"description":{"type":"string"},"dueDate":{"type":"string","format":"date"},"connectedTo":{"$ref":"#/components/schemas/EntityInfo"},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"order":{"type":"integer"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","name","active","status","created","organization","order"]},"EntityInfo":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"},"organization":{"type":"string","format":"uuid"}},"required":["entityId","type"]},"Note":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"note":{"type":"string"},"author":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"}}},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]},"SharingInfo":{"type":"object","properties":{"visibility":{"type":"string"},"ownerId":{"type":"string","format":"uuid"}}}}},"paths":{"/api/v1/idp/{id}":{"patch":{"tags":["IDPs"],"summary":"Update IDP","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdpRequest"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Idp"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```


# Apps

Apps represent a connection to another system - either external or internal - for example a CRM or HRIS.

## Create a new Application

> Create a new application integration record for the organization.

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Apps","description":"Apps represent a connection to another system - either external or internal - for example a CRM or HRIS."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{},"schemas":{"AppRequest":{"type":"object","description":"Payload to create or replace an Application.","properties":{"type":{"type":"string"},"externalId":{"type":"string"},"internal":{"type":"boolean"},"name":{"type":"string"},"appData":{"type":"object","additionalProperties":{"type":"string"}},"secretData":{"type":"object","additionalProperties":{"type":"string"}}},"required":["type","externalId","internal","name"]},"App":{"type":"object","description":"An Application (integration) record.","properties":{"id":{"type":"string","format":"uuid"},"externalId":{"type":"string"},"internal":{"type":"boolean"},"name":{"type":"string"},"type":{"type":"string"},"active":{"type":"boolean"},"status":{"type":"object","properties":{"current":{"type":"string","enum":["ACTIVE","INACTIVE","DRAFT","COMPLETED","CANCELED","TEST","ARCHIVED","TO_BE_DELETED"]},"changedAt":{"type":"string","format":"date-time","nullable":true},"changedBy":{"type":"string","format":"uuid","nullable":true}}},"created":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid","nullable":true}}},"organization":{"type":"string","format":"uuid"},"secretData":{"type":"object","additionalProperties":{"type":"string"}},"appData":{"type":"object","additionalProperties":{"type":"string"}}},"required":["type"]}}},"paths":{"/api/v1/app":{"post":{"tags":["Apps"],"summary":"Create a new Application","description":"Create a new application integration record for the organization.","operationId":"createApp","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppRequest"}}}},"responses":{"201":{"description":"Application created successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/App"}}}},"400":{"description":"Bad Request – Invalid input."},"401":{"description":"Unauthorized – Missing or invalid JWT."},"403":{"description":"Forbidden – Insufficient permissions."}}}}}}
```

## Get Application

> Retrieve an Application by its ID.

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Apps","description":"Apps represent a connection to another system - either external or internal - for example a CRM or HRIS."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{},"schemas":{"App":{"type":"object","description":"An Application (integration) record.","properties":{"id":{"type":"string","format":"uuid"},"externalId":{"type":"string"},"internal":{"type":"boolean"},"name":{"type":"string"},"type":{"type":"string"},"active":{"type":"boolean"},"status":{"type":"object","properties":{"current":{"type":"string","enum":["ACTIVE","INACTIVE","DRAFT","COMPLETED","CANCELED","TEST","ARCHIVED","TO_BE_DELETED"]},"changedAt":{"type":"string","format":"date-time","nullable":true},"changedBy":{"type":"string","format":"uuid","nullable":true}}},"created":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid","nullable":true}}},"organization":{"type":"string","format":"uuid"},"secretData":{"type":"object","additionalProperties":{"type":"string"}},"appData":{"type":"object","additionalProperties":{"type":"string"}}},"required":["type"]}}},"paths":{"/api/v1/app/{app}":{"get":{"tags":["Apps"],"summary":"Get Application","description":"Retrieve an Application by its ID.","operationId":"getApp","responses":{"200":{"description":"Successful response with Application.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/App"}}}},"401":{"description":"Unauthorized – Missing or invalid JWT."},"403":{"description":"Forbidden – Insufficient permissions."},"404":{"description":"Not Found – No Application with this ID."}}}}}}
```

## Update Application (Partial)

> Update one or more fields of an existing Application.

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Apps","description":"Apps represent a connection to another system - either external or internal - for example a CRM or HRIS."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{},"schemas":{"App":{"type":"object","description":"An Application (integration) record.","properties":{"id":{"type":"string","format":"uuid"},"externalId":{"type":"string"},"internal":{"type":"boolean"},"name":{"type":"string"},"type":{"type":"string"},"active":{"type":"boolean"},"status":{"type":"object","properties":{"current":{"type":"string","enum":["ACTIVE","INACTIVE","DRAFT","COMPLETED","CANCELED","TEST","ARCHIVED","TO_BE_DELETED"]},"changedAt":{"type":"string","format":"date-time","nullable":true},"changedBy":{"type":"string","format":"uuid","nullable":true}}},"created":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid","nullable":true}}},"organization":{"type":"string","format":"uuid"},"secretData":{"type":"object","additionalProperties":{"type":"string"}},"appData":{"type":"object","additionalProperties":{"type":"string"}}},"required":["type"]}}},"paths":{"/api/v1/app/{app}":{"patch":{"tags":["Apps"],"summary":"Update Application (Partial)","description":"Update one or more fields of an existing Application.","operationId":"updateApp","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"type":{"type":"string"},"externalId":{"type":"string"},"internal":{"type":"boolean"},"name":{"type":"string"},"appData":{"type":"object","additionalProperties":{"type":"string"}},"secretData":{"type":"object","additionalProperties":{"type":"string"}}}}}}},"responses":{"200":{"description":"Application updated successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/App"}}}},"400":{"description":"Bad Request – Invalid patch data."},"401":{"description":"Unauthorized – Missing or invalid JWT."},"403":{"description":"Forbidden – Insufficient permissions."},"404":{"description":"Not Found – No Application with this ID."}}}}}}
```

## List Applications by Type

> Get all Applications of a given type for the organization.

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Apps","description":"Apps represent a connection to another system - either external or internal - for example a CRM or HRIS."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{},"schemas":{"App":{"type":"object","description":"An Application (integration) record.","properties":{"id":{"type":"string","format":"uuid"},"externalId":{"type":"string"},"internal":{"type":"boolean"},"name":{"type":"string"},"type":{"type":"string"},"active":{"type":"boolean"},"status":{"type":"object","properties":{"current":{"type":"string","enum":["ACTIVE","INACTIVE","DRAFT","COMPLETED","CANCELED","TEST","ARCHIVED","TO_BE_DELETED"]},"changedAt":{"type":"string","format":"date-time","nullable":true},"changedBy":{"type":"string","format":"uuid","nullable":true}}},"created":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid","nullable":true}}},"organization":{"type":"string","format":"uuid"},"secretData":{"type":"object","additionalProperties":{"type":"string"}},"appData":{"type":"object","additionalProperties":{"type":"string"}}},"required":["type"]}}},"paths":{"/api/v1/app/by-type/{type}":{"get":{"tags":["Apps"],"summary":"List Applications by Type","description":"Get all Applications of a given type for the organization.","operationId":"listAppsByType","responses":{"200":{"description":"A list of Application records of the specified type.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/App"}}}}},"400":{"description":"Bad Request – Missing or invalid type parameter."},"401":{"description":"Unauthorized – Missing or invalid JWT."},"403":{"description":"Forbidden – Insufficient permissions."}}}}}}
```

## Get Application by Type and External ID

> Retrieve an Application by its type and external identifier.

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Apps","description":"Apps represent a connection to another system - either external or internal - for example a CRM or HRIS."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{},"schemas":{"App":{"type":"object","description":"An Application (integration) record.","properties":{"id":{"type":"string","format":"uuid"},"externalId":{"type":"string"},"internal":{"type":"boolean"},"name":{"type":"string"},"type":{"type":"string"},"active":{"type":"boolean"},"status":{"type":"object","properties":{"current":{"type":"string","enum":["ACTIVE","INACTIVE","DRAFT","COMPLETED","CANCELED","TEST","ARCHIVED","TO_BE_DELETED"]},"changedAt":{"type":"string","format":"date-time","nullable":true},"changedBy":{"type":"string","format":"uuid","nullable":true}}},"created":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid","nullable":true}}},"organization":{"type":"string","format":"uuid"},"secretData":{"type":"object","additionalProperties":{"type":"string"}},"appData":{"type":"object","additionalProperties":{"type":"string"}}},"required":["type"]}}},"paths":{"/api/v1/app/by-type-id/{type}/{id}":{"get":{"tags":["Apps"],"summary":"Get Application by Type and External ID","description":"Retrieve an Application by its type and external identifier.","operationId":"getAppByTypeAndId","responses":{"200":{"description":"Application found and returned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/App"}}}},"400":{"description":"Bad Request – Missing type or id parameter."},"401":{"description":"Unauthorized – Missing or invalid JWT."},"403":{"description":"Forbidden – Insufficient permissions."},"404":{"description":"Not Found – No Application with this type and external ID."}}}}}}
```

## List Application Mappings

> List all entity mappings for the specified Application.

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Apps","description":"Apps represent a connection to another system - either external or internal - for example a CRM or HRIS."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{},"schemas":{"EntityAndMapping":{"type":"object","properties":{"entity":{"$ref":"#/components/schemas/EntityInfo"},"mapping":{"$ref":"#/components/schemas/EntityMapping"}},"required":["entity","mapping"]},"EntityInfo":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"},"organization":{"type":"string","format":"uuid"}},"required":["entityId","type"]},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]}}},"paths":{"/api/v1/app/{app}/mappings":{"get":{"tags":["Apps"],"summary":"List Application Mappings","description":"List all entity mappings for the specified Application.","operationId":"listAppMappings","responses":{"200":{"description":"A list of entity mappings for this Application.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EntityAndMapping"}}}}},"401":{"description":"Unauthorized – Missing or invalid JWT."},"403":{"description":"Forbidden – Insufficient permissions."},"404":{"description":"Not Found – Application ID not found."}}}}}}
```


# Tasks (or Assignments)

Tasks can be associated with nearly all Entity objects in the platform, but appear most often on OKRs, Meetings and IDPs.

## POST /api/v1/entity/{entity}/task

> Create task for entity

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Tasks (or Assignments)","description":"Tasks can be associated with nearly all Entity objects in the platform, but appear most often on OKRs, Meetings and IDPs."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"TaskRequest":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"dueDate":{"type":"string","format":"date"},"order":{"type":"integer"},"orderGroup":{"type":"string","format":"uuid"}},"required":["name"]},"Task":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"assignees":{"type":"array","items":{"$ref":"#/components/schemas/EntityAssignee"}},"organization":{"type":"string","format":"uuid"},"description":{"type":"string"},"dueDate":{"type":"string","format":"date"},"connectedTo":{"$ref":"#/components/schemas/EntityInfo"},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"order":{"type":"integer"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","name","active","status","created","organization","order"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EntityAssignee":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"entityType":{"type":"string"}},"required":["entityId","entityType"]},"EntityInfo":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"},"organization":{"type":"string","format":"uuid"}},"required":["entityId","type"]},"Note":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"note":{"type":"string"},"author":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"}}},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]}}},"paths":{"/api/v1/entity/{entity}/task":{"post":{"tags":["Tasks (or Assignments)"],"summary":"Create task for entity","parameters":[{"name":"entity","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskRequest"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Task"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## PATCH /api/v1/entity/{entity}/task/{task}

> Update task for entity

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Tasks (or Assignments)","description":"Tasks can be associated with nearly all Entity objects in the platform, but appear most often on OKRs, Meetings and IDPs."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"TaskRequest":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"dueDate":{"type":"string","format":"date"},"order":{"type":"integer"},"orderGroup":{"type":"string","format":"uuid"}},"required":["name"]},"Task":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"assignees":{"type":"array","items":{"$ref":"#/components/schemas/EntityAssignee"}},"organization":{"type":"string","format":"uuid"},"description":{"type":"string"},"dueDate":{"type":"string","format":"date"},"connectedTo":{"$ref":"#/components/schemas/EntityInfo"},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"order":{"type":"integer"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","name","active","status","created","organization","order"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EntityAssignee":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"entityType":{"type":"string"}},"required":["entityId","entityType"]},"EntityInfo":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"},"organization":{"type":"string","format":"uuid"}},"required":["entityId","type"]},"Note":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"note":{"type":"string"},"author":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"}}},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]}}},"paths":{"/api/v1/entity/{entity}/task/{task}":{"patch":{"tags":["Tasks (or Assignments)"],"summary":"Update task for entity","parameters":[{"name":"entity","in":"path","required":true,"schema":{"type":"string"}},{"name":"task","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskRequest"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Task"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```

## GET /api/v1/task/{task}

> Get task

```json
{"openapi":"3.1.0","info":{"title":"Peoplelogic API","version":"1.0.0"},"tags":[{"name":"Tasks (or Assignments)","description":"Tasks can be associated with nearly all Entity objects in the platform, but appear most often on OKRs, Meetings and IDPs."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"Task":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/StatusInfo"},"created":{"$ref":"#/components/schemas/CreationInfo"},"assignees":{"type":"array","items":{"$ref":"#/components/schemas/EntityAssignee"}},"organization":{"type":"string","format":"uuid"},"description":{"type":"string"},"dueDate":{"type":"string","format":"date"},"connectedTo":{"$ref":"#/components/schemas/EntityInfo"},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"order":{"type":"integer"},"mappings":{"type":"array","items":{"$ref":"#/components/schemas/EntityMapping"}}},"required":["id","name","active","status","created","organization","order"]},"StatusInfo":{"type":"object","properties":{"current":{"type":"string"},"changedAt":{"type":"string","format":"date-time"},"changedBy":{"type":"string","format":"uuid"}},"required":["current"]},"CreationInfo":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["createdAt"]},"EntityAssignee":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"entityType":{"type":"string"}},"required":["entityId","entityType"]},"EntityInfo":{"type":"object","properties":{"entityId":{"type":"string","format":"uuid"},"type":{"type":"string"},"organization":{"type":"string","format":"uuid"}},"required":["entityId","type"]},"Note":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"note":{"type":"string"},"author":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"}}},"EntityMapping":{"type":"object","properties":{"app":{"type":"string","format":"uuid"},"namespace":{"type":"string"},"mappedId":{"type":"string"},"reference":{"type":"string"},"mappingData":{"type":"object","additionalProperties":{"type":"string"}},"mappingSecrets":{"type":"object","additionalProperties":{"type":"string"}}},"required":["app","mappedId","mappingData","mappingSecrets"]}}},"paths":{"/api/v1/task/{task}":{"get":{"tags":["Tasks (or Assignments)"],"summary":"Get task","parameters":[{"name":"task","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Task"}}}},"400":{"description":"Bad Request – invalid request payload."},"401":{"description":"Unauthorized – missing or invalid JWT."},"403":{"description":"Forbidden – insufficient permissions."},"404":{"description":"Not Found – no Entity with that ID."}}}}}}
```


# Agent API

As part of the Agent SDK you can expose your agents through a standard REST API.  The API allows you to get the available agents, start new conversations, chat with your agents and search and view the history of your conversations.

{% hint style="info" %}
If you are deploying multiple teams of agents you'll want to [customize the API path](/guides/getting-started-with-the-talent-agent-sdk/advanced/customizing-your-agent-api-path) for each so that you can reach the teams independently.
{% endhint %}


# Conversations

The Directory API gives you access to Organizations, Accounts, Employees and Groups. Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT.

## GET /api/v1/agent/conversations

> List active conversations for the current user.

```json
{"openapi":"3.0.3","info":{"title":"Peoplelogic Agent API","version":"1.0.0"},"tags":[{"name":"Conversations","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"paths":{"/api/v1/agent/conversations":{"get":{"summary":"List active conversations for the current user.","tags":["Conversations"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Conversation"}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"500":{"$ref":"#/components/responses/InternalServerError"}}}}},"components":{"schemas":{"Conversation":{"type":"object","properties":{"id":{"type":"string","description":"Conversation unique identifier."},"userId":{"type":"string","description":"ID of the user who owns this conversation."},"tenant":{"type":"string","description":"Tenant/workspace identifier to which this conversation belongs."},"timestamp":{"type":"string","format":"date-time","description":"Timestamp when the conversation was created."},"name":{"type":"string","description":"Friendly name of the conversation."}}}},"responses":{"BadRequest":{"description":"Bad request","content":{"application/json":{"schema":{"type":"string"}}}},"InternalServerError":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"string"}}}}}}}
```

## POST /api/v1/agent/conversations/start

> Start a new conversation.

```json
{"openapi":"3.0.3","info":{"title":"Peoplelogic Agent API","version":"1.0.0"},"tags":[{"name":"Conversations","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"paths":{"/api/v1/agent/conversations/start":{"post":{"summary":"Start a new conversation.","tags":["Conversations"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Conversation"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"500":{"$ref":"#/components/responses/InternalServerError"}}}}},"components":{"schemas":{"Conversation":{"type":"object","properties":{"id":{"type":"string","description":"Conversation unique identifier."},"userId":{"type":"string","description":"ID of the user who owns this conversation."},"tenant":{"type":"string","description":"Tenant/workspace identifier to which this conversation belongs."},"timestamp":{"type":"string","format":"date-time","description":"Timestamp when the conversation was created."},"name":{"type":"string","description":"Friendly name of the conversation."}}}},"responses":{"BadRequest":{"description":"Bad request","content":{"application/json":{"schema":{"type":"string"}}}},"InternalServerError":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"string"}}}}}}}
```

## PUT /api/v1/agent/conversations/{id}

> Update a conversation's details.

```json
{"openapi":"3.0.3","info":{"title":"Peoplelogic Agent API","version":"1.0.0"},"tags":[{"name":"Conversations","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"paths":{"/api/v1/agent/conversations/{id}":{"put":{"summary":"Update a conversation's details.","tags":["Conversations"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Conversation ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Conversation"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Conversation"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalServerError"}}}}},"components":{"schemas":{"Conversation":{"type":"object","properties":{"id":{"type":"string","description":"Conversation unique identifier."},"userId":{"type":"string","description":"ID of the user who owns this conversation."},"tenant":{"type":"string","description":"Tenant/workspace identifier to which this conversation belongs."},"timestamp":{"type":"string","format":"date-time","description":"Timestamp when the conversation was created."},"name":{"type":"string","description":"Friendly name of the conversation."}}}},"responses":{"BadRequest":{"description":"Bad request","content":{"application/json":{"schema":{"type":"string"}}}},"NotFound":{"description":"Not Found","content":{"application/json":{"schema":{"type":"string"}}}},"InternalServerError":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"string"}}}}}}}
```

## DELETE /api/v1/agent/conversations/{id}

> Delete a conversation.

```json
{"openapi":"3.0.3","info":{"title":"Peoplelogic Agent API","version":"1.0.0"},"tags":[{"name":"Conversations","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"paths":{"/api/v1/agent/conversations/{id}":{"delete":{"summary":"Delete a conversation.","tags":["Conversations"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Conversation ID"}],"responses":{"200":{"description":"Success (conversation deleted)"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalServerError"}}}}},"components":{"responses":{"Unauthorized":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"string"}}}},"NotFound":{"description":"Not Found","content":{"application/json":{"schema":{"type":"string"}}}},"InternalServerError":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"string"}}}}}}}
```

## Get agent task assignments (follow-up).

> Retrieve the list of tasks assigned by the agent for the user's last question. Requires an existing conversation (conversationId must be provided).

```json
{"openapi":"3.0.3","info":{"title":"Peoplelogic Agent API","version":"1.0.0"},"tags":[{"name":"Conversations","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"paths":{"/api/v1/agent/assign":{"post":{"summary":"Get agent task assignments (follow-up).","tags":["Conversations"],"description":"Retrieve the list of tasks assigned by the agent for the user's last question. Requires an existing conversation (conversationId must be provided).","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BaseAssignmentHolder"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"500":{"$ref":"#/components/responses/InternalServerError"}}}}},"components":{"schemas":{"UserRequest":{"type":"object","properties":{"question":{"type":"string","description":"User's question or message."},"maxResults":{"type":"integer","description":"Max number of results or steps (defaults to 5)."},"additionalInstructions":{"type":"string","description":"Additional instructions or context for the agent."},"conversationId":{"type":"string","description":"ID of an existing conversation (for follow-ups; omit for new questions)."},"since":{"type":"string","format":"date-time","description":"If provided, get history messages since this timestamp (used in history request)."}}},"BaseAssignmentHolder":{"type":"object","properties":{"response":{"type":"string","description":"Agent's response summary or prompt to the user (e.g., asking for confirmation)."},"needsConfirmation":{"type":"boolean","description":"True if the agent is awaiting user confirmation or input to proceed."},"newWorkflow":{"type":"boolean","description":"True if the agent is proposing a new scheduled workflow."},"scheduleFrequency":{"$ref":"#/components/schemas/WorkflowScheduleFrequency"},"hourOfWorkflow":{"type":"integer","description":"Hour of day (0-23) for scheduled workflow execution (if applicable)."},"dayOfWorkflow":{"type":"integer","description":"Day of week or month for scheduled workflow (if applicable)."},"minuteOfWorkflow":{"type":"integer","description":"Minute of hour for scheduled workflow (if applicable)."},"timeZone":{"type":"string","description":"Time zone identifier for the scheduled workflow (if applicable)."},"agents":{"type":"array","items":{"$ref":"#/components/schemas/BaseAssignmentResponse"},"description":"List of assigned tasks (agents) to be executed."},"subscriptionActive":{"type":"boolean","description":"Indicates if the user's subscription is active (true) or if execution is limited due to subscription issues."},"notificationChannel":{"$ref":"#/components/schemas/CompletionNotificationChannel"},"notificationTo":{"type":"string","description":"Target identifier for completion notification (e.g., email address or Slack channel, if provided)."},"userId":{"type":"string","description":"Identifier of the user for whom the tasks are assigned."}}},"WorkflowScheduleFrequency":{"type":"string","description":"Frequency for scheduled workflow execution.","enum":["DAILY","WEEKDAY","MONTHLY","WEEKLY","QUARTERLY","YEARLY","CUSTOM","ONCE","NONE","INVALID"]},"BaseAssignmentResponse":{"type":"object","properties":{"agent":{"$ref":"#/components/schemas/AgentProfile"},"specificTask":{"type":"string","description":"Specific action that this task should perform."},"step":{"type":"integer","description":"Zero-based index of this task in the sequence."},"dependsOn":{"type":"integer","description":"Index of the task this one depends on (-1 if none)."},"workflowAssignment":{"type":"boolean","description":"True if this task is the top-level workflow being executed, false otherwise."},"tasksDependingOnThis":{"type":"array","items":{"$ref":"#/components/schemas/BaseAssignmentResponse"},"description":"Tasks that depend on this task."}}},"AgentProfile":{"type":"object","properties":{"name":{"type":"string","description":"Agent name."},"persona":{"type":"string","description":"Short description of the agent's role/persona."},"avatar":{"type":"string","description":"URL or identifier for agent's avatar image."},"bio":{"type":"string","description":"Full biography of the agent."},"title":{"type":"string","description":"Agent title or designation."},"shortBio":{"type":"string","description":"Short bio snippet for quick reference."},"coordinator":{"type":"boolean","description":"Whether this agent is a coordinator (primary agent)."},"beanName":{"type":"string","description":"Internal bean name of the agent (context identifier)."}}},"CompletionNotificationChannel":{"type":"string","description":"Channel for completion notification.","enum":["NONE","EMAIL","SLACK","IMMEDIATE"]}},"responses":{"BadRequest":{"description":"Bad request","content":{"application/json":{"schema":{"type":"string"}}}},"InternalServerError":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"string"}}}}}}}
```

## Ask a question (start a new conversation).

> Submit a question to the Peoplelogic agent. Do not include a conversationId (a new conversation will be started).

```json
{"openapi":"3.0.3","info":{"title":"Peoplelogic Agent API","version":"1.0.0"},"tags":[{"name":"Conversations","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"paths":{"/api/v1/agent/ask":{"post":{"summary":"Ask a question (start a new conversation).","tags":["Conversations"],"description":"Submit a question to the Peoplelogic agent. Do not include a conversationId (a new conversation will be started).","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"500":{"$ref":"#/components/responses/InternalServerError"}}}}},"components":{"schemas":{"UserRequest":{"type":"object","properties":{"question":{"type":"string","description":"User's question or message."},"maxResults":{"type":"integer","description":"Max number of results or steps (defaults to 5)."},"additionalInstructions":{"type":"string","description":"Additional instructions or context for the agent."},"conversationId":{"type":"string","description":"ID of an existing conversation (for follow-ups; omit for new questions)."},"since":{"type":"string","format":"date-time","description":"If provided, get history messages since this timestamp (used in history request)."}}},"AgentResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"Whether the request succeeded."},"agent":{"$ref":"#/components/schemas/AgentProfile"},"reply":{"type":"string","description":"The agent's response message."},"sources":{"type":"array","items":{"$ref":"#/components/schemas/ContentSource"},"description":"Content sources (e.g., documents or URLs) cited in the response."},"confirming":{"type":"boolean","description":"True if the agent is asking for confirmation from the user."},"subtasks":{"type":"array","items":{"$ref":"#/components/schemas/AgentResponse"},"description":"Subtasks or follow-up responses (if the agent's response is composed of multiple parts)."},"conversation":{"type":"string","description":"Conversation ID this response is associated with (if any)."}},"required":["success","agent","reply"]},"AgentProfile":{"type":"object","properties":{"name":{"type":"string","description":"Agent name."},"persona":{"type":"string","description":"Short description of the agent's role/persona."},"avatar":{"type":"string","description":"URL or identifier for agent's avatar image."},"bio":{"type":"string","description":"Full biography of the agent."},"title":{"type":"string","description":"Agent title or designation."},"shortBio":{"type":"string","description":"Short bio snippet for quick reference."},"coordinator":{"type":"boolean","description":"Whether this agent is a coordinator (primary agent)."},"beanName":{"type":"string","description":"Internal bean name of the agent (context identifier)."}}},"ContentSource":{"type":"object","properties":{"name":{"type":"string","description":"Name or title of the content source."},"type":{"type":"string","description":"Type of content (e.g., \"document\", \"url\")."},"url":{"type":"string","format":"uri","description":"URL of the content source if applicable."}}}},"responses":{"BadRequest":{"description":"Bad request","content":{"application/json":{"schema":{"type":"string"}}}},"InternalServerError":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"string"}}}}}}}
```

## Send a reply in a conversation.

> Send a follow-up message or confirmation in an existing conversation. This is typically used to confirm task execution or ask a clarifying question, using the conversationId from a previous response.

```json
{"openapi":"3.0.3","info":{"title":"Peoplelogic Agent API","version":"1.0.0"},"tags":[{"name":"Conversations","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"paths":{"/api/v1/agent/reply":{"post":{"summary":"Send a reply in a conversation.","tags":["Conversations"],"description":"Send a follow-up message or confirmation in an existing conversation. This is typically used to confirm task execution or ask a clarifying question, using the conversationId from a previous response.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"500":{"$ref":"#/components/responses/InternalServerError"}}}}},"components":{"schemas":{"UserRequest":{"type":"object","properties":{"question":{"type":"string","description":"User's question or message."},"maxResults":{"type":"integer","description":"Max number of results or steps (defaults to 5)."},"additionalInstructions":{"type":"string","description":"Additional instructions or context for the agent."},"conversationId":{"type":"string","description":"ID of an existing conversation (for follow-ups; omit for new questions)."},"since":{"type":"string","format":"date-time","description":"If provided, get history messages since this timestamp (used in history request)."}}},"AgentResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"Whether the request succeeded."},"agent":{"$ref":"#/components/schemas/AgentProfile"},"reply":{"type":"string","description":"The agent's response message."},"sources":{"type":"array","items":{"$ref":"#/components/schemas/ContentSource"},"description":"Content sources (e.g., documents or URLs) cited in the response."},"confirming":{"type":"boolean","description":"True if the agent is asking for confirmation from the user."},"subtasks":{"type":"array","items":{"$ref":"#/components/schemas/AgentResponse"},"description":"Subtasks or follow-up responses (if the agent's response is composed of multiple parts)."},"conversation":{"type":"string","description":"Conversation ID this response is associated with (if any)."}},"required":["success","agent","reply"]},"AgentProfile":{"type":"object","properties":{"name":{"type":"string","description":"Agent name."},"persona":{"type":"string","description":"Short description of the agent's role/persona."},"avatar":{"type":"string","description":"URL or identifier for agent's avatar image."},"bio":{"type":"string","description":"Full biography of the agent."},"title":{"type":"string","description":"Agent title or designation."},"shortBio":{"type":"string","description":"Short bio snippet for quick reference."},"coordinator":{"type":"boolean","description":"Whether this agent is a coordinator (primary agent)."},"beanName":{"type":"string","description":"Internal bean name of the agent (context identifier)."}}},"ContentSource":{"type":"object","properties":{"name":{"type":"string","description":"Name or title of the content source."},"type":{"type":"string","description":"Type of content (e.g., \"document\", \"url\")."},"url":{"type":"string","format":"uri","description":"URL of the content source if applicable."}}}},"responses":{"BadRequest":{"description":"Bad request","content":{"application/json":{"schema":{"type":"string"}}}},"InternalServerError":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"string"}}}}}}}
```

## POST /api/v1/agent/add-file-knowledge

> Upload a file to the knowledge base (Admin only).

```json
{"openapi":"3.0.3","info":{"title":"Peoplelogic Agent API","version":"1.0.0"},"tags":[{"name":"Conversations","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"paths":{"/api/v1/agent/add-file-knowledge":{"post":{"summary":"Upload a file to the knowledge base (Admin only).","tags":["Conversations"],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalServerError"}}}}},"components":{"schemas":{"AgentResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"Whether the request succeeded."},"agent":{"$ref":"#/components/schemas/AgentProfile"},"reply":{"type":"string","description":"The agent's response message."},"sources":{"type":"array","items":{"$ref":"#/components/schemas/ContentSource"},"description":"Content sources (e.g., documents or URLs) cited in the response."},"confirming":{"type":"boolean","description":"True if the agent is asking for confirmation from the user."},"subtasks":{"type":"array","items":{"$ref":"#/components/schemas/AgentResponse"},"description":"Subtasks or follow-up responses (if the agent's response is composed of multiple parts)."},"conversation":{"type":"string","description":"Conversation ID this response is associated with (if any)."}},"required":["success","agent","reply"]},"AgentProfile":{"type":"object","properties":{"name":{"type":"string","description":"Agent name."},"persona":{"type":"string","description":"Short description of the agent's role/persona."},"avatar":{"type":"string","description":"URL or identifier for agent's avatar image."},"bio":{"type":"string","description":"Full biography of the agent."},"title":{"type":"string","description":"Agent title or designation."},"shortBio":{"type":"string","description":"Short bio snippet for quick reference."},"coordinator":{"type":"boolean","description":"Whether this agent is a coordinator (primary agent)."},"beanName":{"type":"string","description":"Internal bean name of the agent (context identifier)."}}},"ContentSource":{"type":"object","properties":{"name":{"type":"string","description":"Name or title of the content source."},"type":{"type":"string","description":"Type of content (e.g., \"document\", \"url\")."},"url":{"type":"string","format":"uri","description":"URL of the content source if applicable."}}}},"responses":{"NotFound":{"description":"Not Found","content":{"application/json":{"schema":{"type":"string"}}}},"InternalServerError":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"string"}}}}}}}
```

## POST /api/v1/agent/add-url-knowledge

> Add a URL to the knowledge base (Admin only).

```json
{"openapi":"3.0.3","info":{"title":"Peoplelogic Agent API","version":"1.0.0"},"tags":[{"name":"Conversations","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"paths":{"/api/v1/agent/add-url-knowledge":{"post":{"summary":"Add a URL to the knowledge base (Admin only).","tags":["Conversations"],"requestBody":{"required":true,"content":{"text/plain":{"schema":{"type":"string","format":"uri"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalServerError"}}}}},"components":{"schemas":{"AgentResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"Whether the request succeeded."},"agent":{"$ref":"#/components/schemas/AgentProfile"},"reply":{"type":"string","description":"The agent's response message."},"sources":{"type":"array","items":{"$ref":"#/components/schemas/ContentSource"},"description":"Content sources (e.g., documents or URLs) cited in the response."},"confirming":{"type":"boolean","description":"True if the agent is asking for confirmation from the user."},"subtasks":{"type":"array","items":{"$ref":"#/components/schemas/AgentResponse"},"description":"Subtasks or follow-up responses (if the agent's response is composed of multiple parts)."},"conversation":{"type":"string","description":"Conversation ID this response is associated with (if any)."}},"required":["success","agent","reply"]},"AgentProfile":{"type":"object","properties":{"name":{"type":"string","description":"Agent name."},"persona":{"type":"string","description":"Short description of the agent's role/persona."},"avatar":{"type":"string","description":"URL or identifier for agent's avatar image."},"bio":{"type":"string","description":"Full biography of the agent."},"title":{"type":"string","description":"Agent title or designation."},"shortBio":{"type":"string","description":"Short bio snippet for quick reference."},"coordinator":{"type":"boolean","description":"Whether this agent is a coordinator (primary agent)."},"beanName":{"type":"string","description":"Internal bean name of the agent (context identifier)."}}},"ContentSource":{"type":"object","properties":{"name":{"type":"string","description":"Name or title of the content source."},"type":{"type":"string","description":"Type of content (e.g., \"document\", \"url\")."},"url":{"type":"string","format":"uri","description":"URL of the content source if applicable."}}}},"responses":{"NotFound":{"description":"Not Found","content":{"application/json":{"schema":{"type":"string"}}}},"InternalServerError":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"string"}}}}}}}
```


# History

The Directory API gives you access to Organizations, Accounts, Employees and Groups. Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT.

## POST /api/v1/agent/search

> Search conversation history.

```json
{"openapi":"3.0.3","info":{"title":"Peoplelogic Agent API","version":"1.0.0"},"tags":[{"name":"History","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"paths":{"/api/v1/agent/search":{"post":{"summary":"Search conversation history.","tags":["History"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SearchResult"}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalServerError"}}}}},"components":{"schemas":{"SearchRequest":{"type":"object","properties":{"query":{"type":"string","description":"Search query string."},"page":{"type":"integer","description":"Page number (0-based) for paginated results."},"count":{"type":"integer","description":"Number of results per page."}},"required":["query"]},"SearchResult":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the search result (message or conversation ID)."},"conversationId":{"type":"string","description":"ID of the conversation associated with this result."},"result":{"type":"string","description":"Text snippet or summary of the result."},"timestamp":{"type":"string","format":"date-time","description":"Timestamp of the message or conversation."},"type":{"type":"string","description":"Result type (e.g., \"conversation\" or \"message\")."}}}},"responses":{"BadRequest":{"description":"Bad request","content":{"application/json":{"schema":{"type":"string"}}}},"NotFound":{"description":"Not Found","content":{"application/json":{"schema":{"type":"string"}}}},"InternalServerError":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"string"}}}}}}}
```

## Retrieve conversation history.

> Get all messages in a conversation, optionally those after a specific time.

```json
{"openapi":"3.0.3","info":{"title":"Peoplelogic Agent API","version":"1.0.0"},"tags":[{"name":"History","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"paths":{"/api/v1/agent/history":{"post":{"summary":"Retrieve conversation history.","tags":["History"],"description":"Get all messages in a conversation, optionally those after a specific time.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AgentHistory"}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalServerError"}}}}},"components":{"schemas":{"UserRequest":{"type":"object","properties":{"question":{"type":"string","description":"User's question or message."},"maxResults":{"type":"integer","description":"Max number of results or steps (defaults to 5)."},"additionalInstructions":{"type":"string","description":"Additional instructions or context for the agent."},"conversationId":{"type":"string","description":"ID of an existing conversation (for follow-ups; omit for new questions)."},"since":{"type":"string","format":"date-time","description":"If provided, get history messages since this timestamp (used in history request)."}}},"AgentHistory":{"type":"object","properties":{"tenant":{"type":"string","description":"Tenant/workspace of the user."},"userId":{"type":"string","description":"User ID who initiated or is associated with the message."},"agent":{"type":"string","description":"Name of the agent that produced the response (empty for user messages)."},"messageType":{"type":"string","description":"Type of message (e.g., \"user_request\" or \"agent_response\")."},"message":{"type":"string","description":"Message content."},"tokenUsage":{"type":"integer","description":"Number of language model tokens used for this message (if applicable)."},"timeSpent":{"type":"integer","description":"Time spent (in milliseconds) processing this message."},"conversationId":{"type":"string","description":"ID of the conversation this message belongs to."},"timestamp":{"type":"string","format":"date-time","description":"Timestamp of the message."},"sources":{"type":"array","items":{"$ref":"#/components/schemas/ContentSource"},"description":"List of content sources referenced in this message (if any)."}}},"ContentSource":{"type":"object","properties":{"name":{"type":"string","description":"Name or title of the content source."},"type":{"type":"string","description":"Type of content (e.g., \"document\", \"url\")."},"url":{"type":"string","format":"uri","description":"URL of the content source if applicable."}}}},"responses":{"BadRequest":{"description":"Bad request","content":{"application/json":{"schema":{"type":"string"}}}},"NotFound":{"description":"Not Found","content":{"application/json":{"schema":{"type":"string"}}}},"InternalServerError":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"string"}}}}}}}
```


# Common

The Directory API gives you access to Organizations, Accounts, Employees and Groups. Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT.

## GET /api/v1/agent/profiles

> List all active agent profiles.

```json
{"openapi":"3.0.3","info":{"title":"Peoplelogic Agent API","version":"1.0.0"},"tags":[{"name":"Common","description":"The Directory API gives you access to Organizations, Accounts, Employees and Groups.  Every Entity within the subsequent API calls must have an Organization attached and API calls must be made with a User specific JWT."}],"servers":[{"url":"https://api.peoplelogic.dev"}],"paths":{"/api/v1/agent/profiles":{"get":{"summary":"List all active agent profiles.","tags":["Common"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AgentProfile"}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"500":{"$ref":"#/components/responses/InternalServerError"}}}}},"components":{"schemas":{"AgentProfile":{"type":"object","properties":{"name":{"type":"string","description":"Agent name."},"persona":{"type":"string","description":"Short description of the agent's role/persona."},"avatar":{"type":"string","description":"URL or identifier for agent's avatar image."},"bio":{"type":"string","description":"Full biography of the agent."},"title":{"type":"string","description":"Agent title or designation."},"shortBio":{"type":"string","description":"Short bio snippet for quick reference."},"coordinator":{"type":"boolean","description":"Whether this agent is a coordinator (primary agent)."},"beanName":{"type":"string","description":"Internal bean name of the agent (context identifier)."}}}},"responses":{"BadRequest":{"description":"Bad request","content":{"application/json":{"schema":{"type":"string"}}}},"InternalServerError":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"string"}}}}}}}
```


# Building a simple coaching agent

Leverage your data and the Talent Agent SDK to build an employee coaching agent.

One of the most common requests our friends in talent management get asked to do is to help coach someone through a difficult conversation or to upskill as a leader.  While this is often one of the most enjoyable parts of the job, it can be challenging to provide the sort of coaching a manager or employee needs without the full set of data.  Additionally, it can be helpful to roleplay some of the conversation beforehand to ensure that they have all the talking points down. &#x20;

Fortunately, this is where the Talent Agent SDK and the intersection of HR and IT really shines.  Let's take a look at building a quick coaching agent in Slack that helps solve this problem.

### Prerequisites

We're going to let the agent SDK do most of the heavy lifting here and pull in the HRBP agent and the HR Analyst agent to help us out.  For simplicity, we'll also rely on the Slack integration built into the SDK and this tutorial presumes you already have that setup.

1. First clone the Agent SDK starter from <https://github.com/peoplelogic/agent-sdk-starter>
2. Then, let's enable the HRBP and the HR Analyst within `src/main/resources/application.properties`:

```
peoplelogic.agent.HRBusinessPartnerAgent.enabled=true
peoplelogic.agent.HRAnalystAgent.enabled=true
```

### Setting up your coaching tool

To add the coaching functionality to the HRBP agent, we need to create a new Tool.  If you recall from the [Getting Started guide](/guides/getting-started-with-the-talent-agent-sdk/giving-your-agents-tools/creating-your-own-tools), we need to do this through a new `@PeoplelogicTool` component. We're also going to wire in several of the other SDK components that we'll need to work with.

```java
@PeoplelogicTools("hrbp-coaching-tools")
public class HRBPCoachingTools {
    @Autowired
    PersonalContentRetriever personalContentRetriever;

    @Autowired
    @Qualifier("apmContentRetriever")
    ContentRetriever apmContentRetriever;

    @Autowired
    CustomerKnowledgeContentRetriever customerKnowledgeContentRetriever;

    @Autowired
    ChatMemoryProvider chatMemoryProvider;

    @Autowired
    ChatModel chatLanguageModel;

    @Autowired
    HRAnalystAgent analyst;

    HRBusinessPartnerAgent agentWithFiles;
}
```

So far, so good - we've brought in components that help us fetch data from the organization and also uploaded through the conversation and we've brought in some core components like the chat model and the memory so we can setup some overrides of our agents.  But what good is a coaching agent, without the coaching prompt! Let's add the new prompt just below the `agentWithFiles` definition:

```
private final String COACHING_CONVERSATION_SEGMENT = "You are providing structured coaching guidance for managers based on company-provided training materials, performance documentation, values, employee history, and engagement insights. " +
            "Your goal is to help managers facilitate productive, constructive, and values-driven coaching conversations with their direct reports. " +
            "Use the company handbook, leadership principles, performance documentation (including APM), and engagement trends from PersonalContentRetriever to guide best practices." +
            "Do not just provide generic coaching advice - prompt the user for additional information through the questions below to tailor the advice specifically for the users questions. " +
            "\n\nHere are the steps to take and the details to provide:\n" +

            "**1) Understand the Context:**\\n" +
            "   * Identify the employee’s role, responsibilities, and recent performance trends.\\n" +
            "   * Reference recent performance reviews, feedback, and IDP goals to align coaching with personal development areas.\\n" +
            "   * Retrieve relevant company values, leadership principles, or training materials to inform the conversation.\\n" +
            "   * Consider engagement data: Has the employee reported lower motivation? Are they flagged for burnout risk? Have survey responses indicated disengagement or stress?\\n" +
            "   * Review prior coaching conversations for continuity.\\n" +

            "\\n **2) Prepare a Coaching Plan:**\\n" +
            "   * Summarize key strengths and recent achievements of the employee.\\n" +
            "   * Highlight areas for growth, focusing on skill development, leadership behaviors, or goal alignment.\\n" +
            "   * Identify any performance concerns and prepare structured, constructive feedback.\\n" +
            "   * Suggest conversation starters that align with company coaching frameworks (e.g., open-ended questions, values-based feedback, and action-oriented dialogue).\\n" +

            "\\n **3) Incorporate Engagement Insights:**\\n" +
            "   * If recent engagement data is available, summarize key findings.\\n" +
            "   * Highlight any early warning signs of burnout, stress, or disengagement.\\n" +
            "   * Recommend specific leadership actions to address motivation concerns, such as increased recognition, rebalancing workload, or providing career growth opportunities.\\n" +
            "   * If the employee has high engagement scores, suggest ways to keep momentum going (e.g., stretch assignments, mentorship roles).\\n" +

            "\\n **3) Handling Specific Coaching Scenarios:**\\n" +

            "   **Scenario: Coaching an Underperforming Employee**\\n" +
            "   * Identify the specific performance gaps based on reviews, OKRs, and manager feedback.\\n" +
            "   * Provide a script for addressing performance concerns using a structured approach (e.g., SBI: Situation-Behavior-Impact).\\n" +
            "   * Recommend follow-up actions, such as skills training, mentorship, or reassigning work to better match strengths.\\n" +

            "   **Scenario: High-Potential Coaching & Career Growth**\\n" +
            "   * Recognize recent achievements and set expectations for leadership development.\\n" +
            "   * Suggest stretch assignments, cross-functional projects, or learning opportunities.\\n" +
            "   * Align growth plans with company goals to maximize impact.\\n" +

            "   **Scenario: Addressing Low Engagement or Burnout Risk**\\n" +
            "   * Review recent engagement data to understand concerns (e.g., workload, manager relationships, career stagnation).\\n" +
            "   * Provide conversation starters to uncover underlying challenges.\\n" +
            "   * Suggest leadership interventions (e.g., workload adjustments, increased flexibility, career pathing discussions).\\n" +

            "   **Scenario: Giving Feedback Based on Company Values**\\n" +
            "   * Retrieve company values and leadership principles from the PersonalContentRetriever.\\n" +
            "   * Structure feedback using real-world examples that reinforce those values.\\n" +
            "   * Recommend actions that align with cultural expectations (e.g., collaboration, innovation, customer focus).\\n" +

            "\\n **4) Set Next Steps:**\\n" +
            "   * Summarize key takeaways from the conversation.\\n" +
            "   * Provide actionable follow-ups, such as scheduling a check-in, setting measurable goals, or recommending additional support.\\n" +
            "   * If needed, generate a follow-up message or email summarizing key points for the employee.\\n" +

            "\\n **5) Generate Additional Prompts for the User:**\\n" +
            "   * 'How can I coach Alice on improving leadership skills based on her performance review?'\\n" +
            "   * 'What feedback should I give Bob in our 1:1 based on company values?'\\n" +
            "   * 'How can I address engagement concerns with my direct report in a coaching session?'\\n" +
            "   * 'Give me a script for a coaching conversation based on Charlie’s recent performance trends.'\\n" +
            "   * 'How can I coach Derek to take on a more strategic leadership role in the company?'\\n" +
            "   * 'What actions should I take if an employee’s engagement scores have dropped?'";
```

Quite the prompt, but no-one ever said coaching was easy!  With that out of the way we just need to adjust the HRBP agent a bit.  You can see that we autowired in the HRAnalystAgent with its default configuration - that's because we want to call it with all its available tools.  We need to adjust the HRBP so that when we call it from inside our tool that it doesn't use any other tools - just the knowledge we're giving it.  Add this method at the bottom of your class:

```java
private HRBusinessPartnerAgent getAgentWithPersonalFiles() {
        if (agentWithFiles == null) {
            agentWithFiles = AiServices.builder(HRBusinessPartnerAgent.class)
                    .retrievalAugmentor(PeoplelogicRetrievalAugmentor.builder()
                            .queryTransformer(ExpandingQueryTransformer.builder().chatModel(chatLanguageModel).build())
                            .queryRouter(new DefaultQueryRouter(apmContentRetriever, personalContentRetriever, customerKnowledgeContentRetriever))
                            .build())
                    .chatMemoryProvider(chatMemoryProvider)
                    .chatModel(chatLanguageModel)
                    .tools(Collections.emptyList()).build();
        }
        
        return agentWithFiles;
}
```

With that out of the way, we can get to the actual work - let's build our tool.

### Building the coach

To build the actual coach, we'll need to create a method that we can have the SDK call when it wants to help someone with leadership coaching. Add the method below in to your coaching tools class.

```java
@Tool("Provides an interactive coach or roleplay scenario to help HR and managers have a coaching conversation with an employee. " +
        "You need to ask who the employee is.  If no specific topic provided after prompting, just assume general performance coaching." +
        "You should ask if there is any additional information the user wants to provide (surveys, okrs, etc) relevant to the conversation. " +
        "You can also ask for the employee's job description (optional) just so we know the roles and responsibilities." +
        "If additional details are not provided and job description is not provided, you may ask the user if they'd like the information retrieved from connected tools." +
        "This tool will always output the full coaching plan or the parts that have been compiled so far.")
@SneakyThrows
public String roleplayOrProvideCoachingAdviceHelpMeCoachAnEmployee(@ToolMemoryId String memoryId, @P("Employee Name") String employeeName, 
        @P("Specific topic for coaching") String specificTopic,
        @P(value = "Filenames of additional inputs - excluding job descriptions", required = false) String additionalFiles,
        @P(value = "Employee's Job Description", required = false) String jobDescription) {
}
```

As you can see, we're giving the tool both a very detailed description AND a detailed name so that the LLM has as much information as possible to call our tool.  We're also passing in both required (name and general topic) and optional inputs such as recent reviews, OKRs and even the employee's job description.

{% hint style="info" %}
A more advanced version of this tool might choose to use the Universal Talent API to fetch all of these details and include them in the response without the need for any uploads.
{% endhint %}

Now let's take a look at how we might use all this information:

```java
String userQuery = "Help me have a coaching conversation with " + employeeName + " around " + specificTopic + ". " +
        "If additional files are provided, try to use those. It should be an interactive conversation. " +
        "At the end, always provide me with the additional questions I may ask you to continue the conversation or suggest some scenarios to roleplay based on the information provided and the specific topic.";

// Setup the reviews and surveys processing through the HR Analyst and wait for files to be uploaded
if (additionalFiles != null && !additionalFiles.isEmpty()) {
    additionalFiles = getFilenamesAsJoinedString(additionalFiles);

    String analysisQuery = "analyze these okr cycles, engagement results and review results located in files '" + additionalFiles + "'. All files have been provided already - do not ask for them again.  Everything is confirmed - no more required.";
    SearchFileContext.setCurrentFiles(additionalFiles.split(","));
    if (!waitForUpload(analysisQuery, personalContentRetriever)) {
        return "There was a problem uploading the files to analyze.  Please try again.";
    }

    // Call the HR Analyst and append the results to the user query
    Result<PeoplelogicResult> analystResults = analyst.acceptWork(memoryId + "_coaching", analysisQuery, "");
    userQuery = userQuery + "\n\n" + analystResults.content().getResponse();
}
```

We'll break this into a few parts for simplicity.  First, we're going to setup the basic instruction to go with our earlier system message - remember, every call to the agents needs both! Then, we need to do some cleanup of the additional inputs and ensure those have actually been uploaded.  Finally, we're going to call the HR Analyst and let it work its magic analyzing any reviews, surveys or OKRs and include those in what we want to pass to the coaching tool.

```java
// Check if we have provided a job description
if (jobDescription != null && !jobDescription.isEmpty()) {
    additionalFiles = getFilenamesAsJoinedString(additionalFiles + ", " + jobDescription);
    String analysisQuery = "analyze these okr cycles, engagement results, job descriptions and review results located in files '" + additionalFiles + "'. All files have been provided already - do not ask for them again.  Everything is confirmed - no more required.";
    SearchFileContext.setCurrentFiles(additionalFiles.split(","));
    if (!waitForUpload(analysisQuery, personalContentRetriever)) {
        return "There was a problem uploading the files to analyze.  Please try again.";
    }
}

String result = getAgentWithPersonalFiles().answerWithPrompt(memoryId + "_coaching", userQuery, COACHING_CONVERSATION_SEGMENT);
return "Here is the plan - output it in full to the user: " + result;
```

All that's left is to handle the Job Description file and then ship all this information off to the HRBP agents that we setup earlier.  Again, we're doing some basic cleanup and safety checking in case the job description was provided and then we call the HRBP agent with everything we've pulled together so far and send the result back to the LLM!

### The coach in action

Now that we've written the prompts, configured the agents, built the tools, we just need to tell the built-in HRBP agent about your new tool.  Let's go back to `src/main/resources/application.properties` and add the following:

<pre><code><strong>peoplelogic.agent.HRBusinessPartnerAgent.tools=hrbp-coaching-tools
</strong></code></pre>

That's it!  Deploy your agents or load the application locally and then let's load up our Slack application and see if the tool works.

{% embed url="<https://youtu.be/DOzcMqXyU2I>" %}

Pretty impressive! The agent incorporated the files we uploaded, gave us great conversation starters based on the recent reviews and goal progress, and when prompted for specifics even took the initiative to leverage another tool that the HRBP has available, creating a new IDP (Individual development plan) to use in the conversation.  This will all be a big help for your friends in HR!

### Future improvements

While this example is a great one, there's a few places that we could definitely improve moving forward.    For example:

1. [Moving the long system prompts out to a file for maintainability.](/guides/getting-started-with-the-talent-agent-sdk/advanced/externalizing-your-prompts)
2. [Including the Universal Talent API](/guides/getting-started-with-the-composable-talent-platform) so that there's no need to upload files.
3. [Personalizing the HRBP to fit your organization's persona.](/guides/getting-started-with-the-talent-agent-sdk/personalizing-your-agents)

Feel free to suggest other improvements as you work through the tutorial and as always, happy coding!


# OKR Dashboard with Kotlin Client

In this tutorial, we’ll build a small **Kotlin** command-line program that interacts with the **Peoplelogic.dev API** to manage OKRs (Objectives and Key Results) using pure HTTP calls. We’ll cover the following steps:

1. **Authentication:** Using a JWT API key as a Bearer token for authorization.
2. **Create an Objective:** Making a REST call to create a top-level OKR (Objective).
3. **Add Key Results:** Creating child objectives (key results) under the main objective.
4. **Add Tasks:** Attaching action-item tasks to the OKRs.
5. **Fetch & Display:** Retrieving all OKRs and printing them in a hierarchical, dashboard-like view in the console.

We’ll use **Gradle** to set up a Kotlin project (JVM) with **OkHttp** for HTTP requests and a simple JSON library for parsing. The style here is hands-on and explanatory (in the spirit of CrewAI and Spring AI tutorials), with plenty of comments and clarity for a backend engineer with moderate Kotlin experience.

> **Note:** Replace placeholders (like `<YOUR_ORG_ID>` and `<YOUR_API_KEY>`) with your actual Peoplelogic organization ID and API key. You can obtain these from your Peoplelogic account. The API key is a JWT token that includes your org credentials and must be included as a Bearer token in each request.

### Project Setup

Let's start by setting up a new Kotlin project with Gradle. We will need the Kotlin JVM plugin, and dependencies for OkHttp (for HTTP calls) and org.json (for JSON handling).

**Gradle Build Script (build.gradle.kts):** This configures the project and dependencies.

```kotlin
plugins {
    kotlin("jvm") version "1.8.20"
    application
}
group = "com.example"
version = "1.0-SNAPSHOT"

repositories {
    mavenCentral()
}

dependencies {
    implementation("com.squareup.okhttp3:okhttp:4.10.0")
    implementation("org.json:json:20211205")
}

application {
    mainClass.set("com.example.MainKt")
}
```

A few notes on the setup:

* We apply the Kotlin JVM plugin and set a Kotlin version (1.8.20 here).
* Dependencies include **OkHttp 4.x** for HTTP requests and **org.json** for simple JSON parsing. Both will be pulled from Maven Central.
* We use the Gradle Application plugin to easily run the program (with `MainKt` as the entry point).

Our project structure will look like this:

```
PeoplelogicKotlinDemo/
├── build.gradle.kts
├── settings.gradle.kts
└── src/main/kotlin/com/example/Main.kt
```

> The complete source code is provided in the attached ZIP file at the end of this tutorial.

### Authenticating with a JWT Bearer Token

The Peoplelogic API expects each request to be authenticated with a JWT token in the `Authorization` header. In our code, we’ll store the Org ID and API key (JWT) as constants and include them in every request.

The base URL for the Peoplelogic API is `https://api.peoplelogic.dev/api/v1`. All our endpoint paths will be relative to this (e.g. `/objective` for OKRs). The JWT token provided by Peoplelogic should be included as a **Bearer** token in the HTTP Authorization header.

We’ll set up some constants and an OkHttp client in our `Main.kt`:

```kotlin
package com.example

import okhttp3.*
import org.json.JSONObject

fun main() {
    // Placeholder credentials (replace with your actual values)
    val ORG_ID = "<YOUR_ORG_ID>"
    val API_KEY = "<YOUR_API_KEY>"  // JWT token for your Peoplelogic API
    val BASE_URL = "https://api.peoplelogic.dev/api/v1"

    // Initialize HTTP client
    val client = OkHttpClient()
    // Media type for JSON payloads
    val JSONMedia = MediaType.get("application/json; charset=utf-8")
    ...
}
```

Here we set `API_KEY` to your JWT token string. We’ll use this in the header of every request like so:

```kotlin
.header("Authorization", "Bearer $API_KEY")
```

This ensures the Peoplelogic API recognizes our calls as authorized.

### 1. Creating a Top-Level Objective

An **Objective** in Peoplelogic represents a high-level goal (for example, *“Increase Q3 Sales by 20%”*). We’ll create a new objective via an HTTP **POST** request to the `/objective` endpoint.

**Endpoint:** `POST /objective` (requires auth) – Creates a new objective in your organization. The request body is JSON with the objective details.

```kotlin
// 1. Create a top-level Objective (OKR)
val objectiveJson = JSONObject(mapOf(
    "name" to "Increase Q3 Sales by 20%",
    "description" to "Company-wide sales growth goal for Q3"
))
val createObjectiveRequest = Request.Builder()
    .url("$BASE_URL/objective")
    .header("Authorization", "Bearer $API_KEY")
    .post(RequestBody.create(JSONMedia, objectiveJson.toString()))
    .build()

val createObjectiveResponse = client.newCall(createObjectiveRequest).execute()
if (!createObjectiveResponse.isSuccessful) {
    println("Failed to create objective: HTTP ${createObjectiveResponse.code}")
    return
}
val createdObjective = JSONObject(createObjectiveResponse.body!!.string())
val objectiveId = createdObjective.getString("id")
println("Created Objective '${createdObjective.getString("name")}' (ID: $objectiveId)")
```

### 2. Adding Key Results (Child Objectives)

With the main objective in place, we’ll add a couple of **Key Results**. In Peoplelogic, key results are objectives that have a `parentId` linking them to a top-level objective.

```kotlin
// 2. Create Key Results (child objectives)
val keyResults = listOf("Achieve $1M in new revenue", "Improve conversion rate to 5%")
val keyResultIds = mutableListOf<String>()

for (krName in keyResults) {
    val krJson = JSONObject(mapOf(
        "name" to krName,
        "parentId" to objectiveId          
    ))
    val createKrRequest = Request.Builder()
        .url("$BASE_URL/objective")
        .header("Authorization", "Bearer $API_KEY")
        .post(RequestBody.create(JSONMedia, krJson.toString()))
        .build()
    val createKrResponse = client.newCall(createKrRequest).execute()
    if (!createKrResponse.isSuccessful) {
        println("Failed to create key result: HTTP ${createKrResponse.code}")
        return
    }
    val createdKr = JSONObject(createKrResponse.body!!.string())
    val krId = createdKr.getString("id")
    keyResultIds.add(krId)
    println("Created Key Result '${createdKr.getString("name")}' (ID: $krId)")
}
```

### 3. Adding Tasks to the OKRs

Next, we’ll add tasks to each key result via the `POST /entity/{entityId}/task` endpoint.

```kotlin
// 3. Add Tasks (action items)
val tasks = listOf(
    "Identify 50 new sales leads" to "2025-09-30",
    "Launch marketing campaign"   to "2025-09-30"
)
for ((index, krId) in keyResultIds.withIndex()) {
    val (taskName, dueDate) = tasks[index]
    val taskJson = JSONObject(mapOf(
        "name" to taskName,
        "dueDate" to dueDate
    ))
    val createTaskRequest = Request.Builder()
        .url("$BASE_URL/entity/$krId/task")
        .header("Authorization", "Bearer $API_KEY")
        .post(RequestBody.create(JSONMedia, taskJson.toString()))
        .build()
    val createTaskResponse = client.newCall(createTaskRequest).execute()
    if (!createTaskResponse.isSuccessful) {
        println("Failed to create task: HTTP ${createTaskResponse.code}")
        return
    }
    val updatedObjective = JSONObject(createTaskResponse.body!!.string())
    val task = updatedObjective.getJSONArray("tasks").getJSONObject(0)
    println("Added Task '${task.getString("name")}' to Key Result (ID: $krId)")
}
```

### 4. Fetching and Displaying the OKR Dashboard

Finally, retrieve all objectives with child objectives and tasks via:

```
GET /objective?projections=OBJECTIVE_TREE,TASKS
```

Then print a neat CLI dashboard:

```kotlin
val getOkrsRequest = Request.Builder()
    .url("$BASE_URL/objective?projections=OBJECTIVE_TREE,TASKS")
    .header("Authorization", "Bearer $API_KEY")
    .get()
    .build()

val getOkrsResponse = client.newCall(getOkrsRequest).execute()
...
val okrsArray = JSONArray(getOkrsResponse.body!!.string())
println("\nOKR Dashboard:")
for (i in 0 until okrsArray.length()) {
    val obj = okrsArray.getJSONObject(i)
    printObjective(obj, 0)
}

// Helper to print objectives and tasks recursively
fun printObjective(obj: JSONObject, indent: Int) {
    val indentStr = " ".repeat(indent * 2)
    val label = if (obj.isNull("parentId")) "Objective" else "Key Result"
    println("$indentStr$label: ${obj.getString("name")}")
    if (obj.has("tasks")) {
        val tasks = obj.getJSONArray("tasks")
        for (j in 0 until tasks.length()) {
            val task = tasks.getJSONObject(j)
            val status = task.getJSONObject("status").getString("current")
            val checkbox = if (status == "ACTIVE") "[ ]" else "[x]"
            val due = if (task.isNull("dueDate")) "" else " (due ${task.getString("dueDate")})"
            println("$indentStr  $checkbox ${task.getString("name")}$due")
        }
    }
    if (obj.has("childObjectives")) {
        val children = obj.getJSONArray("childObjectives")
        for (k in 0 until children.length()) {
            printObjective(children.getJSONObject(k), indent + 1)
        }
    }
}
```

**Expected Console Output:**

```
OKR Dashboard:
Objective: Increase Q3 Sales by 20%
  Key Result: Achieve $1M in new revenue
    [ ] Identify 50 new sales leads (due 2025-09-30)
  Key Result: Improve conversion rate to 5%
    [ ] Launch marketing campaign (due 2025-09-30)
```

That’s it! You’ve built a full CLI dashboard for OKRs using **only** the Peoplelogic.dev REST API and **basic** Kotlin libraries.


# Managing Meetings with Kotlin and OkHttp

In this tutorial, we'll build a small Kotlin command-line tool that interacts with Peoplelogic.dev's REST API to manage meetings. Specifically, we'll demonstrate how to create a meeting and then use various API endpoints to add participants, attach an agenda note, and include follow-up tasks. All interactions will use raw HTTP requests via the OkHttp client (no proprietary SDKs), and we'll authenticate using a JWT API key passed as a Bearer token in the `Authorization` header. By the end, we'll fetch the meeting with all related data (participants, notes, and tasks) and print it out in a structured, human-readable format in the console.

**What we'll cover:**

* Setting up OkHttp with a JWT Bearer token for authentication.
* Creating a new meeting with a POST request to the `/meeting` endpoint (providing name, type, etc.).
* Looking up employees by email via GET `/employee/{email}` to get their IDs.
* Adding those employees as meeting participants using POST `/meeting/{meetingId}/participant`.
* Attaching a note (agenda) to the meeting using POST `/entity/{meetingId}/note`.
* Creating a couple of tasks associated with the meeting via POST `/entity/{meetingId}/task`.
* Retrieving the meeting (GET `/meeting/{meetingId}`) with query projections to include participants, notes, and tasks.
* Formatting and displaying the collected meeting information in a friendly CLI output.

Throughout, the tone is conversational and code-focused — as if we're pair-programming this with a fellow backend developer. Let's dive in!

### Setting Up OkHttp and Authentication

First, ensure you have the OkHttp library added to your project (e.g., via Gradle). We'll use OkHttp to perform HTTP calls. We also assume you have a Peoplelogic API JWT key ready (obtainable from your Peoplelogic account). We'll use this JWT for authenticating our requests by sending it as a Bearer token.

Let's configure an OkHttp client that automatically includes the `Authorization: Bearer <API_KEY>` header on every request. This saves us from adding the header manually to each request:

```kotlin
import okhttp3.OkHttpClient
import okhttp3.Interceptor
import okhttp3.Request
import okhttp3.Response

val API_KEY = "<YOUR_PEOPLELOGIC_JWT>"  // replace with your actual API key (JWT)
val client = OkHttpClient.Builder()
    .addInterceptor(Interceptor { chain ->
        val originalRequest = chain.request()
        // Inject the Authorization header into the request
        val requestWithAuth: Request = originalRequest.newBuilder()
            .header("Authorization", "Bearer $API_KEY")
            .build()
        chain.proceed(requestWithAuth)
    })
    .build()
```

In the above code, we build an `OkHttpClient` with an interceptor that appends our JWT API key as a Bearer token in the Authorization header for all requests. This way, we don't have to set it by hand each time. Now we're ready to start making authenticated calls to the Peoplelogic API.

*(Note: For simplicity, we'll use Kotlin's standard library and org.json for JSON parsing in this tutorial. In a real project, you might use a library like kotlinx.serialization or Moshi for JSON, but org.json will suffice for illustrative purposes.)*

### Creating a New Meeting

Let's begin by creating a meeting. Peoplelogic provides a REST endpoint to create meetings via **POST** to `/meeting`. The request body should include at least a **name** for the meeting, the **type** of meeting, and whether it's **recurring** or not. The meeting type is an enum with options like `INTERNAL`, `EXTERNAL`, or `ONE_ON_ONE`, indicating what kind of meeting it is (internal team meeting, external meeting with a client, one-on-one, etc.). For our example, we'll create an internal meeting that is not recurring.

We'll construct a JSON payload with the meeting details and send the POST request. The Peoplelogic API expects JSON, so we'll set the appropriate `Content-Type` header and include the JWT (which our client will handle). Here's how we can do it:

```kotlin
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.RequestBody.Companion.toRequestBody
import org.json.JSONObject

val baseUrl = "https://api.peoplelogic.dev/api/v1"  // base URL for Peoplelogic API (v1)
val meetingJson = """
{
  "name": "Project Roadmap Discussion",
  "type": "INTERNAL",
  "recurring": false
}
""".trimIndent()
val mediaTypeJson = "application/json; charset=utf-8".toMediaType()
val requestBody = meetingJson.toRequestBody(mediaTypeJson)

val createMeetingRequest = Request.Builder()
    .url("$baseUrl/meeting")
    .post(requestBody)
    .build()

val createMeetingResponse = client.newCall(createMeetingRequest).execute()
if (!createMeetingResponse.isSuccessful) {
    error("Failed to create meeting: ${createMeetingResponse.code}")
}
val responseBody = createMeetingResponse.body!!.string()
// Parse the response to get the meeting ID (and other info if needed)
val responseJson = JSONObject(responseBody)
val meetingObj = responseJson.optJSONObject("meeting") ?: responseJson  // handle wrapped response
val meetingId = meetingObj.getString("id")
val meetingName = meetingObj.getString("name")
println("✅ Created meeting '$meetingName' with ID $meetingId")
```

In this code, we build the JSON string for the meeting (with `name`, `type`, and `recurring` fields) and send it via a POST request to the `/meeting` endpoint. We then check for a successful response (HTTP 200/201) and parse the JSON response to extract the newly created meeting's **ID**. Peoplelogic returns the created meeting object; we grab its `id` (which we'll need for subsequent calls) and also log the name for confirmation. We used `JSONObject` to parse the response; if the API responds with the meeting wrapped in a top-level `"meeting"` JSON object, we handle that by using `optJSONObject("meeting")` (if not, we just parse the root as the meeting).

At this point, we have a new meeting in Peoplelogic with a known ID. Next, let's add participants to this meeting.

### Finding Employees by Email

Suppose we want to invite certain employees to this meeting. Peoplelogic identifies employees by UUID internally, but we might only know their emails (for example, from our company directory). The API provides a convenient GET endpoint to retrieve an employee by their email address: **GET** `/employee/{email}`. We can use this to look up each participant and get their `id` which will be needed to add them to the meeting.

Let's say we have two employees we want to add: Alice and Bob, identified by their email addresses. We'll fetch each one by email:

```kotlin
val participantEmails = listOf("alice@example.com", "bob@example.com")
val participantIds = mutableListOf<String>()
val idToName = mutableMapOf<String, String>()  // to store names for output later
val idToEmail = mutableMapOf<String, String>()

for (email in participantEmails) {
    val getEmployeeRequest = Request.Builder()
        .url("$baseUrl/employee/$email")
        .get()
        .build()
    val response = client.newCall(getEmployeeRequest).execute()
    if (!response.isSuccessful) {
        error("Employee lookup failed for $email (HTTP ${response.code})")
    }
    val body = response.body!!.string()
    val empJson = JSONObject(body)
    val empObj = empJson.optJSONObject("employee") ?: empJson
    val employeeId = empObj.getString("id")
    val employeeName = empObj.getString("name")
    participantIds.add(employeeId)
    idToName[employeeId] = employeeName
    idToEmail[employeeId] = email
    println("🔎 Found employee $employeeName (ID=$employeeId) for email $email")
}
```

Here we loop through each participant email, send a GET request to `/employee/{email}`, and parse the result. On success, the API returns the employee's data (which includes their unique `id` and name, among other fields). We collect each employee's ID in a list (`participantIds`) and also keep a mapping of ID to name (and email) for later, so we can easily print names instead of raw IDs. The `println` is just for our confirmation that we found the right people. We now have the IDs of "Alice" and "Bob" as `participantIds[0]` and `participantIds[1]` respectively.

*(Note: This step assumes the employees already exist in Peoplelogic. In practice, if an email isn't found (404 response), you'd need to onboard that employee via the API's employee creation endpoint. For our tutorial, we'll assume Alice and Bob are already in the system.)*

### Adding Participants to the Meeting

With the meeting created and the employee IDs in hand, we can now add these employees as participants of the meeting. The Peoplelogic API provides a **POST** endpoint `/meeting/{meetingId}/participant` that lets you assign an employee (or external guest) to a meeting. We need to send a JSON body containing an **assignment** specifying the participant type and the reference to the participant (either an `employeeId` for internal users, or an email/name for external participants).

Peoplelogic supports different participant roles via a `type` field in the assignment: for example, `PRIMARY` might indicate the meeting organizer/host, `SECONDARY` for regular internal participants, `OBSERVER` for non-participating observers, and `EXTERNAL` for guests outside the organization. We’ll designate the first employee (Alice) as the primary host and the second (Bob) as a secondary participant.

Let's add them to our meeting by making two POST requests to the participant endpoint:

```kotlin
// Assume participantIds[0] is Alice (host) and participantIds[1] is Bob (guest)
val (hostId, guestId) = participantIds

// 1. Add Alice as the PRIMARY participant (host)
val hostAssignJson = """{"type": "PRIMARY", "employeeId": "$hostId"}"""
val hostReqBody = hostAssignJson.toRequestBody(mediaTypeJson)
val addHostRequest = Request.Builder()
    .url("$baseUrl/meeting/$meetingId/participant")
    .post(hostReqBody)
    .build()

val addHostResponse = client.newCall(addHostRequest).execute()
if (!addHostResponse.isSuccessful) {
    error("Failed to add host (HTTP ${addHostResponse.code})")
}

// 2. Add Bob as a SECONDARY participant (regular attendee)
val guestAssignJson = """{"type": "SECONDARY", "employeeId": "$guestId"}"""
val guestReqBody = guestAssignJson.toRequestBody(mediaTypeJson)
val addGuestRequest = Request.Builder()
    .url("$baseUrl/meeting/$meetingId/participant")
    .post(guestReqBody)
    .build()

val addGuestResponse = client.newCall(addGuestRequest).execute()
if (!addGuestResponse.isSuccessful) {
    error("Failed to add participant (HTTP ${addGuestResponse.code})")
}

println("✅ Added ${idToName[hostId]} as host and ${idToName[guestId]} as participant to meeting $meetingId")
```

We post two assignment requests to `/meeting/{meetingId}/participant`. The JSON for each includes the `type` of participant and the `employeeId` of the person we're adding. In our case, we send `{"type": "PRIMARY", "employeeId": "<Alice's UUID>"}` for the host, and `{"type": "SECONDARY", "employeeId": "<Bob's UUID>"}` for the other participant. The API will link those employees to the meeting. If successful, each call returns an updated meeting object including the new participant, but we don't necessarily need to parse the response here since we'll fetch the full meeting details later. We just verify the status and print a confirmation. (Under the hood, the API now considers Alice and Bob as *assignees* on the meeting, which is how it tracks participants.)

### Adding a Meeting Agenda (Note)

Now that our meeting has participants, let's add an agenda. Peoplelogic's platform allows attaching notes to entities (meetings, tasks, etc.), which can serve as agendas, minutes, or any text content. We will use the **POST** `/entity/{meetingId}/note` endpoint to add a note to our meeting. The request body should include the note details. According to Peoplelogic's note model, a note has a **name** (title), **content** (the body of the note), and a **visibility** setting, among other fields. It also supports a **noteType** to classify the note (for example, a note could be categorized as an `INTERNAL_MEETING` note, `EXTERNAL_MEETING` note, etc., which is useful for filtering or analytics). We'll make this note the meeting's agenda, so we can give it a name like "Meeting Agenda" and include the agenda content.

We should also specify the `visibility`. Peoplelogic notes have visibility statuses (Public, Limited, Private). For an agenda that all meeting participants should see, **PUBLIC** is appropriate (which usually means it's visible to the organization or at least to all involved). Additionally, we can set the note's owner to the host of the meeting (so it’s attributed to Alice, for example). Let's add the agenda note:

```kotlin
val agendaNoteJson = """
{
  "name": "Meeting Agenda",
  "content": "Discuss project roadmap and milestones for Q3.",
  "noteType": "INTERNAL_MEETING",
  "format": "text",
  "visibility": "PUBLIC",
  "owner": "$hostId"
}
""".trimIndent()
val noteRequestBody = agendaNoteJson.toRequestBody(mediaTypeJson)
val addNoteRequest = Request.Builder()
    .url("$baseUrl/entity/$meetingId/note")
    .post(noteRequestBody)
    .build()

val addNoteResponse = client.newCall(addNoteRequest).execute()
if (!addNoteResponse.isSuccessful) {
    error("Failed to add agenda note (HTTP ${addNoteResponse.code})")
}
println("✅ Added agenda note to meeting $meetingId")
```

We constructed a JSON with the agenda details: a title ("Meeting Agenda"), some content, a `noteType` of `INTERNAL_MEETING` (since this is an internal meeting's note), and `visibility: "PUBLIC"` so it's broadly visible. We also include `"owner": "<hostId>"` to explicitly set the note's owner as Alice (the host). After posting to `/entity/{meetingId}/note`, the Peoplelogic API will create the note and associate it with our meeting. A successful response means the agenda is now stored. (Like before, the API would return the updated meeting or note info, but we can skip parsing it immediately.)

### Adding Tasks for Follow-ups

Next, let's add a couple of tasks related to this meeting. Perhaps during the meeting, we anticipate some follow-up actions. Peoplelogic lets you attach tasks to any entity in a similar fashion to notes. The endpoint is **POST** `/entity/{meetingId}/task` for creating a task under the meeting. Each task needs at least a **name** (what the task is), and it can also have a **description** and a **dueDate**, among other fields. For simplicity, we'll add two tasks with just names and brief descriptions (no due dates).

For example, let's add one task for someone to follow up with the design team after the meeting, and another task to prepare a budget draft. We'll send two POST requests, one for each task:

```kotlin
// Task 1: Follow up with design team
val task1Json = """
{
  "name": "Follow up with design team",
  "description": "Email the meeting summary to the design lead"
}
""".trimIndent()
val task1Request = Request.Builder()
    .url("$baseUrl/entity/$meetingId/task")
    .post(task1Json.toRequestBody(mediaTypeJson))
    .build()
val task1Response = client.newCall(task1Request).execute()
if (!task1Response.isSuccessful) {
    error("Failed to add task 1 (HTTP ${task1Response.code})")
}

// Task 2: Prepare budget draft
val task2Json = """
{
  "name": "Prepare budget draft",
  "description": "Outline budget for Q3 projects"
}
""".trimIndent()
val task2Request = Request.Builder()
    .url("$baseUrl/entity/$meetingId/task")
    .post(task2Json.toRequestBody(mediaTypeJson))
    .build()
val task2Response = client.newCall(task2Request).execute()
if (!task2Response.isSuccessful) {
    error("Failed to add task 2 (HTTP ${task2Response.code})")
}

println("✅ Added 2 tasks to meeting $meetingId")
```

Each task is added by posting a JSON with a name and description to the `/entity/{meetingId}/task` endpoint. We check that each request succeeded. After these calls, our meeting now has two tasks associated with it in Peoplelogic's system.

*(Just like notes, each task creation returns the updated meeting with the new task or the task object itself. We omitted parsing those responses here for brevity, as we'll retrieve everything in one go next.)*

### Retrieving and Displaying the Meeting Details

We have done all the operations: created a meeting, added participants, an agenda note, and tasks. Now it's time to fetch the meeting data and see if everything is in place. We want the meeting details along with its participants, notes, and tasks. By default, a GET on the meeting might not include all these related items, but Peoplelogic's API allows us to request **projections** – essentially telling the API to include those related collections in the response.

To do this, we add a query parameter `projections` to our GET request. For example, to include participants (internally called assignees), notes, and tasks, we can specify `?projections=ASSIGNEES,NOTES,TASKS` in the URL. Each of these projection keywords corresponds to a set of related data:

* `ASSIGNEES` will include the list of participants (assignees) in the meeting.
* `NOTES` will include any notes attached to the meeting (like our agenda).
* `TASKS` will include the tasks associated with the meeting.

Peoplelogic expects the projection names as a comma-separated list in the query string. Let's call GET on the meeting with these projections:

```kotlin
val getMeetingRequest = Request.Builder()
    .url("$baseUrl/meeting/$meetingId?projections=ASSIGNEES,NOTES,TASKS")
    .get()
    .build()

val getMeetingResponse = client.newCall(getMeetingRequest).execute()
if (!getMeetingResponse.isSuccessful) {
    error("Failed to fetch meeting details (HTTP ${getMeetingResponse.code})")
}
val meetingDetailsJson = JSONObject(getMeetingResponse.body!!.string())
val fullMeetingObj = meetingDetailsJson.optJSONObject("meeting") ?: meetingDetailsJson

// Extract main meeting info
val name = fullMeetingObj.getString("name")
val type = fullMeetingObj.getString("type")
val recurring = fullMeetingObj.getBoolean("recurring")

println("Meeting: $name (Type: $type, Recurring: $recurring)")

// List out participants (assignees)
println("Participants:")
val assigneesArray = fullMeetingObj.getJSONArray("assignees")
for (i in 0 until assigneesArray.length()) {
    val participant = assigneesArray.getJSONObject(i)
    // Determine participant's name and email:
    // If it's an external participant, the object may have 'name' or 'email' fields directly.
    // If it's an internal employee, we use the stored maps (idToName/Email) via the assignee's id.
    var participantName = participant.optString("name", "")
    var participantEmail = participant.optString("email", "")
    if (participantName.isEmpty()) {
        val assigneeInfo = participant.optJSONObject("assignee")
        if (assigneeInfo != null && assigneeInfo.getString("type") == "EMPLOYEE") {
            val empId = assigneeInfo.getString("entityId")
            participantName = idToName[empId] ?: "(Employee $empId)"
            participantEmail = idToEmail[empId] ?: ""
        }
    }
    // Identify role (PRIMARY vs SECONDARY, etc.)
    val roleType = participant.getString("type")
    val roleLabel = if (roleType == "PRIMARY") " (Host)" else ""
    // Print "Name <email>" plus role if host
    val emailPart = if (participantEmail.isNotBlank()) " <$participantEmail>" else ""
    println(" - $participantName$emailPart$roleLabel")
}

// Show the agenda note(s)
println("Agenda:")
val notesArray = fullMeetingObj.getJSONArray("notes")
if (notesArray.length() > 0) {
    val agendaNote = notesArray.getJSONObject(0)  // we only added one note
    val agendaContent = agendaNote.optString("content", "(no content)")
    println(" - $agendaContent")
} else {
    println(" (No notes)")
}

// Show tasks
println("Tasks:")
val tasksArray = fullMeetingObj.getJSONArray("tasks")
if (tasksArray.length() > 0) {
    for (i in 0 until tasksArray.length()) {
        val task = tasksArray.getJSONObject(i)
        val taskName = task.getString("name")
        val taskDesc = task.optString("description", "")
        if (taskDesc.isNotBlank()) {
            println(" - $taskName — $taskDesc")
        } else {
            println(" - $taskName")
        }
    }
} else {
    println(" (No tasks)")
}
```

Let's break down what we're doing in this final step:

* We send a GET request to `/meeting/{meetingId}` with `?projections=ASSIGNEES,NOTES,TASKS` to ask for participants, notes, and tasks to be included in the response. The API responds with a JSON object for the meeting that now contains arrays for `"assignees"` (participants), `"notes"`, and `"tasks"` in addition to the basic meeting fields.
* We parse the response into a `JSONObject`. As before, if the API wraps the result in a `"meeting"` key, we account for that.
* We extract the meeting's name, type, and recurring flag and print them in one line for a header.
* For **Participants**: we iterate over the `assignees` array. Each participant entry includes a `type` (Primary, Secondary, etc.) and either an embedded reference to an employee or direct name/email if it was an external invite. For internal employees like Alice and Bob, the entry might not contain their names/emails directly (it will have an `assignee` object with their ID and type). We use the `idToName`/`idToEmail` maps we built earlier to resolve those IDs back to actual names/emails for display. We then print each participant in the format "Name \<email>" and append "(Host)" for the one with type PRIMARY.
* For **Agenda**: we take the first note in the `notes` list (we only added one note, which is our agenda). We print its content. If there were multiple notes, we could list them, but in this case, it's just the agenda.
* For **Tasks**: we loop through the `tasks` array. For each task, we print the name and, if a description was provided, we print an em dash and the description after the name. Each task shows up as a bullet under Tasks.

Finally, when we run the above code, we should see a nicely formatted summary of the meeting in our console. For example:

```
Meeting: Project Roadmap Discussion (Type: INTERNAL, Recurring: false)
Participants:
 - Alice Johnson <alice@example.com> (Host)
 - Bob Smith <bob@example.com>
Agenda:
 - Discuss project roadmap and milestones for Q3.
Tasks:
 - Follow up with design team — Email the meeting summary to the design lead
 - Prepare budget draft — Outline budget for Q3 projects
```

*(The output above shows that our meeting was created correctly with the expected details and associations. Alice is marked as the host, Bob as a participant, the agenda content is listed, and the two tasks are displayed with their descriptions.)*

***

**Conclusion:** In this tutorial, we demonstrated how to use Kotlin and OkHttp to work with Peoplelogic.dev's REST API for meeting management. We covered authenticating with a JWT, creating a meeting via REST, looking up employees by email, adding participants (with different roles), posting an agenda note, and adding follow-up tasks. We also retrieved the enriched meeting data in one call using projections and printed the information in a readable format.&#x20;

This developer-to-developer walkthrough should help you integrate Peoplelogic's meeting endpoints into your own Kotlin applications. Feel free to expand on this example by handling errors more robustly, assigning tasks to specific people, or exploring other features of the Peoplelogic API as needed. Happy coding!


# Using Webhooks for Slack Notifications

Webhooks are a way for services to send real-time HTTP callbacks to your application when certain events occur. Instead of polling an API repeatedly, your app can **subscribe** to updates and receive an HTTP POST as soon as something changes. This is perfect for building event-driven integrations: for example, Peoplelogic can notify your app immediately when an OKR (or any other entity like an IDP or Meeting) is marked **COMPLETED**, and you can handle it right away—say, by sending a Slack message. Let's dive in!

### Gradle Project Setup

Let’s set up a Kotlin/Gradle project with the dependencies you need. In your `build.gradle.kts`, include Ktor for both server and client, plus kotlinx.serialization:

```kotlin
plugins {
    kotlin("jvm") version "1.8.21"
    application
}

repositories {
    mavenCentral()
}

dependencies {
    // Ktor server
    implementation("io.ktor:ktor-server-core:2.3.1")
    implementation("io.ktor:ktor-server-netty:2.3.1")
    implementation("io.ktor:ktor-server-content-negotiation:2.3.1")
    implementation("io.ktor:ktor-serialization-kotlinx-json:2.3.1")

    // Ktor client (for Slack integration)
    implementation("io.ktor:ktor-client-cio:2.3.1")
    implementation("io.ktor:ktor-client-content-negotiation:2.3.1")
    implementation("io.ktor:ktor-client-logging:2.3.1")

    // Kotlinx JSON
    implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0")
}

application {
    mainClass.set("MainKt")
}
```

This setup gives you everything you need to both **serve** webhook callbacks and **call** external HTTP endpoints (like Slack) within the same application.

***

### 1. Create a Webhook Signing Key

First, create a new signing key in Peoplelogic. This key is used to sign all webhook payloads.

```bash
curl -X POST "https://api.peoplelogic.dev/api/v1/webhook-key"      
-H "Authorization: Bearer <YOUR_API_TOKEN>"      
-H "Content-Type: application/json"      
-d '{"name":"MySigningKey","default":true}'
```

**Sample response**:

```json
{
  "id": "f6a1c9b2-0000-1111-2222-aaaaaaaaaaaa",
  "name": "MySigningKey",
  "secretBase64": "YWJjMTIzIT8kKiYoKSctPUB+",
  "default": true,
  "createdAt": "2025-05-28T14:21:00Z"
}
```

> **Note:** Keep the `secretBase64` value secure. You’ll use it in your listener to verify incoming webhook signatures.

***

### 2. Register a Webhook for Objective Status Changes

Now, register the webhook endpoint in Peoplelogic:

{% code overflow="wrap" %}

```bash
curl -X POST "https://api.peoplelogic.dev/api/v1/webhook"      -H "Authorization: Bearer <YOUR_API_TOKEN>"      
-H "Content-Type: application/json"      
-d '{
           "eventType": "objective.patch",
           "ifUpdates": ["status"],
           "url": "https://your-server.com/webhooks/peoplelogic",
           "signingKey": "f6a1c9b2-0000-1111-2222-aaaaaaaaaaaa"
         }'
```

{% endcode %}

In this request:

* `eventType` is the Peoplelogic event (format is `"<entityType>.<changeType>"`, e.g. `objective.patch` for updates). Using `"objective.patch"` with `ifUpdates: ["status"]` means “notify me when any objective is patched and its status field changed.” This filtering behavior is handled by Peoplelogic’s webhook triage (see [GitHub](https://github.com/peoplelogic/peoplelogic-apis/blob/6896b9ced5660a902aebcb8f05caca0e4e4d491f/modules/jobs/webhooks/src/main/kotlin/ai/peoplelogic/webhooks/WebhookTriageMessagesHandler.kt#L43-L54)).
* `url` is your public webhook endpoint.
* `ifUpdates` specifies which fields must be present in the change for the webhook to fire.
* `signingKey` is the ID of the key created above.

**Sample response**:

```json
{
  "id": "a9b8c7d6-3333-4444-5555-bbbbbbbbbbbb",
  "eventType": "objective.patch",
  "ifUpdates": ["status"],
  "url": "https://your-server.com/webhooks/peoplelogic",
  "signingKey": "f6a1c9b2-0000-1111-2222-aaaaaaaaaaaa",
  "active": true,
  "createdAt": "2025-05-28T14:22:00Z"
}
```

> This webhook fires whenever an objective’s `status` changes, thanks to the `ifUpdates` filter.

***

### 3. Create and Complete an OKR Objective

Next, create a demo OKR objective:

{% code overflow="wrap" %}

```bash
curl -X POST "https://api.peoplelogic.dev/api/v1/objective"      
-H "Authorization: Bearer <YOUR_API_TOKEN>"      
-H "Content-Type: application/json"      
-d '{
           "name": "Improve Customer Satisfaction",
           "description": "Boost our NPS score",
           "startingValue": 0,
           "targetValue": 100
         }'
```

{% endcode %}

> *You may need to adjust fields such as dates or cycle IDs depending on your Peoplelogic org configuration.*&#x20;

**Sample response**:

```json
{
  "id": "d9e8f7a6-6666-7777-8888-cccccccccccc",
  "name": "Improve Customer Satisfaction",
  "description": "Boost our NPS score",
  "status": { "current": "ACTIVE", "changedAt": null },
  "active": true
}
```

Save the `id` from the response—let’s call it `OBJ_ID`.

Now **complete** the objective:

{% code overflow="wrap" %}

```bash
curl -X PATCH "https://api.peoplelogic.dev/api/v1/objective/OBJ_ID"      
-H "Authorization: Bearer <YOUR_API_TOKEN>"      
-H "Content-Type: application/json"      
-d '{"status":"COMPLETED"}'
```

{% endcode %}

**Sample response**:

```json
{
  "id": "d9e8f7a6-6666-7777-8888-cccccccccccc",
  "status": { "current": "COMPLETED", "changedAt": "2025-05-28T14:25:00Z" },
  "active": true
}
```

When you issue the PATCH, Peoplelogic sees the `status` field changed and publishes an `EntityEvent` of type `"objective.patch"`. Since your webhook is listening for `"objective.patch"` with `status` in `ifUpdates`, Peoplelogic will send a POST to your Ktor server’s `/webhooks/peoplelogic` endpoint.

***

### Example API Output Summary

Putting it all together, you'll get something similar to the following:

```bash
# 1. Create Signing Key
curl -X POST "https://api.peoplelogic.dev/api/v1/webhook-key" 
-d '{"name":"MyKey"}'
# (Response) 
{
  "id": "f6a1c9b2-...-1234",
  "name": "MyKey",
  "secretBase64": "YWJjMTIzIT8kKiYoKSctPUB+",
  "default": true,
  "createdAt": "2025-05-28T14:21:00Z"
}

# 2. Register Webhook
curl -X POST "https://api.peoplelogic.dev/api/v1/webhook" -d '{
  "eventType":"objective.patch","url":"https://myapp.com/webhooks/peoplelogic",
  "ifUpdates":["status"],"signingKey":"f6a1c9b2-...-1234"
}'
# (Response)
{
  "id": "a9b8c7d6-...-4321",
  "eventType": "objective.patch",
  "url": "https://myapp.com/webhooks/peoplelogic",
  "ifUpdates": ["status"],
  "signingKey": "f6a1c9b2-...-1234",
  "active": true,
  "createdAt": "2025-05-28T14:22:00Z"
}

# 3. Create Objective
curl -X POST "https://api.peoplelogic.dev/api/v1/objective" -d '{
  "name": "Improve CSAT","description": "Boost score","targetValue":100,"startingValue":0
}'
# (Response)
{
  "id": "d9e8f7a6-...-7890",
  "name": "Improve CSAT",
  "description": "Boost score",
  "status": {"current": "ACTIVE", ...},
  "active": true,
  ...
}

# 4. Complete Objective
curl -X PATCH "https://api.peoplelogic.dev/api/v1/objective/d9e8f7a6-...-7890" 
-d '{"status":"COMPLETED"}'
# (Response)
{
  "id": "d9e8f7a6-...-7890",
  "status": {"current": "COMPLETED", "changedAt": "2025-05-28T14:25:00Z", ...},
  ...
}
```

***

### 4. Ktor Webhook Listener

Finally, let’s set up a Ktor server to receive and handle the webhook:

```kotlin
import io.ktor.server.engine.*
import io.ktor.server.netty.*
import io.ktor.server.routing.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.http.*
import io.ktor.client.*
import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.client.request.*
import io.ktor.serialization.kotlinx.json.*
import kotlinx.serialization.json.*
import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec
import java.util.Base64

fun main() {
    val secretBase64 = "YWJjMTIzIT8kKiYoKSctPUB+"  // from step 1
    val slackWebhookUrl = "<YOUR_SLACK_WEBHOOK_URL>"

    embeddedServer(Netty, port = 8080) {
        routing {
            post("/webhooks/peoplelogic") {
                val payload = call.receiveText()
                val signature = call.request.headers["X-Signature"] ?: ""

                // Verify HMAC-SHA256 signature
                val secretBytes = Base64.getDecoder().decode(secretBase64)
                val hmac = Mac.getInstance("HmacSHA256").apply {
                    init(SecretKeySpec(secretBytes, "HmacSHA256"))
                }.doFinal(payload.toByteArray())
                val expected = Base64.getEncoder().encodeToString(hmac)
                if (signature != expected) {
                    call.respond(HttpStatusCode.Unauthorized, "Invalid signature")
                    return@post
                }

                // Parse payload
                val json = Json.parseToJsonElement(payload).jsonObject
                val objId = json["id"]?.jsonPrimitive?.content ?: "unknown"
                val status = json["status"]?.jsonObject
                              ?.get("current")?.jsonPrimitive?.content

                // Notify Slack if completed
                if (status == "COMPLETED") {
                    val client = HttpClient {
                        install(ContentNegotiation) { json() }
                    }
                    client.post(slackWebhookUrl) {
                        contentType(ContentType.Application.Json)
                        setBody(JsonObject(mapOf(
                            "text" to JsonPrimitive("✅ Objective $objId completed!")
                        )))
                    }
                }
                call.respondText("OK")
            }
        }
    }.start(wait = true)
}
```

Point your Peoplelogic webhook at `https://your-server.com/webhooks/peoplelogic`, and you’re all set. When an objective is completed, Peoplelogic will call your endpoint, you’ll verify the signature, and your app will post a Slack message. Happy coding!


