import type { GithubIssueDemo, NangoSync } from '../../models';export default async function fetchData(nango: NangoSync) { // Fetch issues from GitHub. const res = await nango.get({ endpoint: '/repos/NangoHQ/interactive-demo/issues?labels=demo&sort=created&direction=asc' }); // Map issues to your preferred schema. const issues: GithubIssueDemo[] = res.data.map(({ id, title, html_url }: any) => { return { id, title, url: html_url }; }); // Persist issues to the Nango cache. await nango.batchSave(issues, 'GithubIssueDemo');}
import type { GithubIssueDemo, NangoSync } from '../../models';export default async function fetchData(nango: NangoSync) { // Fetch issues from GitHub. const res = await nango.get({ endpoint: '/repos/NangoHQ/interactive-demo/issues?labels=demo&sort=created&direction=asc' }); // Map issues to your preferred schema. const issues: GithubIssueDemo[] = res.data.map(({ id, title, html_url }: any) => { return { id, title, url: html_url }; }); // Persist issues to the Nango cache. await nango.batchSave(issues, 'GithubIssueDemo');}
import type { NangoAction, GithubCreateIssueInput, GithubCreateIssueResult } from '../../models';export default async function runAction(nango: NangoAction, input: GithubCreateIssueInput): Promise<GithubCreateIssueResult> { // Create a GitHub issue. const res = await nango.post({ endpoint: '/repos/NangoHQ/interactive-demo/issues', data: { title: `[demo] ${input.title}`, body: `The body of the issue.`, labels: ['automatic'] } }); // Send response. return { url: res.data.html_url, status: res.status };}
Read more about integration scripts to understand what role they play in Nango.
Integration scripts expose a helper object (NangoSync for sync scripts, NangoAction for action scripts), which allows to interact with external APIs & Nango more easily.
Makes an HTTP request inside an integration script:
const config = { endpoint: '/some-endpoint' };await nango.get(config); // GET requestawait nango.post(config); // POST requestawait nango.put(config); // PUT requestawait nango.patch(config); // PATCH requestawait nango.delete(config); // DELETE request
Note that all HTTP requests benefit from automatic credential injection. Because scripts are executed in the context of a specific integration & connection, Nango can automatically retrieve & refresh the relevant API credentials.
{ data: {}, // the response provided by the server status: 200, // the HTTP status code headers: {}, // the HTTP headers config: {}, // the config provided for the request request: {} // the request that generated this response }
Integration scripts sometimes need to access sensitive variables that should not be revealed directly in the code.
For this, you can define environment variables in the Nango UI, in the Environment Settings tab. Then you can retrieve these environment variables from integration scripts with:
As shown in the example above, use a for loop to iterate through the paginated results.
Nango has pre-configured the pagination settings for some popular APIs, so you don’t have to specify them in scripts.
You can view the pre-configured pagination settings for all APIs in the providers.yaml file.
Please note that some APIs have diverging pagination strategies per endpoint, so you might still need to override pre-configured pagination settings at times.
The pagination helper supports 3 types of pagination: cursor, link or offset with the following settings:
The name of the parameter containing the number of items per page, in the request. Inserted in the query parameters for GET/DELETE, in the body for POST/PUT/PATCH.
The path of the field containing the results, in the response. If omitted or empty string, it defaults to the root. Use . for nested fields, e.g. "results.contacts".
The name of the parameter containing the cursor for the next page, in the request. Inserted in the query parameters for GET/DELETE, in the body for POST/PUT/PATCH.
The name of the parameter containing the offset for the next page, in the request. Inserted in the query parameters for GET/DELETE, in the body for POST/PUT/PATCH.
The offset calculation method. by-response-size (default) means the offset is incremented by the number of results. per-page means the offset is incremented by one for each page.
A callback function that is called after each page is fetched. Useful for logging or tracking pagination progress. The callback receives the next page parameter and the full Axios response object, which includes the response data, status, headers, and request configuration.
You can find details on the pagination types and logic in the code.
Defaults to false. If false, the token will only be refreshed if it expires within 15 minutes. If true, a token refresh attempt will happen on each request. This is only useful for testing and should not be done at high traffic.
Defaults to false. If false, the refresh token is not included in the response, otherwise it is. In production, it is not advised to return the refresh token, for security reasons, since only the access token is needed to sign requests.
Upserts records to the Nango cache (i.e. create new records, update existing ones). Each record needs to contain a unique id field used to dedupe records.
Marks records as deleted in the Nango cache. Deleted records are still returned when you fetch them, but they are marked as deleted in the record’s metadata (i.e. soft delete).
The only field that needs to be present in each record when calling batchDelete is the unique id; the other fields are ignored.
const githubIssuesToDelete: { id: string }[] = ...; // Fetch issues to delete from GitHub API.await nango.batchDelete(githubIssuesToDelete, 'GitHubIssue');
Updates records in the Nango cache by merging the given data into the existing record. The id field is required in each record and used to determine what existing record to merge into.
batchUpdate is primarily useful in webhook sync scripts, where you receive partial updates from a webhook and want to merge them into the existing records.
The merge algorithm used is a deep merge. Nested objects are merged recursively, while arrays always use the new value for the array. Any fields not present in the update record are left unchanged.
// Create partial GitHub Issue update records with only id and state.const githubIssues: Pick<GitHubIssue, "id" | "state">[] = ...;await nango.batchUpdate(githubIssues, 'GitHubIssue');
Take special care when using batchUpdate with records containing arrays. The merge algorithm does not attempt to merge arrays, but rather always uses the value of the new array.
// given a an existing record:// { id: '1', tags: [{id: 12, name: 'Dev'}, {id: 13, name: "QA"}] }const updates: Pick<Issue, "id" | "tags">[] = [ { id: '1', tags: [{id: 14, name: 'UX'}] }];// after the update, the record will be:// { id: '1', tags: [{id: 14, name: "UX"}] }await nango.batchUpdate(updates, 'Issue');
Fetches records from the Nango cache by ID. Returns a Map where the keys are the requested IDs, and the values are the corresponding records. Any records that are not found will simply be absent from the map.
Example usage:
const records = await nango.getRecordsById<string, Issue>(['1', '2', '3'], 'Issue');if (records.has('1')) { const record = records.get('1'); await nango.log(record.title);} else { await nango.log('Record with id 1 not found.');}
Fetching records by ID is useful when you need to update specific records with a more granular approach than nango.batchUpdate(), which performs a deep merge. Note that nango.batchUpdate() is more performant than using nango.getRecordsById(), followed by nango.batchSave().
A common use case is when handling external webhooks, where only a partial update of a record is received from an API.
You can import relative files into your scripts to allow for code abstraction and to
maintain DRY (Don’t Repeat Yourself) principles. This means you can reuse code across
different scripts by importing it. The imported file must live in the nango-integrations
directory and can be imported in the following way:
import type { GithubIssueDemo, NangoSync } from '../../models';import { issueMapper } from '../mappers/issue-mappper';export default async function fetchData(nango: NangoSync) { // Fetch issues from GitHub. const res = await nango.get({ endpoint: '/repos/NangoHQ/interactive-demo/issues?labels=demo&sort=created&direction=asc' }); // Persist issues to the Nango cache. await nango.batchSave(issueMapper(res.data), 'GithubIssueDemo');}
Note that you cannot import third-party modules at this time. Additionally, if there is a compilation error in an imported file, the entry point file will also fail to compile.