Docs Concepts Connections
A connection stores authenticated credentials for an integration. Use connections when an integration needs access to a third-party account, such as Slack, GitHub, Google Sheets, OpenAI, or another authenticated API.
Some integrations and actions do not require an external account. Utility and built-in integrations such as Datetime, Hash & Encode, Data Transformer, Storage, and KV Store can run without a connection. In those cases, omit connectionId and connectionExternalId; Weavz still scopes the call to your organization, workspace, MCP server, and end user where applicable.
Connections support multiple authentication methods depending on the integration:
For services like Slack, GitHub, and Google Sheets. Weavz provides a hosted connect page that handles the full OAuth2 authorization flow, including token exchange and PKCE.
curl TypeScript SDK Python SDK TypeScript Python
# Step 1: Create a connect token
curl -X POST https://api.weavz.io/api/v1/connect/token \
-H "Authorization: Bearer wvz_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"integrationName": "slack",
"connectionName": "My Slack",
"externalId": "my_slack",
"workspaceId": "550e8400-e29b-41d4-a716-446655440000"
}' import { WeavzClient } from '@weavz/sdk'
const client = new WeavzClient ({ apiKey: 'wvz_your_api_key' })
// Step 1: Create a connect token
const { token , connectUrl } = await client.connect. createToken ({
integrationName: 'slack' ,
connectionName: 'My Slack' ,
externalId: 'my_slack' ,
workspaceId: '550e8400-e29b-41d4-a716-446655440000' ,
}) from weavz_sdk import WeavzClient
client = WeavzClient( api_key = "wvz_your_api_key" )
# Step 1: Create a connect token
result = client.connect.create_token(
integration_name = "slack" ,
connection_name = "My Slack" ,
external_id = "my_slack" ,
workspace_id = "550e8400-e29b-41d4-a716-446655440000" ,
)
token = result[ "token" ]
connect_url = result[ "connectUrl" ] // Step 1: Create a connect token
const res = await fetch ( 'https://api.weavz.io/api/v1/connect/token' , {
method: 'POST' ,
headers: {
'Authorization' : 'Bearer wvz_your_api_key' ,
'Content-Type' : 'application/json' ,
},
body: JSON . stringify ({
integrationName: 'slack' ,
connectionName: 'My Slack' ,
externalId: 'my_slack' ,
workspaceId: '550e8400-e29b-41d4-a716-446655440000' ,
}),
})
const { token , connectUrl } = await res. json () import httpx
# Step 1: Create a connect token
res = httpx.post(
"https://api.weavz.io/api/v1/connect/token" ,
headers = { "Authorization" : "Bearer wvz_your_api_key" },
json = {
"integrationName" : "slack" ,
"connectionName" : "My Slack" ,
"externalId" : "my_slack" ,
"workspaceId" : "550e8400-e29b-41d4-a716-446655440000" ,
},
)
data = res.json()
token = data[ "token" ]
connect_url = data[ "connectUrl" ]
Open the returned connectUrl in a popup or redirect. After the user completes authorization, retrieve the session result:
curl TypeScript SDK Python SDK TypeScript Python
# Step 2: Retrieve the session result
curl -X POST https://api.weavz.io/api/v1/connect/session/poll \
-H "Content-Type: application/json" \
-d '{"token":"cst_your_connect_token"}' import { WeavzClient } from '@weavz/sdk'
const client = new WeavzClient ({ apiKey: 'wvz_your_api_key' })
// Step 2: Retrieve the session result
const session = await client.connect. wait (token) from weavz_sdk import WeavzClient
client = WeavzClient( api_key = "wvz_your_api_key" )
# Step 2: Retrieve the session result
session = client.connect.wait(token) // Step 2: Retrieve the session result
const res = await fetch ( 'https://api.weavz.io/api/v1/connect/session/poll' , {
method: 'POST' ,
headers: {
'Content-Type' : 'application/json' ,
},
body: JSON . stringify ({ token }),
})
const session = await res. json () import httpx
# Step 2: Retrieve the session result
res = httpx.post(
"https://api.weavz.io/api/v1/connect/session/poll" ,
json = { "token" : token},
)
session = res.json()
The session response includes a status field (PENDING, CONNECTING, COMPLETED, or FAILED) and the resulting connectionId when completed. OAuth2 token refresh is handled automatically.
For services like OpenAI and Twilio. Provide the secret value directly:
curl TypeScript SDK Python SDK TypeScript Python
curl -X POST https://api.weavz.io/api/v1/connections \
-H "Authorization: Bearer wvz_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"type": "SECRET_TEXT",
"integrationName": "openai",
"externalId": "my_openai",
"displayName": "Production OpenAI",
"secretText": "sk-your-openai-key"
}' import { WeavzClient } from '@weavz/sdk'
const client = new WeavzClient ({ apiKey: 'wvz_your_api_key' })
const { connection } = await client.connections. create ({
type: 'SECRET_TEXT' ,
integrationName: 'openai' ,
externalId: 'my_openai' ,
displayName: 'Production OpenAI' ,
secretText: 'sk-your-openai-key' ,
}) from weavz_sdk import WeavzClient
client = WeavzClient( api_key = "wvz_your_api_key" )
result = client.connections.create(
type = "SECRET_TEXT" ,
integration_name = "openai" ,
external_id = "my_openai" ,
display_name = "Production OpenAI" ,
secret_text = "sk-your-openai-key" ,
)
connection = result[ "connection" ] const res = await fetch ( 'https://api.weavz.io/api/v1/connections' , {
method: 'POST' ,
headers: {
'Authorization' : 'Bearer wvz_your_api_key' ,
'Content-Type' : 'application/json' ,
},
body: JSON . stringify ({
type: 'SECRET_TEXT' ,
integrationName: 'openai' ,
externalId: 'my_openai' ,
displayName: 'Production OpenAI' ,
secretText: 'sk-your-openai-key' ,
}),
})
const data = await res. json () import httpx
res = httpx.post(
"https://api.weavz.io/api/v1/connections" ,
headers = { "Authorization" : "Bearer wvz_your_api_key" },
json = {
"type" : "SECRET_TEXT" ,
"integrationName" : "openai" ,
"externalId" : "my_openai" ,
"displayName" : "Production OpenAI" ,
"secretText" : "sk-your-openai-key" ,
},
)
data = res.json()
For integrations requiring multiple fields (e.g., base URL + API key):
curl TypeScript SDK Python SDK TypeScript Python
curl -X POST https://api.weavz.io/api/v1/connections \
-H "Authorization: Bearer wvz_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"type": "CUSTOM_AUTH",
"integrationName": "airtable",
"externalId": "my_airtable",
"displayName": "My Airtable",
"props": {
"token": "pat_your_airtable_token"
}
}' import { WeavzClient } from '@weavz/sdk'
const client = new WeavzClient ({ apiKey: 'wvz_your_api_key' })
const { connection } = await client.connections. create ({
type: 'CUSTOM_AUTH' ,
integrationName: 'airtable' ,
externalId: 'my_airtable' ,
displayName: 'My Airtable' ,
props: {
token: 'pat_your_airtable_token' ,
},
}) from weavz_sdk import WeavzClient
client = WeavzClient( api_key = "wvz_your_api_key" )
result = client.connections.create(
type = "CUSTOM_AUTH" ,
integration_name = "airtable" ,
external_id = "my_airtable" ,
display_name = "My Airtable" ,
props = { "token" : "pat_your_airtable_token" },
)
connection = result[ "connection" ] const res = await fetch ( 'https://api.weavz.io/api/v1/connections' , {
method: 'POST' ,
headers: {
'Authorization' : 'Bearer wvz_your_api_key' ,
'Content-Type' : 'application/json' ,
},
body: JSON . stringify ({
type: 'CUSTOM_AUTH' ,
integrationName: 'airtable' ,
externalId: 'my_airtable' ,
displayName: 'My Airtable' ,
props: {
token: 'pat_your_airtable_token' ,
},
}),
})
const data = await res. json () import httpx
res = httpx.post(
"https://api.weavz.io/api/v1/connections" ,
headers = { "Authorization" : "Bearer wvz_your_api_key" },
json = {
"type" : "CUSTOM_AUTH" ,
"integrationName" : "airtable" ,
"externalId" : "my_airtable" ,
"displayName" : "My Airtable" ,
"props" : { "token" : "pat_your_airtable_token" },
},
)
data = res.json()
All connection credentials are encrypted at rest using AES-256. Secrets are never stored in plain text and are only decrypted when needed to make API calls to the third-party service.
Connections have two possible statuses:
Status Description ACTIVE Credentials are valid and ready to use ERROR An error occurred (e.g., OAuth2 token refresh failed)
Connections can be owned by an end user . When you create a connection through the end user connect portal or pass endUserId when creating a connection, that connection is linked to the end user.
This enables per-user connection management:
View connections — get all connections for a specific end user via GET /api/v1/end-users/:id
Automatic cleanup — when an end user is deleted, their connections are deleted too
Connection resolution — pass endUserId when executing actions or resolving connections, and Weavz finds the right connection based on the workspace's connection strategy
End users are auto-created when a connection is established through the hosted connect flow with an endUserId parameter, if the end user doesn't exist yet.
Connections can be scoped at three levels:
Available to everyone in the organization. Best for shared service accounts.
{
"integrationName" : "slack" ,
"displayName" : "Team Slack" ,
"scope" : "ORGANIZATION"
}
Available only within a specific workspace. Best for environment-specific credentials.
{
"integrationName" : "slack" ,
"displayName" : "Production Slack" ,
"scope" : "WORKSPACE" ,
"workspaceId" : "550e8400-e29b-41d4-a716-446655440000"
}
Tied to a specific end user . Best for personal accounts or per-user OAuth2 connections where each end user connects their own account.
Every connection has a Weavz UUID, and every connection you create also has an externalId. Use the connection externalId as a stable selector for that specific credential set, such as a shared customer Slack workspace or a project API key.
Connection externalId is not the default per-user identity model. For per-user OAuth and per-user credential routing, create end users and pass endUserId during execution.
curl TypeScript SDK Python SDK TypeScript Python
curl -X POST https://api.weavz.io/api/v1/connections \
-H "Authorization: Bearer wvz_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"type": "PLATFORM_OAUTH2",
"integrationName": "slack",
"workspaceId": "550e8400-e29b-41d4-a716-446655440000",
"externalId": "conn_customer_789_slack",
"displayName": "Customer 789 Shared Slack",
"accessToken": "xoxb-..."
}' import { WeavzClient } from '@weavz/sdk'
const client = new WeavzClient ({ apiKey: 'wvz_your_api_key' })
const { connection } = await client.connections. create ({
type: 'PLATFORM_OAUTH2' ,
integrationName: 'slack' ,
workspaceId: '550e8400-e29b-41d4-a716-446655440000' ,
externalId: 'conn_customer_789_slack' ,
displayName: 'Customer 789 Shared Slack' ,
accessToken: 'xoxb-...' ,
}) from weavz_sdk import WeavzClient
client = WeavzClient( api_key = "wvz_your_api_key" )
result = client.connections.create(
type = "PLATFORM_OAUTH2" ,
integration_name = "slack" ,
workspace_id = "550e8400-e29b-41d4-a716-446655440000" ,
external_id = "conn_customer_789_slack" ,
display_name = "Customer 789 Shared Slack" ,
access_token = "xoxb-..." ,
)
connection = result[ "connection" ] const res = await fetch ( 'https://api.weavz.io/api/v1/connections' , {
method: 'POST' ,
headers: {
'Authorization' : 'Bearer wvz_your_api_key' ,
'Content-Type' : 'application/json' ,
},
body: JSON . stringify ({
type: 'PLATFORM_OAUTH2' ,
integrationName: 'slack' ,
workspaceId: '550e8400-e29b-41d4-a716-446655440000' ,
externalId: 'conn_customer_789_slack' ,
displayName: 'Customer 789 Shared Slack' ,
accessToken: 'xoxb-...' ,
}),
})
const data = await res. json () import httpx
res = httpx.post(
"https://api.weavz.io/api/v1/connections" ,
headers = { "Authorization" : "Bearer wvz_your_api_key" },
json = {
"type" : "PLATFORM_OAUTH2" ,
"integrationName" : "slack" ,
"workspaceId" : "550e8400-e29b-41d4-a716-446655440000" ,
"externalId" : "conn_customer_789_slack" ,
"displayName" : "Customer 789 Shared Slack" ,
"accessToken" : "xoxb-..." ,
},
)
data = res.json()
Then resolve that connection by external ID when you need the connection record:
curl TypeScript SDK Python SDK TypeScript Python
curl -X POST https://api.weavz.io/api/v1/connections/resolve \
-H "Authorization: Bearer wvz_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"integrationName": "slack",
"workspaceId": "550e8400-e29b-41d4-a716-446655440000",
"externalId": "conn_customer_789_slack"
}' import { WeavzClient } from '@weavz/sdk'
const client = new WeavzClient ({ apiKey: 'wvz_your_api_key' })
const { connection } = await client.connections. resolve ({
integrationName: 'slack' ,
workspaceId: '550e8400-e29b-41d4-a716-446655440000' ,
externalId: 'conn_customer_789_slack' ,
}) from weavz_sdk import WeavzClient
client = WeavzClient( api_key = "wvz_your_api_key" )
result = client.connections.resolve(
integration_name = "slack" ,
workspace_id = "550e8400-e29b-41d4-a716-446655440000" ,
external_id = "conn_customer_789_slack" ,
)
connection = result[ "connection" ] const res = await fetch ( 'https://api.weavz.io/api/v1/connections/resolve' , {
method: 'POST' ,
headers: {
'Authorization' : 'Bearer wvz_your_api_key' ,
'Content-Type' : 'application/json' ,
},
body: JSON . stringify ({
integrationName: 'slack' ,
workspaceId: '550e8400-e29b-41d4-a716-446655440000' ,
externalId: 'conn_customer_789_slack' ,
}),
})
const data = await res. json () import httpx
res = httpx.post(
"https://api.weavz.io/api/v1/connections/resolve" ,
headers = { "Authorization" : "Bearer wvz_your_api_key" },
json = {
"integrationName" : "slack" ,
"workspaceId" : "550e8400-e29b-41d4-a716-446655440000" ,
"externalId" : "conn_customer_789_slack" ,
},
)
data = res.json()
When you execute an action or enable a trigger, Weavz resolves which connection to use. You can specify a connection explicitly by passing the connection's externalId as connectionExternalId, or let Weavz resolve it based on the current workspace integration context:
Resolution priority:
Explicit connectionExternalId — if provided, find the connection with that connection.externalId
Workspace integration — if workspaceId is provided, the workspace's integration configuration determines the connection based on its strategy (fixed, per_user, or per_user_with_fallback)
End-user context — if the strategy is per-user, pass endUserId so Weavz can resolve credentials linked to that end user
No connection — returns a CONNECTION_REQUIRED error
If you provide workspaceId and/or endUserId, explicit external-ID resolution is validated against that scope. Cross-workspace or cross-user matches are rejected.
Learn more about workspace integrations
curl TypeScript SDK Python SDK TypeScript Python
curl https://api.weavz.io/api/v1/connections \
-H "Authorization: Bearer wvz_your_api_key" import { WeavzClient } from '@weavz/sdk'
const client = new WeavzClient ({ apiKey: 'wvz_your_api_key' })
const { connections , total } = await client.connections. list () from weavz_sdk import WeavzClient
client = WeavzClient( api_key = "wvz_your_api_key" )
result = client.connections.list()
connections = result[ "connections" ] const res = await fetch ( 'https://api.weavz.io/api/v1/connections' , {
headers: {
'Authorization' : 'Bearer wvz_your_api_key' ,
},
})
const data = await res. json () import httpx
res = httpx.get(
"https://api.weavz.io/api/v1/connections" ,
headers = { "Authorization" : "Bearer wvz_your_api_key" },
)
data = res.json()
Filter by integration:
curl TypeScript SDK Python SDK TypeScript Python
curl "https://api.weavz.io/api/v1/connections?integrationName=slack" \
-H "Authorization: Bearer wvz_your_api_key" import { WeavzClient } from '@weavz/sdk'
const client = new WeavzClient ({ apiKey: 'wvz_your_api_key' })
// The list method returns all connections; filter client-side
const { connections } = await client.connections. list ()
const slackConnections = connections. filter (
( c : any ) => c.integrationName === 'slack'
) from weavz_sdk import WeavzClient
client = WeavzClient( api_key = "wvz_your_api_key" )
# The list method returns all connections; filter client-side
result = client.connections.list()
slack_connections = [
c for c in result[ "connections" ] if c[ "integrationName" ] == "slack"
] const res = await fetch ( 'https://api.weavz.io/api/v1/connections?integrationName=slack' , {
headers: {
'Authorization' : 'Bearer wvz_your_api_key' ,
},
})
const data = await res. json () import httpx
res = httpx.get(
"https://api.weavz.io/api/v1/connections" ,
headers = { "Authorization" : "Bearer wvz_your_api_key" },
params = { "integrationName" : "slack" },
)
data = res.json()
curl TypeScript SDK Python SDK TypeScript Python
curl -X DELETE https://api.weavz.io/api/v1/connections/{connectionId} \
-H "Authorization: Bearer wvz_your_api_key" import { WeavzClient } from '@weavz/sdk'
const client = new WeavzClient ({ apiKey: 'wvz_your_api_key' })
await client.connections. delete ( 'conn_abc123' ) from weavz_sdk import WeavzClient
client = WeavzClient( api_key = "wvz_your_api_key" )
client.connections.delete( "conn_abc123" ) const res = await fetch ( 'https://api.weavz.io/api/v1/connections/conn_abc123' , {
method: 'DELETE' ,
headers: {
'Authorization' : 'Bearer wvz_your_api_key' ,
},
})
const data = await res. json () import httpx
res = httpx.delete(
"https://api.weavz.io/api/v1/connections/conn_abc123" ,
headers = { "Authorization" : "Bearer wvz_your_api_key" },
)
data = res.json()
Deleting a connection does not disable triggers or remove MCP tools that use it — those will fail with a CONNECTION_REQUIRED error until a new connection is configured.
PreviousBuilt-In Workspace Integrations Next Actions