Docs Concepts Connections
A connection stores authenticated credentials for an integration. Every time you need to interact with a third-party service — executing an action, enabling a trigger, or serving MCP tools — you need a connection.
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": "proj_abc123"
}' 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: 'proj_abc123' ,
}) 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 = "proj_abc123" ,
)
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: 'proj_abc123' ,
}),
})
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" : "proj_abc123" ,
},
)
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 https://api.weavz.io/api/v1/connect/session/cs_abc123 \
-H "Authorization: Bearer wvz_your_api_key" 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. getSession ( 'cs_abc123' ) from weavz_sdk import WeavzClient
client = WeavzClient( api_key = "wvz_your_api_key" )
# Step 2: Retrieve the session result
result = client.connect.get_session( "cs_abc123" )
session = result[ "session" ] // Step 2: Retrieve the session result
const res = await fetch ( 'https://api.weavz.io/api/v1/connect/session/cs_abc123' , {
headers: {
'Authorization' : 'Bearer wvz_your_api_key' ,
},
})
const { session } = await res. json () import httpx
# Step 2: Retrieve the session result
res = httpx.get(
"https://api.weavz.io/api/v1/connect/session/cs_abc123" ,
headers = { "Authorization" : "Bearer wvz_your_api_key" },
)
session = res.json()[ "session" ]
The session response includes a status field (pending, completed, or failed) and the resulting connection object 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" : "proj_abc123"
}
Tied to a specific end user . Best for personal accounts or per-user OAuth2 connections where each end user connects their own account.
For fine-grained multi-tenancy, tag connections with an externalId that maps to a user in your system:
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",
"externalId": "customer_789",
"displayName": "Customer 789 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' ,
externalId: 'customer_789' ,
displayName: 'Customer 789 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" ,
external_id = "customer_789" ,
display_name = "Customer 789 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' ,
externalId: 'customer_789' ,
displayName: 'Customer 789 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" ,
"externalId" : "customer_789" ,
"displayName" : "Customer 789 Slack" ,
"accessToken" : "xoxb-..." ,
},
)
data = res.json()
Then resolve a connection by external ID at execution time:
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": "proj_abc123",
"externalId": "customer_789"
}' import { WeavzClient } from '@weavz/sdk'
const client = new WeavzClient ({ apiKey: 'wvz_your_api_key' })
const { connection } = await client.connections. resolve ({
integrationName: 'slack' ,
workspaceId: 'proj_abc123' ,
externalId: 'customer_789' ,
}) from weavz_sdk import WeavzClient
client = WeavzClient( api_key = "wvz_your_api_key" )
result = client.connections.resolve(
integration_name = "slack" ,
workspace_id = "proj_abc123" ,
external_id = "customer_789" ,
)
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: 'proj_abc123' ,
externalId: 'customer_789' ,
}),
})
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" : "proj_abc123" ,
"externalId" : "customer_789" ,
},
)
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 its external ID, or let Weavz resolve it based on the current context:
Resolution priority:
Explicit connectionExternalId — if provided, find the connection tagged with that external ID
Workspace integration — if a workspaceId is provided, the workspace's integration configuration determines the connection based on its strategy (fixed, per_user, or per_user_with_fallback)
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.
PreviousIntegrations Next Actions