> Source: https://wexa.ai/docs/connectors/test-user-connector-action

# test-user-connector-action

Run one action of a user-defined connector you may edit, with real inputs, while you build it. Needs the `fabric:skill.write` grant.

**Test an action**

**Wexa MCP server**

```bash
curl -sS -X POST https://fabric.wexa.ai/mcp/$FABRIC_PROJECT_ID \
  -H "authorization: Bearer $FABRIC_API_KEY" \
  -H "Mcp-Session-Id: $MCP_SESSION_ID" \
  -H "content-type: application/json" -H "accept: application/json" \
  -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"test-user-connector-action","arguments":{"connector_id":"6b1a3d5e7f9c0b2a4d6e8f02","action_key":"get_employee","inputs":{"employee_id":"E1"}}}}'
```

```json
{
  "content": [
    {
      "type": "text",
      "text": "{\"lifecycle_id\":\"qlc_000017\",\"result\":{\"success\":true,\"output\":{\"id\":\"E1\",\"name\":\"Asha Rao\"}}}"
    }
  ],
  "isError": false
}
```

**REST API**

```bash
curl -sS https://fabric.wexa.ai/v1/test-user-connector-action \
  -H "authorization: Bearer $FABRIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"connector_id":"6b1a3d5e7f9c0b2a4d6e8f02","action_key":"get_employee","inputs":{"employee_id":"E1"}}'
```

```json
{
  "lifecycle_id": "qlc_000017",
  "result": {
    "success": true,
    "output": {
      "id": "E1",
      "name": "Asha Rao"
    }
  }
}
```

**TypeScript SDK**

```ts
import { Fabric } from '@wexa-fabric/sdk'

const fabric = new Fabric()
const result = await fabric.testUserConnectorAction({
  connector_id: '6b1a3d5e7f9c0b2a4d6e8f02',
  action_key: 'get_employee',
  inputs: {
    employee_id: 'E1'
  }
})
```

```ts
// result is the payload itself, with no `.result` to read
{
  success: true,
  output: {
    id: 'E1',
    name: 'Asha Rao'
  }
}
```

**Python SDK**

```python
from wexa import Fabric

fabric = Fabric()
out = fabric.test_user_connector_action(
    connector_id="6b1a3d5e7f9c0b2a4d6e8f02",
    action_key="get_employee",
    inputs={
        "employee_id": "E1"
    },
)
```

```python
# out is the result, already unwrapped
{
    "success": True,
    "output": {
        "id": "E1",
        "name": "Asha Rao"
    }
}
```

## Parameters

| Parameter | Type | Required | Notes |
| --- | --- | --- | --- |
| `action_key` | string | Required | The action, by its `key`. Must not be empty. |
| `connector_id` | string | Required | The user-defined connector, from `list-user-connectors`. An unknown id is refused (404). A missing id, or a connector you may not edit, is refused (502); the message names which. |
| `inputs` | object | Optional | The action's inputs, by name. Defaults to none. |

**Show full response**

An example response, for an action that read one employee.

**Result of test-user-connector-action**

**REST API**

```json
{
  "lifecycle_id": "qlc_000017",
  "result": {
    "success": true,
    "output": {
      "id": "E1",
      "name": "Asha Rao"
    }
  }
}
```

**Wexa MCP server**

```json
{
  "content": [
    {
      "type": "text",
      "text": "{\"lifecycle_id\":\"qlc_000017\",\"result\":{\"success\":true,\"output\":{\"id\":\"E1\",\"name\":\"Asha Rao\"}}}"
    }
  ],
  "isError": false
}
```

**TypeScript SDK**

```ts
// the object you get back IS the result — there is no `.result` to read
{
  "success": true,
  "output": {
    "id": "E1",
    "name": "Asha Rao"
  }
}

// The TS SDK names these camelCase — lifecycleId, traceId — where Python uses
// lifecycle_id and trace_id. Both are non-enumerable: readable, but omitted by
// Object.keys() and JSON.stringify(). `result.lifecycleId` here is undefined.
result.lifecycleId // 'qlc_000017'
```

**Python SDK**

```python
# a dict subclass; `result` is already unwrapped
{
 "success": True,
 "output": {
  "id": "E1",
  "name": "Asha Rao"
 }
}

out.lifecycle_id  # 'qlc_000017' — an attribute, not a key
```

Keeping the `lifecycle_id` is what lets you ask later why a call was allowed, refused or held.

**More details**

**Response fields**

- `success`: Whether the action ran.
- `output`: What the action returned, when `success` is `true`.
- `fault`: When `success` is `false`: the `status` and `detail` the action failed with.

A live connector calls its API. An action that is not a `GET` really changes data there, so test it against data you can afford to change. A simulated connector returns simulated output.

A failed action is an answer, not an error: the call succeeds, with `success` set to `false` and the `fault` the action failed with.

The connector id in the example is illustrative. Swap it for one `list-user-connectors` returned to you.

Not marked consequential: it is the author's own test run of a connector they are building, and the default write gate does not hold it. It can still change data in the connector's API, so mind which action you run.

Every tool call works the same way: [How every tool call works](/docs/sdks-and-apis/how-every-tool-call-works).
