Skip to content

Commit 85267b7

Browse files
create more detailed sections for oauth flow
1 parent f3a7aad commit 85267b7

File tree

2 files changed

+89
-59
lines changed

2 files changed

+89
-59
lines changed

guides/build-plane-app.mdx

Lines changed: 89 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,10 @@ integrations that fit your specific workflow.
4040
## High-Level Workflow
4141

4242
1. [Register your app on Plane developer portal](/guides/build-plane-app/#registering-your-app)
43-
2. [Implement OAuth authorization code flow](/guides/build-plane-app#authentication-setup)
44-
3. Obtain and store access tokens securely
45-
4. Make authenticated API requests to Plane
46-
5. Handle token refresh
43+
2. [Implement OAuth flow](/guides/build-plane-app#implement-oauth-flow)
44+
3. [Obtain and store access tokens securely](/guides/build-plane-app#obtain-and-store-access-tokens-securely)
45+
4. [Make authenticated API requests to Plane](/guides/build-plane-app#make-authenticated-api-requests-to-plane)
46+
5. [Handle token refresh](/guides/build-plane-app#handle-token-refresh)
4747

4848
## Registering Your App
4949

@@ -54,18 +54,23 @@ To build an OAuth application with Plane:
5454
3. Fill out the form with the required details:
5555

5656
- **Redirect URIs**: Provide the URIs where Plane will send the authorization code.
57+
- **Setup URL(Optional)**: Provide the URL that users will be redirected to when they click "Install App" from the marketplace. This URL should initiate the OAuth flow for your application.
5758
- **Contact Details**: Add your email or other contact information.
58-
- **Webhook URL Endpoint**: Update this with your service's webhook endpoint. Plane will send webhooks for all changes that happen in the installed workspace.
59-
- **Organization Details**: Include contact email, privacy policy URL, terms of service URL, and any other relevant information. This helps Plane validate and approve your application for listing in the marketplace.
59+
- **Webhook URL Endpoint(Optional)**: Your service's webhook endpoint. Plane will send an HTTP `POST` request to this endpoint upon every change to the workspace in which your app was installed.
60+
- **Organization Details(Optional)**: Optionally include your contact email, privacy policy URL, terms of service URL, and any other relevant information. This helps Plane validate and approve your application should you choose to [list in the marketplace](#listing-your-app-on-plane-marketplace).
6061

6162
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.
62-
5. Once the app is created, securely store the **Client ID** and **Client Secret**. You will need these credentials to interact with Plane's API during the OAuth flow and for making authenticated API requests.
63+
5. Once the app is created, securely store the generated **Client ID** and **Client Secret**. You will need these credentials to interact with Plane's API during the OAuth flow and for making authenticated API requests.
6364

64-
## Authentication Setup
65+
## Implement OAuth Flow
6566

66-
### Generating Consent URL
67+
### Generating Consent URL (Optional)
6768

68-
Before handling authentication, if your app manages installation, you must generate the consent (authorization) URL to initiate the OAuth flow. Below are sample implementations:
69+
This step is optional. This is needed only if the app should be installed from outside Plane's environment, the developer needs to generate the consent URL using the client ID generated during their app creation flow.
70+
71+
If this flow needs to be triggered from Plane marketplace as well, then provide the URL in "Setup URL" field on application create screen to redirect the user from marketplace on clicking "Install App" button.
72+
73+
Below are sample implementations:
6974

7075
<Tabs>
7176
<Tab title="Python">
@@ -223,24 +228,6 @@ response_data = response.json()
223228
access_token = response_data["access_token"]
224229
refresh_token = response_data["refresh_token"]
225230
expires_in = response_data["expires_in"]
226-
227-
# When access token expires, use refresh token to get a new access token
228-
refresh_payload = {
229-
"grant_type": "refresh_token",
230-
"refresh_token": refresh_token,
231-
"client_id": client_id,
232-
"client_secret": client_secret
233-
}
234-
235-
refresh_response = requests.post(
236-
url="https://api.plane.so/auth/o/token/",
237-
headers={"Content-Type": "application/x-www-form-urlencoded"},
238-
data=refresh_payload
239-
)
240-
241-
# Parse the refresh response
242-
refresh_response_data = refresh_response.json()
243-
access_token = refresh_response_data["access_token"]
244231
```
245232

246233
</Tab>
@@ -278,28 +265,6 @@ const responseData = response.data;
278265
const accessToken = responseData.access_token;
279266
const refreshToken = responseData.refresh_token;
280267
const expiresIn = responseData.expires_in;
281-
282-
// When access token expires, use refresh token to get a new access token
283-
const refreshPayload = {
284-
grant_type: "refresh_token",
285-
refresh_token: refreshToken,
286-
client_id: clientId,
287-
client_secret: clientSecret
288-
};
289-
290-
const refreshResponse = await axios.post(
291-
"https://api.plane.so/auth/o/token/",
292-
refreshPayload,
293-
{
294-
headers: {
295-
"Content-Type": "application/x-www-form-urlencoded"
296-
}
297-
}
298-
);
299-
300-
// Parse the refresh response
301-
const refreshResponseData = refreshResponse.data;
302-
const accessToken = refreshResponseData.access_token;
303268
```
304269

305270
</Tab>
@@ -379,16 +344,87 @@ const workspaceDetails = response.data[0];
379344
]
380345
```
381346

382-
## Using Plane SDKs
383347

384-
To simplify the OAuth flow and make it easier to build Plane apps, official SDKs are available:
348+
349+
## Obtain and store access tokens securely
350+
351+
Once you have obtained the access token, you can use it to make authenticated API requests to Plane.
352+
Store the access token and refresh token securely in your database.
353+
354+
355+
## Make authenticated API requests to Plane
356+
357+
For making authenticated API requests to Plane, you can use the access token obtained from the OAuth flow.
358+
359+
API reference is available at [https://docs.plane.so/api-reference](https://docs.plane.so/api-reference).
360+
361+
We have official SDKs for the following languages to simplify the OAuth flow and make it easier to call Plane's API.
385362

386363
| Language | Package Link | Source Code |
387364
|----------|---------|-------------|
388365
| Node.js | [npm i @makeplane/plane-node-sdk](https://www.npmjs.com/package/@makeplane/plane-node-sdk) | [plane-node-sdk](https://github.com/makeplane/plane-node-sdk) |
389366
| Python | [pip install plane-sdk](https://pypi.org/project/plane-sdk/) | [plane-python-sdk](https://github.com/makeplane/plane-python-sdk) |
390367

391-
These SDKs provide helpers for OAuth and other common tasks, allowing developers to implement the above flows efficiently.
368+
## Handle Token Refresh
369+
370+
When the access token expires, you can use the refresh token to get a new access token.
371+
372+
373+
#### Examples
374+
375+
<Tabs>
376+
<Tab title="Python">
377+
378+
```python
379+
# When access token expires, use refresh token to get a new access token
380+
refresh_payload = {
381+
"grant_type": "refresh_token",
382+
"refresh_token": refresh_token,
383+
"client_id": client_id,
384+
"client_secret": client_secret
385+
}
386+
387+
refresh_response = requests.post(
388+
url="https://api.plane.so/auth/o/token/",
389+
headers={"Content-Type": "application/x-www-form-urlencoded"},
390+
data=refresh_payload
391+
)
392+
393+
# Parse the refresh response
394+
refresh_response_data = refresh_response.json()
395+
access_token = refresh_response_data["access_token"]
396+
```
397+
398+
</Tab>
399+
<Tab title="TypeScript">
400+
401+
```typescript
402+
// When access token expires, use refresh token to get a new access token
403+
const refreshPayload = {
404+
grant_type: "refresh_token",
405+
refresh_token: refreshToken,
406+
client_id: clientId,
407+
client_secret: clientSecret
408+
};
409+
410+
const refreshResponse = await axios.post(
411+
"https://api.plane.so/auth/o/token/",
412+
refreshPayload,
413+
{
414+
headers: {
415+
"Content-Type": "application/x-www-form-urlencoded"
416+
}
417+
}
418+
);
419+
420+
// Parse the refresh response
421+
const refreshResponseData = refreshResponse.data;
422+
const accessToken = refreshResponseData.access_token;
423+
```
424+
</Tab>
425+
426+
</Tabs>
427+
392428

393429
## Listing Your App on Plane Marketplace
394430

mint.json

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -345,12 +345,6 @@
345345
{
346346
"group": "Webhooks",
347347
"pages": ["webhooks/intro-webhooks"]
348-
},
349-
{
350-
"group": "Guides",
351-
"pages": [
352-
"guides/build-plane-app"
353-
]
354348
}
355349
],
356350
"footerSocials": {

0 commit comments

Comments
 (0)