diff --git a/docs-v2/pages/connect/api.mdx b/docs-v2/pages/connect/api.mdx index e68fb4e0ed6f4..86de64dcf24cb 100644 --- a/docs-v2/pages/connect/api.mdx +++ b/docs-v2/pages/connect/api.mdx @@ -77,9 +77,7 @@ import { createClient } from "@pipedream/sdk/browser" import { serverConnectTokenCreate } from "./server" const { token, expires_at } = await serverConnectTokenCreate({ - app_slug: appSlug, // The app's name slug — see the quickstart - oauth_app_id: oauthAppId, // The OAuth app ID, if you're connecting an OAuth app — keep this in config / a DB, pass here - external_id: externalUserId // The end user's ID in your system + external_user_id: externalUserId // The end user's ID in your system }); export default function Home() { @@ -148,9 +146,9 @@ POST /tokens ##### Parameters -- `app_slug` - [The app's name slug](/quickstart#find-your-apps-name-slug) -- `oauth_app_id` - [The OAuth app ID](/quickstart#creating-a-custom-oauth-client), if you're connecting an OAuth app — keep this in config / a DB, pass here - `external_id` - [The external user ID](#external-users) in your system +- `success_redirect_uri` — _Optional_. The URL to redirect the user to after they successfully connect an account +- `error_redirect_uri` — _Optional_. The URL to redirect the user to if they encounter an error during the connection flow ##### Examples @@ -180,9 +178,7 @@ export async function serverConnectTokenCreate(opts: ConnectTokenCreateOpts): Pr } const { token, expires_at } = await serverConnectTokenCreate({ - app_slug: appSlug, // The app's name slug - oauth_app_id: oauthAppId, // The OAuth app ID, if you're connecting an OAuth app — keep this in config / a DB, pass here - external_id: externalUserId // The end user's ID in your system + external_user_id: externalUserId // The end user's ID in your system }); ``` @@ -225,8 +221,6 @@ const client = new Client({ }); const connectTokenOpts = { - app_slug: "YOUR_APP_SLUG", // The app's name slug - oauth_app_id: "o_abc123", // The OAuth app ID, if you're connecting an OAuth app — keep this in config / a DB, pass here external_id: "USER_ID" // The end user's ID in your system } @@ -272,14 +266,12 @@ class Client: # Usage example client = Client({ - 'public_key': 'YOUR_PUBLIC_KEY', - 'secret_key': 'YOUR_SECRET_KEY', + 'public_key': 'YOUR_PUBLIC_KEY', + 'secret_key': 'YOUR_SECRET_KEY', }) connect_token_opts = { - 'app_slug': "YOUR_APP_SLUG", - 'oauth_app_id': "o_abc123", - 'external_id': "USER_ID" + 'external_id': "USER_ID" } # Expose this code as an API endpoint in your server to fetch the token from the frontend @@ -313,7 +305,7 @@ public class Client { return "Basic " + encoded; } - public String connectTokenCreate(String appSlug, String oauthClientId, String externalId) throws Exception { + public String connectTokenCreate(String externalId) throws Exception { String auth = authorizationHeader(); URL url = new URL(baseURL + "/v1/connect/tokens"); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); @@ -322,7 +314,7 @@ public class Client { conn.setRequestProperty("Content-Type", "application/json"); conn.setDoOutput(true); - String jsonInputString = String.format("{\"app_slug\":\"%s\",\"oauth_app_id\":\"%s\",\"external_id\":\"%s\"}", appSlug, oauthClientId, externalId); + String jsonInputString = String.format("{\"external_id\":\"%s\"}", externalId); try (OutputStream os = conn.getOutputStream()) { byte[] input = jsonInputString.getBytes(StandardCharsets.UTF_8); @@ -336,7 +328,7 @@ public class Client { Client client = new Client("YOUR_SECRET_KEY", "YOUR_PUBLIC_KEY"); // Expose this code as an API endpoint in your server to fetch the token from the frontend - String response = client.connectTokenCreate("YOUR_APP_SLUG", "o_abc123", "USER_ID"); + String response = client.connectTokenCreate("USER_ID"); } } @@ -367,13 +359,13 @@ public class Client { return $"Basic {encoded}"; } - public async Task ConnectTokenCreate(string appSlug, string oauthClientId, string externalId) { + public async Task ConnectTokenCreate(string externalId) { string auth = AuthorizationHeader(); using (HttpClient client = new HttpClient()) { client.DefaultRequestHeaders.Add("Authorization", auth); client.DefaultRequestHeaders.Add("Content-Type", "application/json"); - var content = new StringContent($"{{\"app_slug\":\"{appSlug}\",\"oauth_app_id\":\"{oauthClientId}\",\"external_id\":\"{externalId}\"}}", Encoding.UTF8, "application/json"); + var content = new StringContent($"{{\"external_id\":\"{externalId}\"}}", Encoding.UTF8, "application/json"); var response = await client.PostAsync($"{baseURL}/v1/connect/tokens", content); return await response.Content.ReadAsStringAsync(); @@ -384,7 +376,7 @@ public class Client { var client = new Client("YOUR_SECRET_KEY", "YOUR_PUBLIC_KEY"); // Expose this code as an API endpoint in your server to fetch the token from the frontend - string response = await client.ConnectTokenCreate("YOUR_APP_SLUG", "o_abc123", "USER_ID"); + string response = await client.ConnectTokenCreate("USER_ID"); } } @@ -424,13 +416,11 @@ func (c *Client) authorizationHeader() string { return fmt.Sprintf("Basic %s", encoded) } -func (c *Client) ConnectTokenCreate(appSlug, oauthClientId, externalId string) (map[string]interface{}, error) { +func (c *Client) ConnectTokenCreate(externalId string) (map[string]interface{}, error) { auth := c.authorizationHeader() url := fmt.Sprintf("%s/v1/connect/tokens", c.BaseURL) opts := map[string]string{ - "app_slug": appSlug, - "oauth_app_id": oauthClientId, "external_id": externalId, } @@ -465,7 +455,7 @@ func main() { client := NewClient("YOUR_SECRET_KEY", "YOUR_PUBLIC_KEY") // Expose this code as an API endpoint in your server to fetch the token from the frontend - response, err := client.ConnectTokenCreate("YOUR_APP_SLUG", "o_abc123", "USER_ID") + response, err := client.ConnectTokenCreate( "USER_ID") if err != nil { fmt.Println("Error:", err) return @@ -496,13 +486,11 @@ class Client { return "Basic $encoded"; } - public function connectTokenCreate($appSlug, $oauthClientId, $externalId) { + public function connectTokenCreate($externalId) { $auth = $this->authorizationHeader(); $url = "$this->baseURL/v1/connect/tokens"; $data = json_encode([ - 'app_slug' => $appSlug, - 'oauth_app_id' => $oauthClientId, 'external_id' => $externalId ]); @@ -528,13 +516,11 @@ class Client { $client = new Client('YOUR_SECRET_KEY', 'YOUR_PUBLIC_KEY'); $connectTokenOpts = [ - 'app_slug' => "YOUR_APP_SLUG", - 'oauth_app_id' => "o_abc123", 'external_id' => "USER_ID" ]; // Expose this code as an API endpoint in your server to fetch the token from the frontend -$response = $client->connectTokenCreate($connectTokenOpts['app_slug'], $connectTokenOpts['oauth_app_id'], $connectTokenOpts['external_id']); +$response = $client->connectTokenCreate($connectTokenOpts['external_id']); ?> ``` @@ -564,7 +550,7 @@ class Client req = Net::HTTP::Post.new(uri) req['Authorization'] = authorization_header req['Content-Type'] = 'application/json' - req.body = { app_slug: app_slug, oauth_app_id: oauth_app_id, external_id: external_id }.to_json + req.body = { external_id: external_id }.to_json res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(req) @@ -577,13 +563,11 @@ end client = Client.new('YOUR_SECRET_KEY', 'YOUR_PUBLIC_KEY') connect_token_opts = { - app_slug: "YOUR_APP_SLUG", - oauth_app_id: "o_abc123", external_id: "USER_ID" } # Expose this code as an API endpoint in your server to fetch the token from the frontend -response = client.connect_token_create(connect_token_opts[:app_slug], connect_token_opts[:oauth_app_id], connect_token_opts[:external_id]) +response = client.connect_token_create(connect_token_opts[:external_id]) ``` diff --git a/docs-v2/pages/connect/quickstart.mdx b/docs-v2/pages/connect/quickstart.mdx index 85761d457f543..8b124b7e227cd 100644 --- a/docs-v2/pages/connect/quickstart.mdx +++ b/docs-v2/pages/connect/quickstart.mdx @@ -165,8 +165,6 @@ const client = new Client({ }); const connectTokenOpts = { - app_slug: "YOUR_APP_SLUG", // The app's name slug - oauth_app_id: "o_abc123", // The OAuth app ID, if you're connecting an OAuth app — keep this in config / a DB, pass here external_id: "USER_ID" // The end user's ID in your system } @@ -187,39 +185,37 @@ import json import requests class Client: - def __init__(self, opts): - self.secret_key = opts['secret_key'] - self.public_key = opts['public_key'] + def __init__(self, opts): + self.secret_key = opts['secret_key'] + self.public_key = opts['public_key'] - api_host = 'api.pipedream.com' - self.base_url = f"https://{api_host}" - - def _authorization_header(self): - encoded = base64.b64encode(f"{self.public_key}:{self.secret_key}".encode()).decode() - return f"Basic {encoded}" - - def connect_token_create(self, opts): - auth = self._authorization_header() - response = requests.post( - f"{self.base_url}/v1/connect/tokens", - headers={ - "Authorization": auth, - "Content-Type": "application/json", - }, - data=json.dumps(opts) - ) - return response.json() + api_host = 'api.pipedream.com' + self.base_url = f"https://{api_host}" + + def _authorization_header(self): + encoded = base64.b64encode(f"{self.public_key}:{self.secret_key}".encode()).decode() + return f"Basic {encoded}" + + def connect_token_create(self, opts): + auth = self._authorization_header() + response = requests.post( + f"{self.base_url}/v1/connect/tokens", + headers={ + "Authorization": auth, + "Content-Type": "application/json", + }, + data=json.dumps(opts) + ) + return response.json() # Usage example client = Client({ - 'public_key': 'YOUR_PUBLIC_KEY', - 'secret_key': 'YOUR_SECRET_KEY', + 'public_key': 'YOUR_PUBLIC_KEY', + 'secret_key': 'YOUR_SECRET_KEY', }) connect_token_opts = { - 'app_slug': "YOUR_APP_SLUG", - 'oauth_app_id': "o_abc123", - 'external_id': "USER_ID" + 'external_id': "USER_ID" } # Expose this code as an API endpoint in your server to fetch the token from the frontend @@ -253,7 +249,7 @@ public class Client { return "Basic " + encoded; } - public String connectTokenCreate(String appSlug, String oauthClientId, String externalId) throws Exception { + public String connectTokenCreate(String externalId) throws Exception { String auth = authorizationHeader(); URL url = new URL(baseURL + "/v1/connect/tokens"); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); @@ -262,7 +258,7 @@ public class Client { conn.setRequestProperty("Content-Type", "application/json"); conn.setDoOutput(true); - String jsonInputString = String.format("{\"app_slug\":\"%s\",\"oauth_app_id\":\"%s\",\"external_id\":\"%s\"}", appSlug, oauthClientId, externalId); + String jsonInputString = String.format("{\"external_id\":\"%s\"}", externalId); try (OutputStream os = conn.getOutputStream()) { byte[] input = jsonInputString.getBytes(StandardCharsets.UTF_8); @@ -276,7 +272,7 @@ public class Client { Client client = new Client("YOUR_SECRET_KEY", "YOUR_PUBLIC_KEY"); // Expose this code as an API endpoint in your server to fetch the token from the frontend - String response = client.connectTokenCreate("YOUR_APP_SLUG", "o_abc123", "USER_ID"); + String response = client.connectTokenCreate("USER_ID"); } } @@ -307,13 +303,13 @@ public class Client { return $"Basic {encoded}"; } - public async Task ConnectTokenCreate(string appSlug, string oauthClientId, string externalId) { + public async Task ConnectTokenCreate(string externalId) { string auth = AuthorizationHeader(); using (HttpClient client = new HttpClient()) { client.DefaultRequestHeaders.Add("Authorization", auth); client.DefaultRequestHeaders.Add("Content-Type", "application/json"); - var content = new StringContent($"{{\"app_slug\":\"{appSlug}\",\"oauth_app_id\":\"{oauthClientId}\",\"external_id\":\"{externalId}\"}}", Encoding.UTF8, "application/json"); + var content = new StringContent($"{{\"external_id\":\"{externalId}\"}}", Encoding.UTF8, "application/json"); var response = await client.PostAsync($"{baseURL}/v1/connect/tokens", content); return await response.Content.ReadAsStringAsync(); @@ -324,7 +320,7 @@ public class Client { var client = new Client("YOUR_SECRET_KEY", "YOUR_PUBLIC_KEY"); // Expose this code as an API endpoint in your server to fetch the token from the frontend - string response = await client.ConnectTokenCreate("YOUR_APP_SLUG", "o_abc123", "USER_ID"); + string response = await client.ConnectTokenCreate("USER_ID"); } } @@ -364,13 +360,11 @@ func (c *Client) authorizationHeader() string { return fmt.Sprintf("Basic %s", encoded) } -func (c *Client) ConnectTokenCreate(appSlug, oauthClientId, externalId string) (map[string]interface{}, error) { +func (c *Client) ConnectTokenCreate(externalId string) (map[string]interface{}, error) { auth := c.authorizationHeader() url := fmt.Sprintf("%s/v1/connect/tokens", c.BaseURL) opts := map[string]string{ - "app_slug": appSlug, - "oauth_app_id": oauthClientId, "external_id": externalId, } @@ -405,7 +399,7 @@ func main() { client := NewClient("YOUR_SECRET_KEY", "YOUR_PUBLIC_KEY") // Expose this code as an API endpoint in your server to fetch the token from the frontend - response, err := client.ConnectTokenCreate("YOUR_APP_SLUG", "o_abc123", "USER_ID") + response, err := client.ConnectTokenCreate("USER_ID") if err != nil { fmt.Println("Error:", err) return @@ -436,13 +430,11 @@ class Client { return "Basic $encoded"; } - public function connectTokenCreate($appSlug, $oauthClientId, $externalId) { + public function connectTokenCreate($externalId) { $auth = $this->authorizationHeader(); $url = "$this->baseURL/v1/connect/tokens"; $data = json_encode([ - 'app_slug' => $appSlug, - 'oauth_app_id' => $oauthClientId, 'external_id' => $externalId ]); @@ -468,13 +460,11 @@ class Client { $client = new Client('YOUR_SECRET_KEY', 'YOUR_PUBLIC_KEY'); $connectTokenOpts = [ - 'app_slug' => "YOUR_APP_SLUG", - 'oauth_app_id' => "o_abc123", 'external_id' => "USER_ID" ]; // Expose this code as an API endpoint in your server to fetch the token from the frontend -$response = $client->connectTokenCreate($connectTokenOpts['app_slug'], $connectTokenOpts['oauth_app_id'], $connectTokenOpts['external_id']); +$response = $client->connectTokenCreate($connectTokenOpts['external_id']); ?> ``` @@ -504,7 +494,7 @@ class Client req = Net::HTTP::Post.new(uri) req['Authorization'] = authorization_header req['Content-Type'] = 'application/json' - req.body = { app_slug: app_slug, oauth_app_id: oauth_app_id, external_id: external_id }.to_json + req.body = { external_id: external_id }.to_json res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(req) @@ -517,13 +507,11 @@ end client = Client.new('YOUR_SECRET_KEY', 'YOUR_PUBLIC_KEY') connect_token_opts = { - app_slug: "YOUR_APP_SLUG", - oauth_app_id: "o_abc123", external_id: "USER_ID" } # Expose this code as an API endpoint in your server to fetch the token from the frontend -response = client.connect_token_create(connect_token_opts[:app_slug], connect_token_opts[:oauth_app_id], connect_token_opts[:external_id]) +response = client.connect_token_create(connect_token_opts[:external_id]) ``` @@ -534,9 +522,7 @@ In our Next.js app, we call the `serverConnectTokenCreate` method from the front import { serverConnectTokenCreate } from "./server" const { token, expires_at } = await serverConnectTokenCreate({ - app_slug: appSlug, // The app's name slug, passed from the frontend - oauth_app_id: oauthAppId, // The OAuth app ID, if you're connecting an OAuth app — keep this in config / a DB, pass here - external_id: externalUserId // The end user's ID in your system + external_user_id: externalUserId // The end user's ID in your system }); ``` diff --git a/packages/sdk/src/server/__tests__/server.test.ts b/packages/sdk/src/server/__tests__/server.test.ts index b79235f406a2b..cdc4a266fa47a 100644 --- a/packages/sdk/src/server/__tests__/server.test.ts +++ b/packages/sdk/src/server/__tests__/server.test.ts @@ -243,7 +243,6 @@ describe("ServerClient", () => { }); const result = await client.connectTokenCreate({ - app_slug: "test-app", external_user_id: "user-id", }); @@ -256,9 +255,54 @@ describe("ServerClient", () => { expect.objectContaining({ method: "POST", body: JSON.stringify({ + external_user_id: "user-id", + external_id: "user-id", + }), + headers: expect.objectContaining({ + "Authorization": expect.any(String), + "Content-Type": "application/json", + }), + }), + ); + }); + + it("should create a connect token with optional redirect URIs", async () => { + fetchMock.mockResponseOnce( + JSON.stringify({ + token: "connect-token-with-redirects", + expires_at: "2024-01-01T00:00:00Z", + }), + { + headers: { + "Content-Type": "application/json", + }, + }, + ); + + client = new ServerClient({ + publicKey: "test-public-key", + secretKey: "test-secret-key", + }); + + const result = await client.connectTokenCreate({ + external_user_id: "user-id", + success_redirect_uri: "https://example.com/success", + error_redirect_uri: "https://example.com/error", + }); + + expect(result).toEqual({ + token: "connect-token-with-redirects", + expires_at: "2024-01-01T00:00:00Z", + }); + expect(fetchMock).toHaveBeenCalledWith( + "https://api.pipedream.com/v1/connect/tokens", + expect.objectContaining({ + method: "POST", + body: JSON.stringify({ + external_user_id: "user-id", + success_redirect_uri: "https://example.com/success", + error_redirect_uri: "https://example.com/error", external_id: "user-id", - app_slug: "test-app", - oauth_app_id: undefined, }), headers: expect.objectContaining({ "Authorization": expect.any(String), diff --git a/packages/sdk/src/server/index.ts b/packages/sdk/src/server/index.ts index 981cfc26ee607..07068777b725a 100644 --- a/packages/sdk/src/server/index.ts +++ b/packages/sdk/src/server/index.ts @@ -42,16 +42,6 @@ export type CreateServerClientOpts = { * Options for creating a Connect token. */ export type ConnectTokenCreateOpts = { - /** - * https://pipedream.com/docs/connect/quickstart#find-your-apps-name-slug - */ - app_slug: string; - - /** - * Pass for OAuth apps. See https://pipedream.com/docs/connect/quickstart#creating-a-custom-oauth-client - */ - oauth_app_id?: string; - /** * An external user ID associated with the token. */ @@ -556,7 +546,6 @@ export class ServerClient { * * ```typescript * const tokenResponse = await client.connectTokenCreate({ - * app_slug: "your-app-slug", * external_user_id: "external-user-id", * }); * console.log(tokenResponse.token); @@ -564,9 +553,8 @@ export class ServerClient { */ public async connectTokenCreate(opts: ConnectTokenCreateOpts): Promise { const body = { + ...opts, external_id: opts.external_user_id, - app_slug: opts.app_slug, - oauth_app_id: opts.oauth_app_id, }; return this.makeConnectRequest("/tokens", { method: "POST",