-
Notifications
You must be signed in to change notification settings - Fork 575
fix(integrations): Add Passportal integration #4942
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 5 commits
519d1f9
c32efb9
0330947
a01d162
bf3a756
ddf3083
97cc7fd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| --- | ||
| title: 'Passportal' | ||
| sidebarTitle: 'Passportal' | ||
| description: 'Connect to the Passportal API in 2 minutes 💨' | ||
| --- | ||
|
|
||
| <Tabs> | ||
| <Tab title="🚀 Quickstart"> | ||
| <Steps> | ||
| <Step title="Create an integration"> | ||
| Sign up for a free Nango account ([here](https://app.nango.dev)) if you haven't already. Then navigate to [Integrations](https://app.nango.dev/dev/integrations) -> _Configure New Integration_ -> select _Passportal_. | ||
| </Step> | ||
|
|
||
| <Step title="Authorize Passportal"> | ||
| Go to [Connections](https://app.nango.dev/dev/connections) -> _Add Test Connection_ -> _Authorize_, then enter your Passportal **API Access Key ID**, **HMAC Token**, **Content String**, and **Base URL**. Later, you'll let your users do the same directly from your app. | ||
| </Step> | ||
|
|
||
| <Step title="Call the Passportal API"> | ||
| Let's make your first request to Passportal (fetch a list of clients). Replace the placeholders below with your [Nango secret key](https://app.nango.dev/dev/environment-settings), [integration ID](https://app.nango.dev/dev/integrations), and [connection ID](https://app.nango.dev/dev/connections): | ||
|
|
||
| <Tabs> | ||
| <Tab title="cURL"> | ||
| ```bash | ||
| curl -X GET "https://api.nango.dev/proxy/api/v2/clients" \ | ||
| -H "Authorization: Bearer <NANGO-SECRET-KEY>" \ | ||
| -H "Provider-Config-Key: <INTEGRATION-ID>" \ | ||
| -H "Connection-Id: <CONNECTION-ID>" \ | ||
| -H "Accept: application/json" | ||
| ``` | ||
| </Tab> | ||
|
|
||
| <Tab title="Node"> | ||
| Install Nango's backend SDK: `npm i @nangohq/node`. Then run: | ||
|
|
||
| ```typescript | ||
| import { Nango } from '@nangohq/node'; | ||
|
|
||
| const nango = new Nango({ secretKey: '<NANGO-SECRET-KEY>' }); | ||
|
|
||
| // Fetch a list of clients from Passportal | ||
| const res = await nango.get({ | ||
| endpoint: '/api/v2/clients', | ||
| providerConfigKey: '<INTEGRATION-ID>', | ||
| connectionId: '<CONNECTION-ID>' | ||
| }); | ||
|
|
||
| console.log(res.data); | ||
| ``` | ||
| </Tab> | ||
| </Tabs> | ||
|
|
||
| You can also fetch credentials dynamically via the [Node SDK](/reference/sdks/node#get-a-connection-with-credentials) or [API](/reference/api/connection/get). | ||
| </Step> | ||
| </Steps> | ||
|
|
||
| ✅ You're connected! Check the [Logs](https://app.nango.dev/dev/logs) tab in Nango to inspect requests. | ||
|
|
||
| <Tip> | ||
| Next step: [Embed the auth flow](/getting-started/quickstart/embed-in-your-app) in your app to let your users connect their Passportal accounts. | ||
| </Tip> | ||
| </Tab> | ||
|
|
||
| <Tab title="🔗 Useful links"> | ||
| | Topic | Links | | ||
| | - | - | | ||
| | Authorization | [Guide to connect to Passportal using Connect UI](/integrations/all/passportal/connect) | | ||
| | General | [Passportal Website](https://www.n-able.com/products/passportal) | | ||
| | Developer | [Passportal API Documentation](https://documentation.n-able.com/passportal/userguide/Content/api/api_information.htm) | | ||
| | | [API Key Management Guide](https://documentation.n-able.com/passportal/userguide/Content/api/api_key_management.htm) | | ||
| | | [Create HMAC Token Guide](https://documentation.n-able.com/passportal/userguide/Content/api/api_create_hmac.htm) | | ||
| | | [Generate API Access Token](https://documentation.n-able.com/passportal/userguide/Content/api/api_authorization.htm) | | ||
|
|
||
| <Note>Contribute useful links by [editing this page](https://github.com/nangohq/nango/tree/master/docs/integrations/all/passportal.mdx)</Note> | ||
| </Tab> | ||
|
|
||
| <Tab title="🚨 API gotchas"> | ||
| - Passportal uses instance-specific base URLs (e.g., `mycompany.passportalmsp.com`) | ||
| - Authentication requires a POST request to `/api/v2/auth/client_token` with the API Access Key ID in the `x-key` header | ||
| - The `x-hash` header must contain a pre-generated HMAC-SHA256 token (hexadecimal hash) | ||
| - Generate your HMAC token offline before configuring the integration | ||
| - You must provide the same content string that was used to generate the HMAC token in the request body | ||
| - The token request must include `scope: "docs_api"` in the body | ||
| - The access token expires and should be refreshed using the provided refresh token | ||
| - All API requests must include the access token in the Authorization Bearer header | ||
propel-code-bot[bot] marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| <Note>Contribute API gotchas by [editing this page](https://github.com/nangohq/nango/tree/master/docs/integrations/all/passportal.mdx)</Note> | ||
| </Tab> | ||
| </Tabs> | ||
|
|
||
| <Info> | ||
| Questions? Join us in the [Slack community](https://nango.dev/slack). | ||
| </Info> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| --- | ||
| title: Passportal - How do I link my account? | ||
| sidebarTitle: Passportal | ||
| --- | ||
|
|
||
| # Overview | ||
|
|
||
| To authenticate with Passportal, you need: | ||
| 1. **API Access Key ID** – Your Passportal API Access Key ID. | ||
| 2. **HMAC Token** – A pre-generated HMAC-SHA256 hash token (base64 encoded). | ||
| 3. **Content String** – The plain text message used to compute the HMAC token. | ||
| 4. **Base URL** – Your Passportal instance domain (e.g., `mycompany.passportalmsp.com`). | ||
|
|
||
| This guide walks you through generating your API credentials and HMAC token for Passportal. | ||
|
|
||
| ### Prerequisites: | ||
|
|
||
| - Access to your Passportal account with API permissions. | ||
|
|
||
| ### Step 1: Find your Passportal base URL | ||
|
|
||
| Log into your Passportal dashboard, check the URL at your browser address bar. | ||
propel-code-bot[bot] marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| If your URL is `https://mycompany.passportalmsp.com/dashboard` → Your Base URL is | ||
| `mycompany.passportalmsp.com` | ||
|
|
||
| ### Step 2: Generate API Access Key ID and Secret Access Key | ||
|
|
||
| 1. Log into your Passportal dashboard. | ||
| 2. In the left pane, go to **Settings** > **API Keys**. | ||
| <img src="/integrations/all/passportal/passportal-settings.png"/> | ||
| 3. Click **Create access key**. | ||
| <img src="/integrations/all/passportal/passportal-api-keys.png"/> | ||
| 4. View the **Access key ID**, then click **Show key** to reveal the **Secret access key**. | ||
| <img src="/integrations/all/passportal/passportal-new-key.png"/> | ||
| 5. Copy both the **Access key ID** and **Secret access key** to a secure location. | ||
|
|
||
| **Important**: The Secret access key is only viewable once in the Create access key dialog. After closing this dialog, it cannot be retrieved again. | ||
|
|
||
| <img src="/integrations/all/passportal/api-keys.png"/> | ||
|
|
||
| See: [API Key Management Guide](https://documentation.n-able.com/passportal/userguide/Content/api/api_key_management.htm) | ||
|
|
||
| ### Step 3: Generate HMAC Token | ||
|
|
||
| You need to create an HMAC-SHA256 token using: | ||
| - **Plain text message**: Choose a content string (e.g., `api-content-hash`). This text is not considered sensitive | ||
| - **Secret key**: Your Secret access key from Step 2 | ||
| - **Algorithm**: SHA-256 | ||
|
|
||
| Generate the HMAC token using Python: | ||
|
|
||
| ```python | ||
| import hmac | ||
| import hashlib | ||
|
|
||
| secret_key = "YOUR_SECRET_ACCESS_KEY" | ||
| content = "api-content-hash" | ||
| hmac_token = hmac.new(secret_key.encode(), content.encode(), hashlib.sha256).hexdigest() | ||
| print(hmac_token) | ||
| ``` | ||
|
|
||
| Store both the **HMAC token** and the **content string** you used – you'll need both. | ||
|
|
||
| See: [Create HMAC Token Guide](https://documentation.n-able.com/passportal/userguide/Content/api/api_create_hmac.htm) | ||
|
|
||
| ### Step 4: Enter your details in the Connect UI | ||
|
|
||
| Once you have your **API Access Key ID**, **HMAC Token**, **Content String**, and **Base URL**: | ||
| 1. Open the form where you connect to Passportal. | ||
| 2. Enter your **API Access Key ID**. | ||
| 3. Enter your **HMAC Token** (the hexadecimal hash you generated). | ||
| 4. Enter your **Content String** (the same text you used to generate the HMAC token, e.g., `api-content-hash`). | ||
| 5. Enter your **Base URL** (e.g., `mycompany.passportalmsp.com`). | ||
| 6. Click **Connect**. | ||
|
|
||
| <img src="/integrations/all/passportal/passportal-auth-form.png"/> | ||
|
|
||
| You are now connected to Passportal. | ||
|
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would be nice to include the form screenshot. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added. |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| ## Pre-built tooling | ||
| <AccordionGroup> | ||
| <Accordion title="✅ Authorization"> | ||
| | Tools | Status | | ||
| | - | - | | ||
| | Pre-built authorization (Two Step) | ✅ | | ||
| | Pre-built authorization UI | ✅ | | ||
| | Custom authorization UI | ✅ | | ||
| | End-user authorization guide | ✅ | | ||
| | Expired credentials detection | ✅ | | ||
| </Accordion> | ||
| <Accordion title="✅ Read & write data"> | ||
| | Tools | Status | | ||
| | - | - | | ||
| | Pre-built integrations | 🚫 (time to contribute: <48h) | | ||
| | API unification | ✅ | | ||
| | 2-way sync | ✅ | | ||
| | Webhooks from Nango on data modifications | ✅ | | ||
| | Real-time webhooks from 3rd-party API | 🚫 (time to contribute: <48h) | | ||
| | Proxy requests | ✅ | | ||
| </Accordion> | ||
| <Accordion title="✅ Observability & data quality"> | ||
| | Tools | Status | | ||
| | - | - | | ||
| | HTTP request logging | ✅ | | ||
| | End-to-type type safety | ✅ | | ||
jeremydhoon marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| | Data runtime validation | ✅ | | ||
| | OpenTelemetry export | ✅ | | ||
| | Slack alerts on errors | ✅ | | ||
| | Integration status API | ✅ | | ||
| </Accordion> | ||
| <Accordion title="✅ Customization"> | ||
| | Tools | Status | | ||
| | - | - | | ||
| | Create or customize use-cases | ✅ | | ||
| | Pre-configured pagination | 🚫 (time to contribute: <48h) | | ||
| | Pre-configured rate-limit handling | 🚫 (time to contribute: <48h) | | ||
| | Per-customer configurations | ✅ | | ||
| </Accordion> | ||
| </AccordionGroup> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| ## Pre-built integrations | ||
|
|
||
| _No pre-built integration yet (time to contribute: <48h)_ | ||
|
|
||
| <Tip>Not seeing the integration you need? [Build your own](https://nango.dev/docs/guides/platform/functions) independently.</Tip> |
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -9187,6 +9187,66 @@ pandadoc-api-key: | |||||||
| example: 3039ba033eb1410caa0a2227158d63c9d6502cd8 | ||||||||
| pattern: '^[a-fA-F0-9]+$' | ||||||||
|
|
||||||||
| passportal: | ||||||||
| display_name: Passportal | ||||||||
| categories: | ||||||||
| - support | ||||||||
| auth_mode: TWO_STEP | ||||||||
| token_url: https://${connectionConfig.base_url}/api/v2/auth/client_token | ||||||||
| token_headers: | ||||||||
| x-key: ${credentials.apiKey} | ||||||||
| x-hash: ${credentials.hmacToken} | ||||||||
| content-type: application/json | ||||||||
| token_params: | ||||||||
| scope: docs_api | ||||||||
| content: ${credentials.content} | ||||||||
| token_response: | ||||||||
| token: access_token | ||||||||
| token_expiration: expiry_time | ||||||||
| token_expiration_strategy: expireAt | ||||||||
| proxy: | ||||||||
| base_url: https://${connectionConfig.base_url} | ||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unfortunately the |
||||||||
| headers: | ||||||||
| authorization: Bearer ${accessToken} | ||||||||
| verification: | ||||||||
| method: GET | ||||||||
| headers: | ||||||||
| content-type: application/json | ||||||||
| endpoints: | ||||||||
| - /api/v2/documents?resultsPerPage=1 | ||||||||
| connection_config: | ||||||||
| base_url: | ||||||||
| type: string | ||||||||
| title: Passportal Base URL | ||||||||
| description: Your Passportal base URL | ||||||||
| example: mycompany.mypasswordapp.com | ||||||||
| format: hostname | ||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
| doc_section: '#step-1-find-your-passportal-base-url' | ||||||||
| credentials: | ||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would be nice to a add an example and pattern for both There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good call. I've added these. |
||||||||
| apiKey: | ||||||||
| type: string | ||||||||
| title: API Access Key ID | ||||||||
| description: Your Passportal API Access Key ID | ||||||||
| example: a14e6b4923ba5027189baded6ba7b68e6fcda742008c5d57b867f43a09768ece | ||||||||
| pattern: '^[a-fA-F0-9]{64}$' | ||||||||
| doc_section: '#step-2-generate-api-access-key-id-and-secret-access-key' | ||||||||
| hmacToken: | ||||||||
| type: string | ||||||||
| title: HMAC Token | ||||||||
| description: Your pre-generated HMAC token, hex encoded | ||||||||
| example: 23ec313efecb560a7f44239f6dd439ea56d18911c18b59e1150a3c7299da8202 | ||||||||
| pattern: '^[a-fA-F0-9]{64}$' | ||||||||
| secret: true | ||||||||
| doc_section: '#step-3-generate-hmac-token' | ||||||||
| content: | ||||||||
| type: string | ||||||||
| title: Content String | ||||||||
| description: Plain text message used to compute the HMAC token | ||||||||
| example: api-content-hash | ||||||||
| doc_section: '#step-3-generate-hmac-token' | ||||||||
| docs: https://nango.dev/docs/integrations/all/passportal | ||||||||
| docs_connect: https://nango.dev/docs/integrations/all/passportal/connect | ||||||||
|
|
||||||||
| paychex: | ||||||||
| display_name: Paychex | ||||||||
| categories: | ||||||||
|
|
||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the logo should have a maximum width or height of 44px and be centered within a 62x62px container. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If Claude Code is to be believed, the SVG should now meet these requirements. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we have a new docs style,take a look at Sellsy (Client Credentials) as an example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have moved to this new style.