This SDK provides a unified interface to interact with Captain Data’s API using a single entry point: the CaptainData class. It simplifies authentication and gives access to the core api and multiple integrations such as linkedin, and salesnavigator.

✨ Features

  • Unified CaptainData interface
  • Individual API clients: core, linkedin, salesnavigator, etc.
  • Auto-generated TypeScript types for safety and autocompletion
  • Built using OpenAPI Generator with the typescript-fetch generator and custom templates
  • Supports modern async/await and Fetch API
  • Supports ES6 Language level (es2019 and newer)
  • Supports CommonJS and ES6 module systems
  • Can be used in both Typescript and Javascript. In TypeScript, the definition will be automatically resolved via package.json. (Reference)

πŸ“¦ Installation

npm install @captaindatatech/sdk --save
# or
yarn add @captaindatatech/sdk
# or for this version
npm install {{npmName}}@{{npmVersion}} --save

πŸ” Authentication

Each user has their own unique API Key tied to their account. API Keys are not shared across the workspace. To get your API Key:
  1. Log into the Captain Data Platform
  2. Go to Developer Settings
  3. Copy your API Key

πŸš€ Usage

Basic Usage

import { CaptainData } from '@captaindatatech/sdk';

// Initialize the SDK with your API Key
const CAPTAIN_DATA_API_KEY = "your_api_key"; // for production code, you should use environment variables and add proper check

const cd = new CaptainData({ apiKey: CAPTAIN_DATA_API_KEY });

// Example: Use the Core client
const workspaceResponse = await cd.core.getWorkspaces();
console.log(workspaceResponse.data);

// Example: Use the LinkedIn client
const { data: profile } = await cd.linkedin.extractPeople({ input: {linkedin_profile_url: "https://www.linkedin.com/in/guillaumeodier"} });
console.log(profile);

// Example: Use the Sales Navigator client
// !!!You need a linkedin account with an active Sales Navigator subscription!!!
const params = {
    input: {
        sales_navigator_profile_search_url: "https://www.linkedin.com/sales/search/people?query=(...)"
    },
    parameters: {
        exclude_crm_contacts: true,
        exclude_viewed_leads: true
    }
}

const searchResults = await cd.salesnavigator.searchPeople(params);
console.log(searchResults);

Responses

All SDK operations return an enhanced Response wrapper that provides access to the full HTTP response as well as convenience methods to work with its content and metadata. This design allows you to: β€’ Inspect HTTP status, headers, and success flags β€’ Parse and access the response body easily β€’ Handle paginated endpoints with built-in pagination helpers πŸ” Structure of the Response Object The returned object includes:
PropertyDescription
rawThe native fetch Response object, with full access if needed
statusHTTP status code (e.g., 200, 404)
statusTextHTTP status text (e.g., "OK", "Not Found")
okBoolean indicating if status is in the range 200–299
headersThe native Response.headers object – use .get() to retrieve header values
previousPageThe value of the X-Pagination-Previous header, or null if not present
nextPageThe value of the X-Pagination-Next header, or null if not present
dataThe parsed body of the response (lazily evaluated on first access)
// Full response object with metadata and parsed body
const profileRes = await cd.linkedin.extractPeople({
  input: { linkedin_profile_url: "https://www.linkedin.com/in/guillaumeodier" }
});

// Accessing status information
console.log(profileRes.status);       // e.g., 200
console.log(profileRes.statusText);   // e.g., "OK"
console.log(profileRes.ok);           // true if status is 2xx

// Accessing response headers (native fetch Headers object)
console.log(profileRes.headers.get("Content-Type"));

// Using pagination headers
console.log(profileRes.previousPage);
console.log(profileRes.nextPage);

// Accessing parsed response body
console.log(profileRes.data);

// Convenient destructuring when you only need the data
const { data: profile } = await cd.linkedin.extractPeople({
  input: { linkedin_profile_url: "https://www.linkedin.com/in/guillaumeodier" }
});

console.log(profile);

πŸ’‘ Tip Use the ok flag to easily gate logic on successful requests:
const res = await cd.linkedin.extractPeople({ input });

if (!res.ok) {
  throw new Error(`Request failed with status ${res.status}`);
}

console.log(res.data);

This gives you fine-grained control over both successful and unsuccessful responses, while keeping your codebase clean and predictable.

Error handling

API calls can fail, and production-ready code should always handle errors properly. When an error occurs, the SDK throws a ResponseError, which extends the native Error object and adds:
  • response: the raw Fetch Response object
  • body: the decoded API error body (already parsed from JSON)
try {
    const profileRes = await cd.linkedin.extractPeople({ input: {linkedin_profile_url: "https://www.linkedin.com/in/john-doe"} });
    console.log(profileRes.data);
} catch(error) {
    console.error("[ERR] Extract People", error.message, error.response.status);
    console.error(error.body);
}
The body follows the API error definition. For more details, check about errors in the API doc. Each error response includes:
  • error_label: A machine-readable identifier for the error type
  • error_scope: Indicates which part of the request caused the error (e.g., β€œinput”, β€œauth”, β€œserver”)
  • error_ref: A unique reference code for tracking and debugging
  • message: A human-readable description of the error
  • status_code: The HTTP status code
  • params: Additional error parameters (if any)
Common HTTP status codes:
  • 200: The request was successful (some API calls may return 201 instead)
  • 400: Bad Request - Invalid input or parameters
  • 401: Unauthorized - Invalid or missing API key
  • 403: Forbidden - Insufficient permissions
  • 404: Not Found - Resource doesn’t exist
  • 500: Internal Server Error - Server-side issue
πŸ’‘ Tips
Always check the error_label and error_scope fields to programmatically handle different types of errors in your application.
If you encounter an unusual error, such as a 500 or 503, feel free to reach out! These are internal errors on our end, and we’re happy to help resolve them.

Async execution mode Usage

All the actions that can benefit of being executed in async mode will have β€œAsync” suffixed methods, corresponding to the API async endpoints (for example Extract LinkedIn People Async). This means a few things for the expected params:
  • inputs: you can now pass an array of input to batch fetch the results
  • callback:
    • url: the url, on your side, where we will stream you the results
    • headers: an array of { name: string, value: string} header’s definitions we will include on each call of your url
Your url will receive the following payload format:
{
  "run": {
    "run_uid": "string",
    "batch_uid": "string",
    "status": "CREATED" || "INVALID" || "QUEUED" || "SCHEDULED" || "BLOCKED" || "STOPPED" || "RUNNING" || "FAILED" || "PARTIAL_SUCCEEDED" || "SUCCEEDED",
  },
  "input": {} || null,
  "error": {} || null,
  "results": [] || null
}
Example of an async call:
const inputs = [
  // live like inputs
  { linkedin_profile_url: "https://www.linkedin.com/in/guillaumeodier" },
  { linkedin_profile_url: "https://www.linkedin.com/in/marcfrancis961" }
];

const result = await cd.linkedin.extractPeopleAsync({
  inputs,
  callback: {
    url: "https://your.callback.url.app.com/captaindata",
    headers: [
      { name: "Authorization", value: "your-token" },
      { name: "greetings", value: "Coucou from France" }
    ]
  }
});

// Let's wait for results on your callback url!

where:
  • input match the input of the corresponding live action
  • error match the error format (see β€œError handling”)
  • results is an array of results that match the response format of the corresponding live action
A new callback should be issued for each input or page if the result for an input has several pages internally. You don’t have to bother with that and just process the results as soon as they arrive so the load on your platform will stay low and dispatched over time. If you want to restrict the number of results, note that you have the parameters.max_results param on actions that need it.

Schedule execution mode Usage

All the actions that can benefit of being executed in schedule mode will have β€œSchedule” suffixed methods, corresponding to the API schedule endpoints (for example Extract LinkedIn People Schedule). Basically, it is an async execution, so it shares all the async specifics described above, but we added some params to plan future executions:
  • schedule_at: ISO 8601 datetime. It will define the next execution date (defaults to UTC). If you use a cron expression the recurrence will start at the first occurence after this datetime
  • cron: a * * * * * cron format expression to schedule repeated executions. By default it will be UTC based and start to evaluate immediately (use schedule_at if you want to delay).
  • timezone: IANA timezone to evaluate the cron expression. Note that it is not compatible with schedule_at that will always use the timezone of the datetime expression
β›” Note: CRON intervals below 15 minutes are currently blocked (feel free to reach out if you have a special near real-time needs) Example of a schedule call:
const inputs = [
  {linkedin_profile_url: "https://www.linkedin.com/in/guillaumeodier"},
  {linkedin_profile_url: "https://www.linkedin.com/in/marcfrancis961"}
];

const result = await cd.linkedin.extractPeopleSchedule({
  // Async like params
  inputs,
  callback: {
    url: "https://your.callback.url.app.com/captaindata",
    headers: [
      { name: "Authorization", value: "your-token" },
      { name: "greetings", value: "Coucou from France" }
    ]
  },
  // Schedule specific params
  schedule_at: "2100-06-26T13:10:58+02:00",
  cron: "0 7 * * *",
  timezone: "Europe/Paris"
});

// Let's wait for results on your callback url!

Account Rotation

Actions are performed over third-party services, the integrations (LinkedIn, Sales Navigator,…). Most of the time, those services need authenticated accounts to be able to do their job. If you’re new to Captain Data, we strongly recommend reviewing the following resources before diving into the API and the SDK:
  • Quickstart – A brief overview of how to use the API.
  • Core Concepts – A description of core objects and how to interact with them.
You need to have at least one identity connected to an integration account corresponding to the actions you want to use. For example, to perform LinkedIn actions, you have to connect a valid LinkedIn integration to an identity. By default, action calls will try to find the appropriate accounts on your workspace and dispatch the load over them: this is called account rotation and is proven usefull to run a bunch of actions like batch data enrichments. The identity_ids body param is an array of identity uids that allows you to better control the identities used to execute your call. You can then dedicate some identities and their integration accounts to specific tasks.

Core methods

The core scope (CaptainData.core) provides methods to manage operationnal entities used by the Captain Data platform. For example, you can find methods to:
  • manage identities: the building block of integration management
  • manage integrations: the connection to a specific 3rd party platform to be able to perform the actions
  • manage the schedules, the runs, the callbacks,…: insights of what you triggered on the platform
  • … more to come, we’re moving fast!
To better understand how Captain Data allows you to build great things, be sure to take a look at the Quickstart guide and a deeper explanation of our Core Concepts.

🧠 SDK Structure

Captain Data api allows to interact with several 3rd party services called integrations (linkedin, salesnavigator,…). The actions allowed for each integration are exposed under scoped client for each integration.
const cd = new CaptainData({ apiKey: 'your_api_key_here' });

cd.core            // Core platform endpoints (identities, workspaces, etc.)
cd.linkedin        // LinkedIn-specific actions
cd.salesnavigator  // Sales Navigator-specific actions

// More integrations to be added under the same predictable pattern.
Scopes are always lower case alpha identifiers. The actions are then corresponding to the actions names you will find in the API Reference or in the Captain Data SaaS stripped from the integration identifier prefixes.

πŸ“˜ API Reference

The full API reference is available at: Captain Data API Docs This SDK is auto-generated from our OpenAPI specification. A full SDK reference is also auto-generated under the installed package docs/ if needed.

❓ FAQ

Q: Can I use this SDK in Node.js and browser environments? A: Yes! It supports both environments as it is based on fetch. For Node.js, make sure to install a polyfill like node-fetch.