Installing & instantiating the node SDK

Install it with your favorite package manager, e.g.:

npm i -S @nangohq/node

Instantiate the Nango class:

  • Nango Cloud

  • Localhost

  • Self-hosted

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

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

Auth

Retrieve API credentials

Nango stores API credentials in connections objects. Retrieve a connection with:

const connection = await nango.getConnection(
    '<INTEGRATION-ID>',
    '<CONNECTION-ID>',
    '<FORCE_REFRESH?: boolean>', // Optional: attempt to refresh the access access token regardless of its expiration status, defaults to false
    '<REFRESH_TOKEN?: boolean>', // Optional: return the refresh token as part of the response, defaults to false
);

The nango.getConnection() method returns the necessary information authenticate API requests:

  • OAuth 2: fresh access token
  • OAuth 1: token & token secret
  • API key: API key
  • Basic: username and password
Example Response
{
    "id": 18393,                                  // Nango internal connection id
    "created_at": "2023-03-08T09:43:03.725Z",     // Creation timestamp
    "updated_at": "2023-03-08T09:43:03.725Z",     // Last updated timestamp (e.g. last token refresh)
    "provider_config_key": "github",              // <INTEGRATION-ID>
    "connection_id": "1",                         // <CONNECTION-ID>
    "credentials": {
        "type": "OAUTH2",                         // OAUTH2 or OAUTH1
        "access_token": "gho_tsXLG73f....",       // The current access token (refreshed if needed)
        "refresh_token": "gho_fjofu84u9....",     // Refresh token (Only returned if the REFRESH_TOKEN boolean parameter is set to true and the refresh token is available)
        "expires_at": "2024-03-08T09:43:03.725Z", // Expiration date of access token (only if refresh token is present, otherwise missing)
        "raw": {                                  // Raw token response from the OAuth provider: Contents vary!
            "access_token": "gho_tsXLG73f....",
            "refresh_token": "gho_fjofu84u9....", // Refresh token (Only returned if the REFRESH_TOKEN boolean parameter is set to true and the refresh token is available)
            "token_type": "bearer",
            "scope": "public_repo,user"
        }
    },
    "connection_config": {                        // Additional API Configuration, see OAuth guide
        "subdomain": "myshop",
        "realmId": "XXXXX",
        "instance_id": "YYYYYYY"
    },                      
    "account_id": 0,                              // ID of your Nango account (Nango Cloud only)
    "metadata": {                                 // Custom metadata stored by you
        "myProperty": "yes",
        "filter": "closed=true"
    }
}                              

If you do not want to deal with collecting & injecting credentials in API requests for multiple authentication types, use the Proxy.

Please check the REST API reference for an example response and the full list of returned fields.

For OAuth 2, always fetch the latest access token from Nango before you run an API request, as we refresh tokens if needed. Caching tokens on your side could lead to failed requests.

List all connections for a user

const list = await nango.listConnections('<CONNECTION-ID>');

This returns you all connections of a specific user (i.e. Connection ID):

{
    connections: [
        {
            connection_id: '<CONNECTION-ID>',
            provider: '<INTEGRATION-ID>',
            created: '2023-03-08T09:43:03.725Z'
        },
        // ...
    ];
}

List all connections

const list = await nango.listConnections();

Returns a list of minimalistic connection objects. This can be helpful if you need to check whether a user has setup a specific integration. Note that the list does not contain any access credentials and fetching it also does not refresh the access tokens of any connections.

Please check the REST API reference for an example response and the full list of returned fields.

Delete a connection

await nango.deleteConnection('<INTEGRATION-ID>', '<CONNECTION-ID>');

This will throw an exception if the delete call is not successful.

Set and fetch custom Metadata

Nango lets you store custom metadata on the Connection.

setMetadata overrides any existing Metadata for the connection!

// Store custom metadata with the connection
await nango.setMetadata('<INTEGRATION-ID>', '<CONNECTION-ID>', { filter: 'status=closed' });

// Fetch custom metadata
const myMetadata = await nango.getMetadata('<INTEGRATION-ID>', '<CONNECTION-ID>');

console.log(JSON.stringify(myMetadata));
// prints: { "filter": "status=closed" }

If you know the structure of the metadata, you can specify a type for it when retrieving;

interface CustomMetadata {
    fieldMapping: Record<string, string>;
    idsToSkip: {
        id: number;
        path: string
   };
}
const myTypedMetadata = await nango.getMetadata<CustomMetadata>('<INTEGRATION-ID>', '<CONNECTION-ID>')

Retrieve integration details

Use this method to retrieve all the details Nango stores on a specific integration:

const integration = await nango.getIntegration(
    '<INTEGRATION-ID>',
    '<INCLUDE-INTEGRATION-CREDENTIALS?: boolean>', // Optional: if true, the response will contain the client ID, secret and scopes (false by default).
);

Please check the REST API reference for an example response and the full list of returned fields.

Sync

Proxy

Some APIs are not yet fully-configured to work with the Proxy and require you to indicate the base URL.

You can check if your API contains the proxy.base_url field in the providers.yaml configuration file.

If not, you need to add a baseUrlOverride field in your call to the Proxy as follow:

const res = await nango.proxy({
...
baseUrlOverride: 'https://gmail.googleapis.com',
...
});

Feel free to contribute the proxy.base_url field to any API in the providers.yaml public file, or reach out on the Slack community to ask us to do it.

To execute proxy requests, use:

const res = await nango.proxy({
    method: 'POST',
    endpoint: '/calendar/v3/users/me/calendarList',
    providerConfigKey: '<INTEGRATION-ID>',
    connectionId: '<CONNECTION-ID>',
    headers: {
        Go: 'Here'
    },
    params: {
        query: 'params!'
    },
    retries: 5, // If response code != 200. Exponential backoff, default is 0
    data: {
        id: 1,
        colorId: 'blue',
        selected: true
    },
    baseUrlOverride: 'https://api.google.com' // Optional
});

The base URL should already be set for you for each API, but you can override with the baseUrlOverride field.

Some APIs don’t have a default base URL (because it hasn’t been configured in Nango or they have multiple ones). You can check this by looking at the proxy.base_url field in the providers.yaml configuration file. Feel free to contribute this field or reach out on the Slack community to ask us to do it.

There are also convenience methods available: nango.get({}), nango.post({}), nango.patch{{}} and nango.delete({}).

Return value
When you call the proxy, Nango creates the API request to the external API and runs it for you (possibly with retries).

The response from the external API is passed back to you exactly as Nango gets it:

  • Response code
  • Response headers
  • Response body

For the node SDK, Nango returns an Axios response object.

Trigger syncs

You can trigger specific sync(s) for a connection:

await nango.triggerSync('<INTEGRATION-ID>', ['github-sync', 'hubspot-sync'], '<CONNECTION-ID>');

To trigger all syncs for a connection, just pass in an empty array:

await nango.triggerSync('<INTEGRATION-ID>', [], '<CONNECTION-ID>');

Start/pause syncs

Starts or pauses the continuous execution of specified sync(s) for a given connection.

await nango.pauseSync('<INTEGRATION-ID>', ['github-sync', 'hubspot-sync'], '<CONNECTION-ID>');
await nango.startSync('<INTEGRATION-ID>', ['github-sync', 'hubspot-sync'], '<CONNECTION-ID>');

Sync status

Returns the status of syncs given an integration, sync names, and an optional connection id

const syncStatuses = await nango.syncStatus('<INTEGRATION-ID>', '<Array of sync names | *>', '<CONNECTION-ID>')

console.log(syncStatuses);

/*
{
    "syncs": [
        {
            "id": "e234d172-6830-4db9-a6b2-2a30f2f668e2",
            "name": "salesforce-articles",
            "status": "ERROR",
            "latestResult": {},
            "type": "INCREMENTAL",
            "finishedAt": "2023-11-09T12:58:06.205Z",
            "nextScheduledSyncAt": "2023-11-10T00:58:04.000Z"
        },
        {
            "id": "3463bfdd-3fa2-418c-9e53-09f59416fe5f",
            "name": "salesforce-tickets",
            "type": "INITIAL",
            "status": "SUCCESS",
            "finishedAt": "2023-11-04T12:58:06.205Z",
            "nextScheduledSyncAt": "2023-11-10T01:58:04.000Z",
            "latestResult": {
                "SalesforceTicket": {
                    "added": 27,
                    "updated": 0
                }
            }
        }
    ]
}
*/

Read synced data

nango.getRecords() is deprecated and will be removed in future releases as it does not support efficient pagination. Please use nango.listRecords() detailed below.

To read synced data from Nango, use listRecords:

import type { ModelName } from '<path-to-nango-integrations>/models'

const records = await nango.listRecords<ModelName>({
    providerConfigKey: '<integration-id>',    // Name of your integration, from nango.yaml. E.g. github
    connectionId: '<user-id>',                // The connection id you passed to nango.auth()
    model: '<model-name>',                    // The name of the data model, from nango.yaml. E.g. ticket
    delta: '<timestamp>'                      // Optional. Only return records added or updated since this timestamp. E.g. 2023-05-31T11:46:13.390Z
    limit: <number>,                          // Optional: For pagination: Maximum of records to return. If not passed, all records are returned.
    cursor: '<string>'                        // Optional: Paginate through records using this value which can be obtained from the "next_cursor" property in the response.
    filter: 'added' | 'updated' | 'deleted'   // Optional: Retrieve only records that have been added, updated, or deleted since the last sync. Useful when used with the delta parameter. Also accepts comma separated combinations e.g., "added,updated"
});

console.log(records);

By default, this returns an array of objects in the data model that you queried with some metadata about each record.

{
    records:
        [
            {
                id: 123,
                ..., // Fields as specified in the model you queried
                _nango_metadata: {
                    deleted_at: null,
                    last_action: 'ADDED',
                    first_seen_at: '2023-09-18T15:20:35.941305+00:00',
                    last_modified_at: '2023-09-18T15:20:35.941305+00:00'
                }
            },
            ...
        ],
    next_cursor: "Y3JlYXRlZF9hdF4yMDIzLTExLTE3VDExOjQ3OjE0LjQ0NyswMjowMHxpZF4xYTE2MTYwMS0yMzk5LTQ4MzYtYWFiMi1mNjk1ZWI2YTZhYzI"
}

If you are using the Nango webhooks, you can use the timestamp you get from the webhook for the delta parameter.

The value from the next_cursor property can be used with the cursor parameter to get the next page of results. If there are no more results, the next_cursor will be null.

Trigger an action

To trigger an action, use:

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

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

const result = await nango.triggerAction('<INTEGRATION-ID>', '<CONNECTION-ID>', '<ACTION-NAME>', jsonInput);

This will return whatever the action script is configured to return.

Get environment variables

To get the environment variables from a sync script, you can use getEnvironmentVariables:

const vars = await nango.getEnvironmentVariables();

console.log(vars);

/*
[
    { "name": "BOT_TOKEN", "value": "abcdefg" }
]
*/