save-user-connector
Create a user-defined connector as a private draft, or update one you may edit. Needs the fabric:skill.write grant.
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":"save-user-connector","arguments":{"connector_id":"6b1a3d5e7f9c0b2a4d6e8f02","credentials":{"api_key":"<api-key>"}}}}'{
"content": [
{
"type": "text",
"text": "{\"lifecycle_id\":\"qlc_000017\",\"result\":{\"connector_id\":\"6b1a3d5e7f9c0b2a4d6e8f02\",\"name\":\"Payroll\",\"category\":\"user_payroll\",\"mode\":\"live\",\"base_url\":\"https://payroll.example.com/v1\",\"lifecycle\":\"draft\",\"access_scope\":\"individual\",\"has_credentials\":true,\"actions\":[{\"key\":\"get_employee\",\"name\":\"Get employee\"}]}}"
}
],
"isError": false
}Parameters
| Parameter | Type | Required | Notes |
|---|---|---|---|
connector_id | string | Optional | Omit to create a draft; set to update that connector. An unknown id is refused (404). One you may not edit (another person's draft, or a published one when you are neither its author nor a project admin) is refused (502, user connector not found). |
credentials | object | Optional | Write-only secrets: api_key, token, username, password. Saved to the vault, never returned. A call needs definition, credentials or both. |
definition | object | Optional | The connector's definition. Required to create one: leave connector_id out and pass it. A definition the platform refuses gets its own reason (422). |
Errors
UpstreamError(502): the credentials could not be verified in the vault. Save them again.
Show full response
An example response, after saving an API key for a draft.
{
"content": [
{
"type": "text",
"text": "{\"lifecycle_id\":\"qlc_000017\",\"result\":{\"connector_id\":\"6b1a3d5e7f9c0b2a4d6e8f02\",\"name\":\"Payroll\",\"category\":\"user_payroll\",\"description\":\"Read employees from the payroll API.\",\"logo\":null,\"mode\":\"live\",\"base_url\":\"https://payroll.example.com/v1\",\"auth\":{\"type\":\"api_key\",\"name\":\"X-API-Key\",\"location\":\"header\"},\"headers\":{},\"connected\":false,\"lifecycle\":\"draft\",\"access_scope\":\"individual\",\"has_credentials\":true,\"user_id\":\"6a0f1e2d3c4b5a6978877665\",\"project_id\":\"6a0f1e2d3c4b5a6978877601\",\"org_id\":\"6a0f1e2d3c4b5a6978877600\",\"actions\":[{\"key\":\"get_employee\",\"name\":\"Get employee\",\"description\":\"One employee by id.\",\"input_schema\":{\"fields\":[{\"name\":\"employee_id\",\"type\":\"string\",\"required\":true}]},\"output_schema\":{\"fields\":[{\"name\":\"id\",\"type\":\"string\"},{\"name\":\"name\",\"type\":\"string\"}]},\"fault\":null,\"request\":{\"method\":\"GET\",\"path\":\"/employees/{employee_id}\",\"query\":[],\"headers\":{},\"body\":\"none\",\"result_path\":null}}]}}"
}
],
"isError": false
}Keeping the lifecycle_id is what lets you ask later why a call was allowed, refused or held.
More details
Response fields
The connector as it now stands, the same as get-user-connector returns it:
connector_id: The connector's id. Pass it to the other user-defined connector tools.name: Its name.category: Its category. A user-defined connector's category starts withuser_.description: Its description; empty when it has none.logo: Its logo, or null.mode:live(calls the real API) orsimulated.base_url: A live connector's base URL; every action's request path is appended to it.auth: How requests authenticate:typeisnone,api_key,bearerorbasic; forapi_key,nameis the header or query parameter andlocationisheaderorquery.headers: Static headers sent on every request.connected: Whether its actions are skills agents can use. Publishing connects it.lifecycle:draftorpublished.access_scope:individual(a draft, its author's alone),projectororganization.has_credentials: Whether credentials are saved. The credentials themselves are never returned.user_id: Its author.project_id: The project it belongs to.org_id: The organization it belongs to.actions: Its actions. Each has akey, aname, adescription, aninput_schema, anoutput_schema, afaultand, for a live connector, therequestit makes (method,path,query,headers,body,result_path).
To create a connector, pass its definition and leave connector_id out. To update one, pass its connector_id and a new definition, new credentials, or both. You may edit your own connectors, and a project admin may also edit a published one in this project.
The definition is name, description, mode (live or simulated), base_url, auth (type is none, api_key, bearer or basic, with name and location for an API key), headers, and actions. Each action has a key, a name, a description, an input_schema, an output_schema and, for a live connector, the request it makes (method, path, query, headers, body, result_path). import-connector-spec drafts one from an OpenAPI document.
credentials are write-only. Wexa keeps api_key, token, username and password, saves them to its vault, and never returns them. Do not put secrets in headers. The credentials argument is masked wherever Wexa records the call's arguments, and the answer never carries it.
The connector id in the example is illustrative. Swap it for one list-user-connectors returned to you.
Not marked consequential: a draft is its author's alone, so saving one affects nobody else, and the default write gate does not hold it. Publishing is the consequential step; see publish-user-connector.
Every tool call works the same way: How every tool call works.