Skip to content
196 changes: 196 additions & 0 deletions guides/build-plane-app.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
---
title: Build your Plane Integration app
Comment thread
Prashant-Surya marked this conversation as resolved.
Outdated
Comment thread
Prashant-Surya marked this conversation as resolved.
Outdated
sidebarTitle: Build your Plane Integration app
Comment thread
Prashant-Surya marked this conversation as resolved.
Outdated
description: Step-by-step guide for developers to build and integrate an app with Plane.so using OAuth-based authentication and authorization workflow.
Comment thread
Prashant-Surya marked this conversation as resolved.
Outdated
---

This guide provides step-by-step instructions for developers to build and integrate an app with Plane.so using an OAuth-based authentication and authorization workflow.
Comment thread
Prashant-Surya marked this conversation as resolved.
Outdated

## Introduction

Plane.so supports OAuth 2.0 for secure authentication and authorization of third-party applications. This ensures that apps can request and obtain access tokens on behalf of users, enabling seamless integration while maintaining security standards.
Comment thread
Prashant-Surya marked this conversation as resolved.
Outdated
Comment thread
Prashant-Surya marked this conversation as resolved.
Outdated

## Prerequisites

* A Plane.so workspace.
Comment thread
Prashant-Surya marked this conversation as resolved.
Outdated
Comment thread
Prashant-Surya marked this conversation as resolved.
Outdated
* Access to Plane.so developer portal.
Comment thread
Prashant-Surya marked this conversation as resolved.
Outdated
Comment thread
Prashant-Surya marked this conversation as resolved.
Outdated
* Familiarity with OAuth 2.0 concepts (authorization code flow).
* A backend server to handle OAuth token exchange.

## High-Level Workflow

1. **Register your app on Plane.so developer portal**
2. **Implement OAuth authorization code flow**
3. **Obtain and store access tokens securely**
4. **Make authenticated API requests to Plane.so**
5. **Handle token refresh**
Comment thread
Prashant-Surya marked this conversation as resolved.
Outdated

## Registering Your App

To build an OAuth application with Plane.so:
Comment thread
Prashant-Surya marked this conversation as resolved.
Outdated

1. Navigate to `https://app.plane.so/<workspace_slug>/settings/applications/`.
Comment thread
Prashant-Surya marked this conversation as resolved.
Outdated
2. Click on the **Build your own** button.
3. Fill out the form with the required details:

* **Redirect URIs**: Provide the URIs where Plane.so will send the authorization code.
Comment thread
Prashant-Surya marked this conversation as resolved.
Outdated
* **Contact Details**: Add your email or other contact information.
* **Webhook URL Endpoint**: Update this with your service's webhook endpoint. Plane.so will send webhooks for all changes that happen in the installed workspace.
Comment thread
Prashant-Surya marked this conversation as resolved.
Outdated
* **Organization Details**: Include contact email, privacy policy URL, terms of service URL, and any other relevant information. This helps Plane.so validate and approve your application for listing in the marketplace.
Comment thread
Prashant-Surya marked this conversation as resolved.
Outdated
4. If you're building an agent (with or without using Plane's ADK) capable of performing operations when assigned or mentioned, enable the **Is Mentionable** checkbox during app creation.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • We haven't talked about agents before this section. Do we need to use this term here?
  • Are agents the only type of app which is mentionable? My instinct tells me agents are just apps so all should be mentionable.
  • What does mentionable mean?
  • Are apps not otherwise mentionable if this box is checked? Why do developers need to check this box? Mentioning apps in Slack / Github is pretty common, before AI came around. Seems like this should always be enabled and we would remove this option from the UI.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We enabled Is Mentionable by default. This will result in all apps coming in assignees and other user fields. It'll be noise if there are too many apps in the assignees/members list.
We took inspiration from other products in similar to space to control this using a flag. Which will be moved to a scope in future once they're available.

5. Once the app is created, securely store the **Client ID** and **Client Secret**. You will need these credentials to interact with Plane.so's API during the OAuth flow and for making authenticated API requests.
Comment thread
Prashant-Surya marked this conversation as resolved.
Outdated

Comment thread
Prashant-Surya marked this conversation as resolved.
## Authentication Setup

### Generating Consent URL

Before handling types of authentication, if your app manages installation, you must generate the consent (authorization) URL to initiate the OAuth flow. Below is a sample implementation:
Comment thread
Prashant-Surya marked this conversation as resolved.
Outdated

```python
params = {
"client_id": os.getenv("PLANE_CLIENT_ID"),
"response_type": "code",
"redirect_uri": os.getenv("PLANE_REDIRECT_URI"),
# Optional: include state if needed
}

consent_url = f"https://api.plane.so/auth/o/authorize-app/?{urlencode(params)}"
```
Comment thread
Prashant-Surya marked this conversation as resolved.
Outdated

There are two types of authenticated actions your application can perform:

1. **User-authorized actions** — Actions performed on behalf of a user after they grant permission to your app via OAuth.
Comment thread
Prashant-Surya marked this conversation as resolved.
Outdated
2. **App-authorized actions** — Actions that the app can perform independently within the workspace where it is installed (such as responding to webhooks or automation triggers).
Comment thread
Prashant-Surya marked this conversation as resolved.
Outdated

We will describe how to configure and use each type in the following sections.

### App-Authorized Actions (Client Credentials Flow)

When the user or admin installs the app, Plane.so will send an `app_installation_id` as part of the callback to the `redirect_uri` provided during consent URL generation. You can use this `app_installation_id` to request a bot token for your app.
Comment thread
Prashant-Surya marked this conversation as resolved.
Outdated

#### Example Pseudo-code
Comment thread
Prashant-Surya marked this conversation as resolved.
Outdated

Comment thread
Prashant-Surya marked this conversation as resolved.
Outdated
```python
# Prepare basic auth header using client_id and client_secret
basic_auth = base64encode("client_id:client_secret")

# Prepare request data
payload = {
"grant_type": "client_credentials",
"app_installation_id": app_installation_id
}

# Make a POST request to fetch bot token
response = POST(
url="https://api.plane.so/auth/o/token/",
headers={"Authorization": f"Basic {basic_auth}",
"Content-Type": "application/x-www-form-urlencoded"},
data=payload
)

bot_token = response.data['access_token']
expires_in = response.data["expires_in"]
```

### User-Authorized Actions (Authorization Code Flow)

In this flow, your app exchanges the `code` received as a query parameter on the callback (to your `redirect_uri`) for an access token and refresh token. The access token is short-lived and must be refreshed using the refresh token when it expires. Both tokens should be securely stored.

#### Example Pseudo-code

```python
Comment thread
Prashant-Surya marked this conversation as resolved.
Outdated
# Exchange authorization code for access and refresh tokens
payload = {
"grant_type": "authorization_code",
"code": code,
"client_id": client_id,
"client_secret": client_secret,
"redirect_uri": redirect_uri
}

response = POST(
url="https://api.plane.so/auth/o/token/",
headers={"Content-Type": "application/x-www-form-urlencoded"},
data=payload
)

access_token = response.data["access_token"]
refresh_token = response.data["refresh_token"]
expires_in = response.data["expires_in"]

# When access token expires, use refresh token to get a new access token
refresh_payload = {
"grant_type": "refresh_token",
"refresh_token": refresh_token,
"client_id": client_id,
"client_secret": client_secret
}

refresh_response = POST(
url="https://api.plane.so/auth/o/token/",
headers={"Content-Type": "application/x-www-form-urlencoded"},
data=refresh_payload
)

access_token = refresh_response.data["access_token"]
```

### Fetching App Installation Details

In both user-authorized and app-authorized flows, the `app_installation_id` identifies the app's installation within a specific workspace. It is recommended that developers fetch workspace details after OAuth is successfully completed. Plane.so provides an `app-installation` endpoint that works with both types of tokens.
Comment thread
Prashant-Surya marked this conversation as resolved.
Outdated

#### Example Pseudo-code

Comment thread
Prashant-Surya marked this conversation as resolved.
Outdated
```python
# Set authorization header with either access token or bot token
headers = {
"Authorization": f"Bearer {token}",
}

# Make GET request to fetch installation/workspace details
response = GET(
url=f"https://api.plane.so/auth/o/app-installation/?id={app_installation_id}",
headers=headers
)

workspace_details = response.data[0]
```

#### Sample Response
```
[
{
"id": "34b97361-8636-43dc-953e-90deedc8498f",
"workspace_detail": {
"name": "sandbox",
"slug": "sandbox",
"id": "7a2e5944-c117-4a7d-b5f4-058fe705d7d1",
"logo_url": null
},
"created_at": "2025-05-16T13:50:27.865821Z",
"updated_at": "2025-06-23T08:57:26.976742Z",
"deleted_at": null,
"status": "installed",
"workspace": "7a2e5944-c117-4a7d-b5f4-058fe705d7d1",
"application": "ab235529-388a-4f51-a55a-78272251f5f1",
"installed_by": "63333ab1-c605-42fc-82f7-5cd86799eca1",
"app_bot": "7286aaa7-9250-4851-a520-29c904fd7654", // app's bot user id in the workspace
"webhook": "b1f4b7f1-51e8-4919-a84c-0b1143b51d2c"
}
]
```

## Using Plane SDKs

To simplify the OAuth flow and make it easier to build Plane apps, official SDKs are available:

* **Node.js**: `npm i @makeplane/plane-node-sdk`
* **Python**: `pip install plane-sdk`
Comment thread
Prashant-Surya marked this conversation as resolved.
Outdated

These SDKs provide helpers for OAuth and other common tasks, allowing developers to implement the above flows efficiently.

## Listing Your App on Plane Marketplace

Apps built using the OAuth flow can be listed on the Plane Marketplace: [https://plane.so/marketplace/integrations](https://plane.so/marketplace/integrations)

To list your app, please contact the Plane team at [**support@plane.so**](mailto:support@plane.so).
Comment thread
Prashant-Surya marked this conversation as resolved.
Outdated
10 changes: 10 additions & 0 deletions mint.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@
{
"name": "Webhooks",
"url": "webhooks"
},
{
"name": "Guides",
"url": "guides"
}
],
"navigation": [
Expand Down Expand Up @@ -341,6 +345,12 @@
{
"group": "Webhooks",
"pages": ["webhooks/intro-webhooks"]
},
{
"group": "Guides",
"pages": [
"guides/build-plane-app"
]
}
],
"footerSocials": {
Expand Down