This guide will help you migrate your existing Pipedream SDK v1.x integration to the latest version.
- Migrating from v1.x
- Table of contents
- Deprecation
- Breaking changes
- Client initialization
- Method migration
- Namespace mapping
- New features in v2.x
- Browser/Server Environment Separation
- Additional namespaces
- Partial migration
- Important removed functionality
- Migration checklist
The v1.x version of the Pipedream SDK is now deprecated. This means that no changes will be made to this version unless there are critical security issues. We recommend that you migrate to the latest version of the SDK to take advantage of new features, improvements, and bug fixes if possible.
The new SDK version introduces several breaking changes that you need to be aware of when migrating from v1.x. Below is a summary of the most significant changes:
- Namespaced Methods: Methods are now namespaced by the resource they act
upon. For example, instead of using
client.runAction(), you now useclient.actions.run(). - Automatic Snake Case Conversion: While the TypeScript interfaces use
camelCasefor better developer experience, the SDK automatically converts these tosnake_casewhen making API calls to align with our OpenAPI spec. - Client Initialization: The
createBackendClient()andcreateFrontendClient()methods have been replaced with a newPipedreamClientclass. Note: The v1.xBrowserClientclass has been replaced withPipedreamClientin the browser context. - TypeScript Types: All TypeScript types are now exported for better type safety.
- Authentication Changes: The
rawAccessToken()method is now available as arawAccessTokengetter property on the server-side SDK. - Environment Variables: The SDK now supports automatic configuration via environment variables (see below).
For server-side applications, we recommend using the PipedreamClient wrapper
class, which simplifies OAuth token management.
import { createBackendClient } from "@pipedream/sdk";
const client = createBackendClient({
credentials: {
clientId: "your-client-id",
clientSecret: "your-client-secret",
},
projectId: "your-project-id",
environment: "development", // or 'production'
});
import { PipedreamClient } from "@pipedream/sdk";
const client = new PipedreamClient({
clientId: "your-client-id",
clientSecret: "your-client-secret",
projectId: "your-project-id",
projectEnvironment: "development", // or 'production'
});
For browser-side applications, you should use the PipedreamClient class and
authenticate using a connect_token obtained from your backend.
import { createFrontendClient } from "@pipedream/sdk";
const frontendClient = createFrontendClient({
environment: "development",
credentials: {
token: "connect-token-from-backend",
},
});
The v2.x SDK provides two options for browser-side usage:
Option 1: Using PipedreamClient with token callback (for dynamic token
management)
import { PipedreamClient } from "@pipedream/sdk";
const tokenCallback = async ({ externalUserId }) => {
// Call your backend to get a connect token
const response = await fetch("/api/pipedream/token", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ externalUserId }),
});
return response.json();
};
const clientWithToken = new PipedreamClient({
tokenCallback,
projectId: "your-project-id",
projectEnvironment: "development", // or 'production'
});
Option 2: Using createFrontendClient with connect token (for simple token-based
auth)
// Explicit browser import (recommended for browser apps)
import {
createFrontendClient,
type PipedreamClient,
} from "@pipedream/sdk/browser";
// Or automatic browser resolution
import { createFrontendClient, type PipedreamClient } from "@pipedream/sdk";
// `tokenCallback` is also supported here
const client: PipedreamClient = createFrontendClient({
token: "connect-token",
externalUserId: "user-123",
});
// Connect an account using Pipedream Connect
client.connectAccount({
app: "github",
onSuccess: (result) => {
console.log("Account connected:", result.id);
},
onError: (error) => {
console.error("Connection failed:", error);
},
});
// Get user's accounts
const accounts = await client.getAccounts();
The v2.x SDK supports automatic configuration via environment variables:
// These environment variables are automatically used if set:
// PIPEDREAM_CLIENT_ID
// PIPEDREAM_CLIENT_SECRET
// PIPEDREAM_PROJECT_ID
// PIPEDREAM_PROJECT_ENVIRONMENT (defaults to 'production')
// You can initialize the client with minimal configuration
const client = new PipedreamClient({
projectId: "your-project-id", // Can also come from PIPEDREAM_PROJECT_ID
});
// If environment variables are set, you can even do:
const client = new PipedreamClient();
// This will use PIPEDREAM_CLIENT_ID, PIPEDREAM_CLIENT_SECRET, and PIPEDREAM_PROJECT_ID
In v2.x, all methods are namespaced. While you write TypeScript code using
camelCase (e.g., externalUserId), the SDK automatically converts these to
snake_case (e.g., external_user_id) when making API calls. For example,
client.runAction({ externalUserId: '...' }) becomes
client.actions.run({ externalUserId: '...' }) in your code, but the SDK sends
external_user_id to the API. This automatic conversion aligns with the
OpenAPI spec, but does
not apply to the following arguments:
- Client constructor parameters like
clientId,clientSecret,projectId,projectEnvironment, andworkflowDomain. - The props listed under
configuredProps(the naming follows whatever the corresponding component defines). - Request options like
timeoutInSeconds,maxRetries, andheaders(these remain in camelCase as they are not part of the API request body).
const result = await client.runAction({
externalUserId: "jverce",
actionId: "gitlab-list-commits",
configuredProps: {
gitlab: { authProvisionId: "apn_kVh9AoD" },
projectId: 45672541,
refName: "main",
},
});
const result = await client.actions.run({
externalUserId: "jverce",
id: "gitlab-list-commits",
configuredProps: {
gitlab: { authProvisionId: "apn_kVh9AoD" },
projectId: 45672541,
refName: "main",
},
});
const trigger = await client.deployTrigger({
externalUserId: "jverce",
triggerId: "gitlab-new-issue",
configuredProps: {
gitlab: {
authProvisionId: "apn_kVh9AoD",
},
projectId: 45672541,
},
webhookUrl: "https://events.example.com/gitlab-new-issue",
});
const trigger = await client.triggers.deploy({
externalUserId: "jverce",
id: "gitlab-new-issue",
configuredProps: {
gitlab: {
authProvisionId: "apn_kVh9AoD",
},
projectId: 45672541,
},
webhookUrl: "https://events.example.com/gitlab-new-issue",
});
// List accounts
const accounts = await client.getAccounts({
external_user_id: "jverce",
include_credentials: true,
});
// Get specific account
const account = await client.getAccountById("apn_kVh9AoD", {
include_credentials: true,
});
// List accounts
const accounts = await client.accounts.list({
externalUserId: "jverce",
includeCredentials: true,
});
// Get specific account
const account = await client.accounts.retrieve("apn_kVh9AoD", {
includeCredentials: true,
});
const token = await client.createConnectToken({
external_user_id: "jverce",
});
const token = await client.tokens.create({
externalUserId: "jverce",
});
// validateConnectToken was available in v1.x
const isValid = await client.validateConnectToken({
token: "connect-token-to-validate",
});
const validation = await client.tokens.validate({
token: "connect-token-to-validate",
});
const response = await client.configureComponent({
externalUserId: "jverce",
componentId: "gitlab-new-issue",
propName: "projectId",
configuredProps: {
gitlab: { authProvisionId: "apn_kVh9AoD" },
},
});
const response = await client.components.configureProp({
externalUserId: "jverce",
id: "gitlab-new-issue",
propName: "projectId",
configuredProps: {
gitlab: { authProvisionId: "apn_kVh9AoD" },
},
});
// Delete specific account
await client.deleteAccount("account-id");
// Delete all accounts for an app
await client.deleteAccountsByApp("app-id");
// Delete external user
await client.deleteExternalUser("jverce");
// Delete specific account
await client.accounts.delete("account-id");
// Delete all accounts for an app - functionality removed
// Consider using accounts.list() and deleting individually
// Delete external user - use users namespace
await client.users.delete({
externalUserId: "jverce",
});
const projectInfo = await client.getProjectInfo();
console.log(projectInfo.apps);
const project = await client.projects.retrieve();
console.log(project);
// v1.x uses a single method with two parameters
const response = await client.makeProxyRequest(
{
searchParams: {
external_user_id: "jverce",
account_id: "apn_kVh9AoD",
},
},
{
url: "https://api.example.com/data",
options: {
method: "GET",
headers: {
Accept: "application/json",
},
},
}
);
// POST request with body
const postResponse = await client.makeProxyRequest(
{
searchParams: {
external_user_id: "jverce",
account_id: "apn_kVh9AoD",
},
},
{
url: "https://api.example.com/users",
options: {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ name: "John Doe" }),
},
}
);
// v2.x uses separate methods for each HTTP verb
const response = await client.proxy.get({
externalUserId: "jverce",
accountId: "apn_kVh9AoD",
url: "https://api.example.com/data",
headers: {
Accept: "application/json",
},
params: {}, // Additional query parameters if needed
});
// POST request with body
const postResponse = await client.proxy.post({
externalUserId: "jverce",
accountId: "apn_kVh9AoD",
url: "https://api.example.com/users",
body: { name: "John Doe" }, // Body is passed as an object, not a string
headers: {
"Content-Type": "application/json",
},
});
// Other HTTP methods are available
await client.proxy.put({
/* ... */
});
await client.proxy.delete({
/* ... */
});
await client.proxy.patch({
/* ... */
});
// Invoke a workflow
const response = await client.invokeWorkflow(
"https://your-endpoint.m.pipedream.net",
{
foo: 123,
bar: "abc",
},
HTTPAuthType.OAuth // Optional auth type
);
// Invoke a workflow for an external user
const response = await client.invokeWorkflowForExternalUser(
"https://your-workflow-url.m.pipedream.net",
"jverce", // external user ID as second parameter
{
foo: 123,
bar: "abc",
}
);
// Invoke a workflow
const response = await client.workflows.invoke(
{
urlOrEndpoint: "https://your-endpoint.m.pipedream.net",
body: {
foo: 123,
bar: "abc",
},
headers: {
Accept: "application/json",
},
},
Pipedream.HTTPAuthType.OAuth
);
// Invoke a workflow for an external user
const response = await client.workflows.invokeForExternalUser({
urlOrEndpoint: "https://your-workflow-url.m.pipedream.net",
externalUserId: "jverce", // now part of the options object
body: {
foo: 123,
bar: "abc",
},
});
Here's a complete list of how v1.x methods map to v2.x namespaced methods:
| v1.x Method | v2.x Method |
|---|---|
runAction() | actions.run() |
getAccounts() | accounts.list() |
getAccountById() | accounts.retrieve() |
deleteAccount() | accounts.delete() |
deleteAccountsByApp() | Not available (use list + delete) |
deleteExternalUser() | users.delete() |
createConnectToken() | tokens.create() |
validateConnectToken() | tokens.validate() |
deployTrigger() | triggers.deploy() |
getDeployedTriggers() | deployedTriggers.list() |
getDeployedTrigger() | deployedTriggers.retrieve() |
updateDeployedTrigger() | deployedTriggers.update() |
deleteDeployedTrigger() | deployedTriggers.delete() |
getTriggerEvents() | deployedTriggers.listEvents() |
getTriggerWebhooks() | deployedTriggers.listWebhooks() |
updateTriggerWebhooks() | deployedTriggers.updateWebhooks() |
getTriggerWorkflows() | deployedTriggers.listWorkflows() |
updateTriggerWorkflows() | deployedTriggers.updateWorkflows() |
getUsers() | users.list() |
getUser() | users.retrieve() |
getApps() | apps.list() |
getApp() | apps.retrieve() |
getComponents() | components.list() |
getComponent() | components.retrieve() |
configureComponent() | components.configureProp() |
reloadComponentProps() | components.reloadProps() |
getProjectInfo() | projects.retrieve() |
makeProxyRequest() | proxy.get(), proxy.post(), etc. |
invokeWorkflow() | workflows.invoke() |
invokeWorkflowForExternalUser() | workflows.invokeForExternalUser() |
rawAccessToken() | rawAccessToken (getter property in server SDK) |
The v2.x SDK includes several new features not available in v1.x:
import { type RunActionResponse } from "@pipedream/sdk";
const result: RunActionResponse = await client.actions.run({
externalUserId: "jverce",
id: "gitlab-list-commits",
configuredProps: {
gitlab: { authProvisionId: "apn_kVh9AoD" },
projectId: 45672541,
refName: "main",
},
});
// Automatic pagination
for await (const account of client.accounts.list({
externalUserId: "jverce",
})) {
console.log(account);
}
// Manual pagination
const firstPage = await client.accounts.list({
externalUserId: "jverce",
limit: 20,
});
if (firstPage.hasNextPage()) {
const nextPage = await firstPage.getNextPage();
console.log(nextPage.data);
}
import { PipedreamError } from "@pipedream/sdk";
try {
await client.actions.run({
externalUserId: "jverce",
id: "gitlab-list-commits",
configuredProps: {
gitlab: { authProvisionId: "apn_kVh9AoD" },
projectId: 45672541,
refName: "main",
},
});
} catch (error) {
if (error instanceof PipedreamError) {
console.error("API Error:", error.status, error.message);
}
}
// Custom timeout
const result = await client.actions.run(
{
externalUserId: "jverce",
id: "gitlab-list-commits",
configuredProps: {
gitlab: { authProvisionId: "apn_kVh9AoD" },
projectId: 45672541,
refName: "main",
},
},
{
timeoutInSeconds: 30,
}
);
// Retry configuration
const result = await client.actions.run(
{
externalUserId: "jverce",
id: "gitlab-list-commits",
configuredProps: {
gitlab: { authProvisionId: "apn_kVh9AoD" },
projectId: 45672541,
refName: "main",
},
},
{
maxRetries: 3,
}
);
// Custom headers
const result = await client.actions.run(
{
externalUserId: "jverce",
id: "gitlab-list-commits",
configuredProps: {
gitlab: { authProvisionId: "apn_kVh9AoD" },
projectId: 45672541,
refName: "main",
},
},
{
headers: {
"X-Custom-Header": "value",
},
}
);
const controller = new AbortController();
// Abort after 5 seconds
setTimeout(() => controller.abort(), 5000);
try {
const result = await client.actions.run(
{
externalUserId: "jverce",
id: "gitlab-list-commits",
configuredProps: {
gitlab: { authProvisionId: "apn_kVh9AoD" },
projectId: 45672541,
refName: "main",
},
},
{
abortSignal: controller.signal,
}
);
} catch (error) {
if (error.name === "AbortError") {
console.log("Request was aborted");
}
}
const response = await client.actions
.run({
externalUserId: "jverce",
id: "gitlab-list-commits",
configuredProps: {
gitlab: { authProvisionId: "apn_kVh9AoD" },
projectId: 45672541,
refName: "main",
},
})
.withRawResponse();
console.log(response.data); // Parsed response data
console.log(response.rawResponse); // Original Response object
The v2.x SDK provides proper environment separation to ensure browser-safe imports without Node.js dependencies.
The SDK uses conditional exports to automatically serve the right code:
{ "exports": { ".": { "browser": "./dist/esm/browser/index.mjs", // Browser gets browser-only code "import": "./dist/esm/index.mjs", // Node.js gets full functionality "require": "./dist/cjs/index.js" }, "./browser": { "import": "./dist/esm/browser/index.mjs" // Explicit browser import }, "./server": { "import": "./dist/esm/index.mjs", // Explicit server import "require": "./dist/cjs/index.js" } } }
// For browser applications - avoids Node.js dependencies
import { PipedreamClient, createFrontendClient } from "@pipedream/sdk/browser";
// For server applications - includes full functionality
import { PipedreamClient } from "@pipedream/sdk/server";
// Automatic resolution (recommended for most cases)
import { PipedreamClient } from "@pipedream/sdk";
This ensures:
- Browser bundlers automatically get the browser-safe version
- Node.js environments get the full SDK with all server functionality
- Smaller bundle sizes for browser applications
- No Node.js dependency errors in browser builds
The v2.x SDK includes several new namespaces not available in v1.x:
apps- Browse available apps and integrationsappCategories- List app categoriescomponents- Work with componentsdeployedTriggers.listEvents()- List events for a deployed triggerdeployedTriggers.listWebhooks()- List webhooks for a deployed triggerdeployedTriggers.listWorkflows()- List workflows for a deployed triggerprojects- Get project informationproxy- Work with HTTP proxy endpointstriggers- Additional trigger operations beyond deploymentusers- User informationoauthTokens- OAuth token managementworkflows- Invoke workflows
If you are unable to migrate all your code at once, you can use the new SDK alongside the old one by leveraging package aliases. This allows you to migrate incrementally without breaking your existing codebase. To do this, you can install the new SDK with an alias:
npm install @pipedream/sdk-v2@npm:@pipedream/sdk@^2.0.0 --save
Then, in your code, you can import the new SDK with the alias:
import { createBackendClient } from "@pipedream/sdk";
import { PipedreamClient } from "@pipedream/sdk-v2";
const clientOpts = {
credentials: {
clientId,
clientSecret,
},
projectId,
environment,
};
const client = createBackendClient(clientOpts);
const newClient = new PipedreamClient({
...clientOpts.credentials,
projectEnvironment: clientOpts.environment,
projectId: clientOpts.projectId,
});
// Use old client for existing code
const oldResult = await client.runAction({
externalUserId: "jverce",
actionId: "gitlab-list-commits",
configuredProps: {
gitlab: { authProvisionId: "apn_kVh9AoD" },
projectId: 45672541,
refName: "main",
},
});
// Use new client for migrated code
const newResult = await newClient.actions.run({
externalUserId: "jverce",
id: "gitlab-list-commits",
configuredProps: {
gitlab: { authProvisionId: "apn_kVh9AoD" },
projectId: 45672541,
refName: "main",
},
});
Some methods from v1.x have been removed or changed significantly in v2.x:
-
deleteAccountsByApp()- This bulk deletion method is no longer available. You'll need to list accounts for an app and delete them individually. -
rawAccessToken()- The method has been changed to a getter property. For the server-side SDK (Pipedreamclass from@pipedream/sdk/serveror the wrapper), you can access the raw access token via therawAccessTokengetter property which returns a Promise:// v1.x (old) const token = await client.rawAccessToken(); // v2.x (new) const token = await client.rawAccessToken;For the base
PipedreamClientclass, token management is handled internally. -
Alternative method names - The v1.x SDK provided alternative method names (e.g.,
actionRun()as an alias forrunAction()). These are no longer available in v2.x. -
userIdparameter - The deprecateduserIdparameter has been removed. Always useexternalUserIdinstead.
- Update import statements from
createBackendClient/createFrontendClienttoPipedreamClient. - Update client initialization to use
new PipedreamClient()for both server-side and browser-side. - Convert all method calls to use namespaced format (e.g.,
client.actions.run()). - Keep parameter names in camelCase in your TypeScript/JavaScript code (the SDK handles conversion to snake_case automatically).
- Pass
externalUserIdto methods instead of setting it on the client. - Update error handling to use
PipedreamErrortype. - Review and implement new features like pagination and request options where beneficial.
- Replace any usage of removed methods with their alternatives.
- Update any code using
rawAccessToken()- for server-side code, you can accessclient.rawAccessTokenas a getter property that returns a Promise. - For raw response access, use
.withRawResponse()method chaining instead of passingincludeRawResponseoption. - Test all migrated code thoroughly.
- Remove the old SDK dependency once migration is complete.