CONNECT APP
Build with Slab
Knowledge Base & Wiki Software
Productivity
- API key
MCP
Give your agent Slab tools
Every Slab action is exposed as an MCP tool on Pipedream's remote server. Point a client at it with your end user's ID and Connect resolves that user's Slab account for each tool call — you store no tokens.
// accessToken: mint a short-lived token with the Connect SDK — see the MCP guide
const transport = new StreamableHTTPClientTransport(
new URL("https://remote.mcp.pipedream.net/v3"),
{
requestInit: {
headers: {
Authorization: `Bearer ${accessToken}`,
"x-pd-project-id": "{project_id}",
"x-pd-environment": "production",
"x-pd-external-user-id": "{external_user_id}", // any stable ID for this user in your system
"x-pd-app-slug": "slab",
},
},
},
)
const mcp = new Client({ name: "my-agent", version: "1.0.0" })
await mcp.connect(transport)
const { tools } = await mcp.listTools()
// e.g. run Add Topic To Post:
const result = await mcp.callTool({
name: "slab-add-topic-to-post",
arguments: {
postId: "Post ID",
topicId: "Topic ID",
},
})# access_token: mint a short-lived token with the Connect SDK — see the MCP guide
headers = {
"Authorization": f"Bearer {access_token}",
"x-pd-project-id": "{project_id}",
"x-pd-environment": "production",
"x-pd-external-user-id": "{external_user_id}", # any stable ID for this user in your system
"x-pd-app-slug": "slab",
}
async with streamablehttp_client("https://remote.mcp.pipedream.net/v3", headers=headers) as (read, write, _):
async with ClientSession(read, write) as session:
await session.initialize()
tools = await session.list_tools()
# e.g. run Add Topic To Post:
result = await session.call_tool("slab-add-topic-to-post", {
"postId": "Post ID",
"topicId": "Topic ID",
})API PROXY
Call the Slab API directly
For an endpoint with no pre-built tool, the Connect proxy forwards your request to the Slab API with the connected user's credentials attached. You store no tokens and write no refresh logic.
const resp = await pd.proxy.get({
externalUserId: "{external_user_id}", // any stable ID for this user in your system
accountId: "apn_xxxxxxx",
url: "https://api.slab.com/v1/graphql",
})
// Any allowed Slab endpoint works here. Pipedream attaches the
// connected account's credentials to the outgoing request.# The path segment is the target URL, URL-safe base64 encoded:
# https://api.slab.com/v1/graphql
curl "https://api.pipedream.com/v1/connect/{project_id}/proxy/aHR0cHM6Ly9hcGkuc2xhYi5jb20vdjEvZ3JhcGhxbA?external_user_id={external_user_id}&account_id=apn_xxxxxxx" \
-H "Authorization: Bearer {access_token}" \
-H "x-pd-environment: production"SDK
Run Slab actions from your backend
Connect a user's Slab account once, then run Add Topic To Post on their behalf from your own code — TypeScript, Python, or plain HTTP.
import { PipedreamClient } from "@pipedream/sdk"
const pd = new PipedreamClient({
projectId: process.env.PIPEDREAM_PROJECT_ID!,
clientId: process.env.PIPEDREAM_CLIENT_ID!,
clientSecret: process.env.PIPEDREAM_CLIENT_SECRET!,
projectEnvironment: "production",
})
const result = await pd.actions.run({
id: "slab-add-topic-to-post",
externalUserId: "{external_user_id}", // any stable ID for this user in your system
configuredProps: {
slab: { authProvisionId: "apn_xxxxxxx" },
postId: "Post ID",
topicId: "Topic ID",
},
})from pipedream import Pipedream
pd = Pipedream(
client_id="{oauth_client_id}",
client_secret="{oauth_client_secret}",
project_id="{project_id}",
project_environment="production",
)
result = pd.actions.run(
id="slab-add-topic-to-post",
external_user_id="{external_user_id}", # any stable ID for this user in your system
configured_props={
"slab": {"authProvisionId": "apn_xxxxxxx"},
"postId": "Post ID",
"topicId": "Topic ID",
},
)curl -X POST https://api.pipedream.com/v1/connect/{project_id}/actions/run \
-H "Content-Type: application/json" \
-H "X-PD-Environment: production" \
-H "Authorization: Bearer {access_token}" \
-d '{
"external_user_id": "{external_user_id}",
"id": "slab-add-topic-to-post",
"configured_props": {
"slab": { "authProvisionId": "apn_xxxxxxx" },
"postId": "Post ID",
"topicId": "Topic ID"
}
}'TOOLS
Slab actions
On-demand operations your product or agent can configure and run on behalf of a connected user.
-
Add Topic To Post
actionAssociate a topic with a post via theaddTopicToPostGraphQL mutation, returning the topic. Run Search Posts to obtain the post ID and List Topics to obtain the topic ID before calling. Example: postIdabc123, topicIdabc12defreturns{"id":"abc12def","name":"Engineering"}. See the documentation.Writev0.0.1 -
Create Post
actionCreate a new post in Slab via thecreatePostGraphQL mutation, returning the full post object (e.g.{"id":"abc123","title":"Q3 Onboarding Guide","topics":[{"id":"abc12def","name":"Engineering"}]}). If Content is provided, the body is appended after creation via theupdatePostContentmutation (the Slab schema does not accept content at creation time). Slab derives the displayed title from the first line of the post's content, so the appended text is inserted after the existing title line rather than replacing it — this preserves Title instead of overwriting it. NOTE: the returnedcontentfield reflects the pre-append snapshot (title line only) even though the append is applied — treat a non-error response as confirmation, not the returnedcontent. New posts are published by default (set Published tofalseto leave it as an unpublished draft) — unpublished posts do not appear in Search Posts/List Posts results. Run List Topics to obtain a Topic ID to pass at creation. See the documentation.Writev0.0.1 -
Get Posts
actionGet one or more Slab posts by their IDs, returning full post objects including content, owner, and associated topics. Use Search Posts first to discover post IDs; this action does not list or search. Accepts up to 100 IDs per call. Example: postIds["abc123"]returns[{"id": "abc123", "title": "Engineering Onboarding Guide", "owner": {"id": "u1", "name": "Alice"}, "topics": [{"id": "abc12def", "name": "Engineering"}], "content": "..."}]. Pass Fields (e.g.["id","title","owner"]) to trim large fields likecontentfrom each result when only metadata is needed. See the documentation.Read-onlyv0.1.0 -
List Posts
actionList all posts in the Slab organization (no filter). This action is superseded by Search Posts, which accepts an optional Query string and can list all posts when Query is empty. Prefer Search Posts for new workflows. Returns{ posts, pageInfo }—postsis an array of post objects (e.g.{"id": "abc123", "title": "Engineering Onboarding Guide", "owner": {"id": "u1", "name": "Alice"}, "topics": [{"id": "abc12def", "name": "Engineering"}]}). Only forward pagination is supported: whenpageInfo.hasNextPageistrue, passpageInfo.endCursoras After to retrieve the next page. Pass Fields (e.g.["id","title","owner"]) to trim large fields likecontentfrom each post when only metadata is needed. See the documentation.Read-onlyv1.0.0 -
List Topics
actionList all topics in the Slab organization via theorganization { topics }GraphQL query, returning an array of topic objects withidandname(e.g.[{"id":"abc12def","name":"Engineering"}]). This is the picker action agents should call to obtain topic IDs for Create Post, Add Topic To Post, and Remove Topic From Post. There is no root topics-listing query, so this reads the organization's topics field. See the documentation.Read-onlyv0.0.1 -
List Users
actionList all users in the Slab organization via theorganization { users }GraphQL query, returning an array of user objects withid,name, andemail(e.g.[{"id":"u1","name":"Alice","email":"alice@example.com"}]). This is the picker action agents should call to obtain a user ID for Update Post's Owner ID. See the documentation.Read-onlyv0.0.1 -
Remove Topic From Post
actionDisassociate a topic from a post via theremoveTopicFromPostGraphQL mutation, returning the topic. This only removes the association (reversible with Add Topic To Post); it does not delete the post or the topic. Run Search Posts for the post ID and List Topics for the topic ID before calling. Example: postIdabc123, topicIdabc12defreturns{"id":"abc12def","name":"Engineering"}. See the documentation.Writev0.0.1 -
Search Posts
actionList or search posts in the Slab organization via the GraphQLsearchendpoint. Leave Query empty to list all posts; provide a Query string to full-text search. This is the picker action agents should call to obtain post IDs for Get Posts, Update Post, Add Topic To Post, and Remove Topic From Post. Returns{ posts, pageInfo }—postsis an array of post objects (e.g.{"id": "abc123", "title": "Engineering Onboarding Guide", "owner": {"id": "u1", "name": "Alice"}, "topics": [{"id": "abc12def", "name": "Engineering"}]}). Only forward pagination is supported: whenpageInfo.hasNextPageistrue, passpageInfo.endCursoras After to retrieve the next page. Pass Fields (e.g.["id","title","owner"]) to trim large fields likecontentfrom each post when only metadata is needed. See the documentation.Read-onlyv1.0.0 -
Update Post
actionUpdate a post's metadata and access settings via theupdatePostGraphQL mutation, returning the updated post object. Manages link access (sharing), owner, archived/published state, and banner. NOTE: this mutation does NOT change title or content; use Update Post Content for the body (there is no title-update field in the schema). Run Search Posts first to obtain the post ID. Example: postIdabc123, archivedtruereturns{"id":"abc123","title":"Q3 Onboarding Guide","archivedAt":"2026-01-01T00:00:00Z","linkAccess":"INTERNAL"}. See the documentation.Writev0.0.1 -
Update Post Content
actionReplace or edit a post's body via theupdatePostContentGraphQL mutation. Content must be supplied as a Quill delta (see https://quilljs.com/docs/delta/) wrapped in an{"ops":[...]}object, passed as a JSON string — the API rejects a native/unwrapped delta object at the GraphQL layer. IMPORTANT: Slab derives the post's displayed title from the first line of its content — there is no independent title field after creation. An op with{"retain":0}(or no leading retain) inserts at the very start WITHOUT deleting anything — it pushes the existing content later in the document, so it can change what displays as the title without removing the old title text (which still exists, just no longer on the first line). To actually replace the title, delete the existing title's range —{"delete":N}where N is the old title line's length — then insert the replacement. To append body text while preserving the title, first read the post's currentcontent(via Search Posts or Get Posts) and lead with aretaincount covering the existing title line's length. This is a distinct endpoint from Update Post (which handles metadata/access only, and cannot change title). Run Search Posts first to obtain the post ID. Example (append after a 20-character title line): postIdabc123, delta{"ops":[{"retain":20},{"insert":"Additional body text.\n"}]}— a non-error response confirms the edit was accepted. CRITICAL: this mutation applies your delta positionally against whatever the post's content actually is at the moment the call runs — there is no version check, and the response reflects the pre-edit snapshot, not the result. Always re-read the post's currentcontent(Search Posts or Get Posts) immediately before computing a delta, and if you need to make a second edit to the same post, re-read again first — never compute a new delta from an earlier read or from this action's own response. Offsets computed against a stale snapshot land in the wrong place and silently corrupt the document instead of erroring; they do not queue safely. See the documentation.Writev0.0.1
No Slab triggers are available yet.
- App slug
- slab
- Authentication
- API key
- Categories
- Productivity
- Actions
- 10
- Triggers
- 0
- API proxy
- Available