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

# Invoke a Connector via API

> Find a connector, get its connection, list its operations, and invoke any operation with curl — no agent or task required.

Every connector you set up at [app.xpander.ai/connectors](https://app.xpander.ai/connectors) can be called directly over REST. This page walks the full path end to end: **find the connector → get its `connection_id` → pick an operation → invoke it**.

## Base URL & Authentication

```text theme={"dark"}
https://api.xpander.ai
```

All requests require an API key passed as a header:

```text theme={"dark"}
x-api-key: YOUR_XPANDER_API_KEY
```

<Note>
  Your API key is already scoped to your organization — you do **not** need to pass an organization ID.
</Note>

## The three IDs you need

| ID              | What it is                                            | Where to get it                                                                                                                        |
| --------------- | ----------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `connector_id`  | The connector itself (e.g. Firecrawl)                 | The URL at `app.xpander.ai/connectors/{connector_id}`, or [List Tools](/api-reference/v1/tools/list-tools)                             |
| `connection_id` | Your org's authenticated connection to that connector | The `connections[].id` field in [List Tools](/api-reference/v1/tools/list-tools)                                                       |
| `operation_id`  | The specific action to run                            | [List Connector Operations](/api-reference/v1/tools/list-connector-operations) — accepts the operation's `id` **or** its `operationId` |

<Warning>
  The connector page URL in the app gives you the `connector_id` — but invoking also requires a `connection_id`, which is a different UUID. Step 1 below shows how to get it.
</Warning>

## Step 1 — Find the connector and its connection

Search your tool catalog by name:

```bash theme={"dark"}
curl "https://api.xpander.ai/v1/tools?type=connector&query=firecrawl" \
  -H "x-api-key: YOUR_XPANDER_API_KEY"
```

```json theme={"dark"}
{
  "items": [
    {
      "kind": "connector",
      "id": "11111111-2222-3333-4444-555555555555",
      "name": "Firecrawl",
      "status": "ready",
      "total_operations": 6,
      "using_built_in_auth": true,
      "connections": [
        {
          "id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
          "name": "Firecrawl",
          "access_scope": "organizational"
        }
      ]
    }
  ],
  "total": 1
}
```

Here `items[].id` is the **`connector_id`** and `items[].connections[].id` is the **`connection_id`**.

<Note>
  An empty `connections` array means the connector isn't connected yet — create a connection first with [Connect Connector](/api-reference/v1/tools/connect-connector) (OAuth2 connectors return a `connector_page_url` to finish auth in the browser).
</Note>

## Step 2 — List the operations

```bash theme={"dark"}
curl "https://api.xpander.ai/v1/tools/connectors/{connector_id}/operations?connection_id={connection_id}" \
  -H "x-api-key: YOUR_XPANDER_API_KEY"
```

```json theme={"dark"}
[
  {
    "id": "67e2daf399f31f9c55d127a7",
    "operationId": "FirecrawlScrapingServiceExtractWebpageContent",
    "path": "/scrape",
    "method": "post",
    "pretty_name": "Extract Webpage Content",
    "pretty_description": "Extracts content from a specified webpage URL."
  }
]
```

Either `id` or `operationId` works as the `operation_id` in the next steps.

## Step 3 (optional) — Inspect the operation's inputs

```bash theme={"dark"}
curl "https://api.xpander.ai/v1/tools/connectors/{connector_id}/connections/{connection_id}/{operation_id}/schema" \
  -H "x-api-key: YOUR_XPANDER_API_KEY"
```

The response's `input` field is a JSON schema with three groups — `body_params`, `query_params`, and `path_params` — which is exactly the structure the invoke call accepts.

## Step 4 — Invoke

```bash theme={"dark"}
curl -X POST "https://api.xpander.ai/v1/tools/connectors/{connector_id}/connections/{connection_id}/{operation_id}" \
  -H "x-api-key: YOUR_XPANDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "body_params": {
      "url": "https://example.com",
      "formats": ["markdown"]
    }
  }'
```

The response is the **target API's response**, passed through unchanged:

```json theme={"dark"}
{
  "success": true,
  "data": {
    "markdown": "# Example Domain\n\nThis domain is for use in documentation examples...",
    "metadata": {
      "title": "Example Domain",
      "sourceURL": "https://example.com",
      "statusCode": 200
    }
  }
}
```

### How the request body maps to the target API

| Field          | Purpose                              | Example                          |
| -------------- | ------------------------------------ | -------------------------------- |
| `body_params`  | The JSON body sent to the target API | `{"url": "https://example.com"}` |
| `query_params` | Query-string parameters, by name     | `{"limit": 10}`                  |
| `path_params`  | Path parameters, by name             | `{"crawlJobId": "abc123"}`       |
| `headers`      | Extra headers for the target API     | `{"Accept": "text/csv"}`         |

All four fields are optional — send only what the operation's schema requires. The operation always runs with its spec-defined HTTP method (a GET operation stays a GET), even though you call this endpoint with POST. The connection's stored credentials are applied automatically, and the call times out after 300 seconds.

<Tip>
  You can pass `_` as the `connector_id` and it will be resolved from the connection:
  `POST /v1/tools/connectors/_/connections/{connection_id}/{operation_id}`
</Tip>

## Common mistakes

| ❌ Doesn't work                                                  | ✅ Use instead                                                                                              |
| --------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| Using the connector page URL's UUID as `connection_id`          | That UUID is the `connector_id`; get `connection_id` from [List Tools](/api-reference/v1/tools/list-tools) |
| `Authorization: Bearer <key>` with an API key                   | `x-api-key: <key>`                                                                                         |
| Putting the target API's arguments at the top level of the body | Wrap them in `body_params` / `query_params` / `path_params`                                                |
| `GET /v1/tools/search?query=...` without `type`                 | Always pass `type` as well, e.g. `?query=firecrawl&type=connector`                                         |
