> ## Documentation Index
> Fetch the complete documentation index at: https://docs.edges.run/llms.txt
> Use this file to discover all available pages before exploring further.

# SDK Setup

> Official TypeScript SDK for interacting with the Edges API.

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

## ✨ Features

* Unified `Edges` interface
* Individual API clients: `core`, `linkedin`, `salesnavigator`, etc.
* Auto-generated TypeScript types for safety and autocompletion
* Built using [OpenAPI Generator](https://openapi-generator.tech/) 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](https://www.typescriptlang.org/docs/handbook/declaration-files/consumption.html))

## 📦 Installation

```bash theme={null}
npm install @edgesrun/sdk --save
# or
yarn add @edgesrun/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 [Edges Platform](https://app.edges.run)
2. Go to [**Developer Settings**](https://app.edges.run/settings/developers)
3. Copy your API Key

## 🚀 Usage

### Basic Usage

```ts theme={null}
import { Edges } from '@edgesrun/sdk';

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

const ed = new Edges({ apiKey: EDGES_API_KEY });

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

// Example: Use the LinkedIn client
const { data: profile } = await ed.linkedin.extractPeople({ input: {linkedin_profile_url: "https://uk.linkedin.com/in/philip-wookey-8642939b"} });
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 ed.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

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 containing the cursor URL, or `null` if not present |
| `data`         | The parsed body of the response (lazily evaluated on first access)                              |

<Note>
  For paginated endpoints, `nextPage` contains a URL with a `cursor` parameter. Use this URL directly for the next request. Cursors expire after 24 hours. See the [Pagination Guide](/v1/runs/pagination) for details.
</Note>

```ts theme={null}
// Full response object with metadata and parsed body
const profileRes = await ed.linkedin.extractPeople({
  input: { linkedin_profile_url: "https://uk.linkedin.com/in/jouni-paavola-1ba10063" }
});

// 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 ed.linkedin.extractPeople({
  input: { linkedin_profile_url: "https://www.linkedin.com/in/lee-swepston-4367b628/" }
});

console.log(profile);

```

> 💡 Use the `ok` flag to easily gate logic on successful requests:

```ts theme={null}
const res = await ed.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)

```ts theme={null}
try {
    const profileRes = await ed.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](https://docs.edges.run/v1/faq-troubleshooting#troubleshooting-errors).

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

<Tip>Always check the `error_label` and `error_scope` fields to programmatically handle different types of errors in your application.</Tip>

<Info>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.</Info>

### 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](https://docs.edges.run/v1/api/actions/linkedin-extract-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:

```json theme={null}
{
  "run": {
    "run_uid": "string",
    "batch_uid": "string",
    "status": "CREATED" || "INVALID" || "QUEUED" || "SCHEDULED" || "BLOCKED" || "STOPPED" || "RUNNING" || "FAILED" || "PARTIAL_SUCCEEDED" || "SUCCEEDED",
  },
  "input": {} || null,
  "custom_data": {} || null,
  "error": {} || null,
  "results": [] || null
}
```

Example of an `async` call:

```javascript theme={null}
const inputs = [
  { linkedin_profile_url: "https://it.linkedin.com/in/nair-marques-3459748a" },
  { linkedin_profile_url: "https://lv.linkedin.com/in/innadjeri" }
];

const result = await ed.linkedin.extractPeopleAsync({
  inputs,
  callback: {
    url: "https://your.callback.url.app.com/from-sdk",
    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 is issued for each input or page when results span multiple pages.

You can process results as they arrive to keep your platform load low and distributed over time.
To limit the number of results, use the `parameters.max_results` parameter available on relevant actions.

### 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](https://docs.edges.run/v1/api/actions/linkedin-extract-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](https://en.wikipedia.org/wiki/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](https://en.wikipedia.org/wiki/Cron) 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](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) to evaluate the `cron` expression. Note that it is not compatible with `schedule_at` that will always use the timezone of the datetime expression

<Warning>CRON intervals below 15 minutes are currently blocked. Contact support if you require shorter intervals for real-time use cases.</Warning>

Example of a `schedule` call:

```javascript theme={null}
const inputs = [
  {linkedin_profile_url: "https://uk.linkedin.com/in/martin-stevens-a7176965"},
  {linkedin_profile_url: "https://ch.linkedin.com/in/ptlugonarantes"}
];

const result = await ed.linkedin.extractPeopleSchedule({
  inputs,
  callback: {
    url: "https://your.callback.url.app.com/edges",
    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"
});
```

### 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 Edges, we strongly recommend reviewing the following resources before diving into the API and the SDK:

* [Quickstart](https://docs.edges.run/v1/quickstart) – A brief overview of how to use the API.
* [Core Concepts](https://docs.edges.run/v1/core-concepts) – A description of core objects and how to interact with them.

You need to have at least one [identity](https://app.edges.run/identities) 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](https://app.edges.run/integrations/linkedin)
to an [identity](https://app.edges.run/identities).

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 (`Edges.core`) provides methods to manage operational entities used by the Edges platform.

Available methods include:

* **Identities**: The building blocks of integration management
* **Integrations**: Connections to third-party platforms that enable action execution
* **Schedules, runs, and callbacks**: Insights into platform activities and triggered operations
* Additional methods are continuously being added as the platform evolves

To better understand how Edges allows you to build great things, be sure to take a look at the [Quickstart guide](https://docs.edges.run/v1/quickstart)
and a deeper explanation of our [Core Concepts](https://docs.edges.run/v1/core-concepts).

## 🧠 SDK Structure

The Edges API allows you to interact with various third-party services through integrations (LinkedIn, Sales Navigator, and more).
Actions available for each integration are exposed through dedicated scoped clients.

```ts theme={null}
const ed = new Edges({ apiKey: 'your_api_key_here' });

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

Scopes are always lower case alpha identifiers.

These actions correspond to the action names found in the [API Reference](https://docs.edges.run/v1/api/introduction)
or [Edges SaaS](https://app.edges.run/actions), with integration identifier prefixes removed.

## 📘 API Reference

The full API reference is available at: [Edges API Docs](https://docs.edges.run/v1/api/introduction)

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.
