This guide shows how you can let your users authorize external APIs, from inside your app. Once authorized, you will retrieve, store and refresh OAuth credentials so you can later perform API requests or use Nango’s syncing features.

This feature is free & unlimited on Nango Cloud.

Step 1: Set up Nango

Create a free Nango account (no credit card required): Try Nango Cloud

Open the Dashboard in your browser.

Step 2: Create an integration

On the Dashboard, go to the New Integration page and fill in the form.

To get the Client ID and Client Secret you will need to register your app with the API. The API provider will ask you to submit the Callback URL shown at the bottom of the New Integration page on Nango. You should also register the necessary scopes both with the API provider and on the New Integration page on Nango.

Search for your API here on the Nango docs: e.g. Notion.
It will show you helpful links to register your OAuth app & get scopes.

Step 3: Test your integration

Click “Auth” next to the integration to try an OAuth flow from Nango. Nango OAuth button

  • If you get an error check the Activity tab: The logs there can show you helpful information to debug the issue.
  • If the OAuth flow succeeds, you can get your access token from the Connections tab - Congrats! 🎉

Step 4: Embed Nango in your frontend

Install @nangohq/frontend and use the code snippet from the Add New Connection page (step 3 above) to trigger OAuth flows from your frontend (cf. Frontend SDK docs).

<CONNECTION-ID> identifies this user’s connection with the integration in Nango. We recommend using a user ID or similar for it.

Step 5: Retrieve access tokens

In your backend you can use our Node SDK or Connections REST API to fetch always-fresh access tokens (which will allow you to query the external API).

  • <INTEGRATION-ID> is the name of your integration. It is listed on the Integrations tab in the Dashboard, e.g. slack
  • <CONNECTION-ID> is the Connection ID you passed in step 4 above.

When you fetch access tokens from Nango, Nango refreshes them if necessary. Always fetch them fresh to make sure you never work with an expired access token!

With the backend Node SDK

Check the backend Node SDK reference for more details.

Install @nangohq/node, then use:

import { Nango } from '@nangohq/node';

let nango = new Nango({ secretKey: '<SECRET-KEY>' });

let creds = await nango.getConnection('<INTEGRATION-ID>', '<CONNECTION-ID>');

With the REST API

Check the API reference for full details and an example response

Get the Secret Key from the Project Settings page.

curl --request GET \
        --url<CONNECTION-ID>?provider_config_key=<INTEGRATION-ID> \
        --header 'Authorization: Bearer <SECRET-KEY-FROM-PROJECT-SETTINGS>'

Advanced Configuration

Custom Callback URL

You can change the callback URL of Nango if you want to personalize it (e.g. use your own domain).

If you are using Nango Cloud, follow these steps:

  1. Add a new endpoint in your app, e.g. All requests to this endpoint should redirect to and pass along all original parameters. The easiest way to do this is with a 308 redirect.
  2. Change the registered OAuth callback URL with all API providers. Otherwise they will refuse new flows!
  3. When you are ready change your Nango callback URL in the Project Settings page (cloud)

Before saving the custom callback URL in Nango, ensure that:

  • the callback URL redirects to and passes along all parameters (e.g. 308 redirect)
  • your OAuth app, as registered with the external API provider, has the new callback URL whitelisted

If you are self-hosting Nango, follow the instructions here to change your callback URL.

Connection Configuration

Some APIs require additional parameters to run an OAuth flow or make API requests.

Some examples:

  • Zendesk OAuth has the following authorization URL, where the subdomain is specific to a user’s Zendesk account:
  • Qualtrics, Shopify and Gorgias have the same per-customer subdomains as Zendesk
  • Salesforce uses a different API base URL per customer, e.g.
  • Zoho uses different API base URLs for different data centers. E.g. US customer’s data is at and EU customer’s at

Setting Connection Configuration

For some APIs Nango requires additional details from the end user to run an OAuth flow or make API requests.

This is documented in two places:

For instance, to specify the subdomain for Zendesk, pass in an additional configuration object to nango.auth():

            params: {
                subdomain: '<ZENDESK-SUBDOMAIN>' 

Automatically retrieved Connection Configuration

Some Connection Configurations, such as the base URL for the Salesforce API, are automatically retrieved by Nango. This is noted on the API’s Nango docs page.

Nango will automatically use this information for the Proxy, but if needed you can also retrieve it (see next section).

Fetching Connection Configuration data

Nango stores all connection configuration data on the Connection objects. You can retrieve it with the SDKs or REST API.

    "connectionConfiguration": {
        "subdomain": "myshop",
        "instance_url": ""

Storing custom metadata per Connection

Nango lets you store arbitrary metadata on the Connection.

This is useful for:

  • Storing custom field mappings per customer (e.g. map “name” from the external API to “firstname” in your data model)
  • Storing per-customer configuration (e.g. which filters for syncing objects, categories to skip etc.)
  • Any other per-connection data you want to have available in your sync scripts

This metadata is available to you in syncs & actions with getMetadata():

interface Metadata {
    owner: string;
    repo: string;
    branch: string;

export default async function fetchData(nango: NangoSync) {
    const { owner, repo, branch } = await nango.getMetadata<Metadata>();

It can also be set and retrieved with the SDKs and the REST API. Check these pages for the methods to set and retrieve it.

Connection-Specific Authorization Params

Some APIs require to pass additional query parameters in the authorization URL. If this applies to all users & use-cases, these params can be added to the providers.yaml API configurations.

But sometimes, the additional authorization parameter is specific to a user or a use-case. In this case, it is possible to add it to the nango.auth() call from the Frontend SDK:

nango.auth('discord', '<CONNECTION-ID>', { authorization_params: { key: 'value' } });

Securing the Frontend SDK calls with HMAC

By default, this feature is disabled and your frontend can attempt to create a new connection using any Integration ID and Connection ID.

But you might want to ensure that the app user is the only one that can create a new connection with that Connection ID.

To enable this feature:

  1. Add a secret HMAC key in your Project Settings. Pick a large, random value!
  2. Generate the HMAC signature in your backend and pass it to your frontend where you make the nango.auth calls.
  3. When ready, enable the HMAC check in the Project settings. Nango will now reject auth calls without or mismatching HMAC signature, so make sure your code is ready before you flip the switch!

The HMAC digest is generated by your backend using the secret HMAC key you set and the combination of the Integration ID and the Connection ID. Your backend should keep the secret HMAC key private and not reveal it to your frontend or end-users!

In your frontend pass the HMAC digest as follows in nango.auth:

nango.auth('<INTEGRATION-ID>', '<CONNECTION-ID>', { hmac: '<HMAC-DIGEST>' });

The HMAC digest can be generated by using the following code in your backend (node example):

import * as crypto from 'node:crypto';

// TODO: execute authentication and authorization checks before generating the HMAC digest.

// The value of '<HMAC-KEY>' should match the secret HMAC key set in your project settings.
const hmac = crypto.createHmac('sha256', '<HMAC-KEY>');
const digest = hmac.digest('hex');

// TODO: return the value of `digest` to the frontend to pass to `nango.auth`.

Configure Integrations Programmatically

Nango offers a REST API to programmatically manage your Integrations.

Questions, problems, feedback?

We are happy to help! Please reach out on the Slack community, we are very active there.