Official TypeScript SDK for interacting with the Captain Data Actions API.
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
.
- 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)
npm install @captaindatatech/sdk --save
# or
yarn add @captaindatatech/sdk
# or for this version
npm install @captaindatatech/sdk@25.702.924 --save
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:
- Log into the Captain Data Platform
- Go to Developer Settings
- Copy your API Key
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);
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:
Property | Description |
---|---|
raw |
The native fetch Response object, with full access if needed |
status |
HTTP status code (e.g., 200 , 404 ) |
statusText |
HTTP status text (e.g., "OK" , "Not Found" ) |
ok |
Boolean indicating if status is in the range 200–299 |
headers |
The native Response.headers object – use .get() to retrieve header values |
previousPage |
The value of the X-Pagination-Previous header, or null if not present |
nextPage |
The value of the X-Pagination-Next header, or null if not present |
data |
The 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.
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
anderror_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.
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 ofinput
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.
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 acron
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 (useschedule_at
if you want to delay). -
timezone
: IANA timezone to evaluate thecron
expression. Note that it is not compatible withschedule_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!
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.
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.
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 (users, 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.
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.
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.