Productlane integration
Productlane is a customer support and product feedback platform built on Linear. With this API an agent can work the support inbox (list, create, update, bulk-update and delete threads, read and send messages, post internal comments, record timeline events, link threads to roadmap issues and projects), manage contacts, companies and blocked senders, publish changelogs (with tags, AI translation and email or Slack broadcasts), write the help center (articles, groups, tabs, review drafts, full-text search), manage roadmap projects and issues synced to Linear, thread tags and tag groups, reply snippets, import files, read portals and the public roadmap, and read support reports. Workspace settings, API keys, webhooks, SSO, custom domain, custom connectors, member invitations and roles, integrations, the coding agent, billing and bulk thread deletion are not exposed. Authentication is a v2 API key (pl_v2_...) sent as Authorization: Bearer; each route needs the scope named in its description.
Say what should happen.
The workflow builds itself.
What you can do with Productlane
Each of these is one operation on one endpoint, available both as a workflow step and as a tool an AI agent can call on its own. Nothing bundles several operations into one action, so what a run did stays readable afterwards.
Most endpoints run on the free plan. A few, mainly the ones that publish on your behalf, need a paid plan.
Group, 10 operations
create_docs_groupCreate docs groupPOSTCreate a help-center group. Requires the docs:write scope.create_tag_groupCreate tag groupPOSTCreate a tag group. Requires the tags:write scope.delete_docs_groupDelete docs groupDELETEHard-delete a help-center group. Articles in the group are detached, not deleted. Requires the docs:write scope.delete_tag_groupDelete tag groupDELETESoft-delete an empty tag group. Returns 409 if the group still owns any tags - move or delete those first. Requires the tags:write scope.get_docs_groupGet docs groupGETFetch a help-center group by id. Requires the docs:read scope.get_tag_groupGet tag groupGETFetch a tag group by id. Requires the tags:read scope.list_docs_groupsList docs groupsGETList help-center groups. Filter by portal with portal_instance_id. Requires the docs:read scope.list_tag_groupsList tag groupsGETList tag groups in the workspace. Use a returned `id` as `tag_group_id` when creating or moving a tag. Requires the tags:read scope.update_docs_groupUpdate docs groupPATCHUpdate a help-center group. Requires the docs:write scope.update_tag_groupUpdate tag groupPATCHUpdate a tag group. Requires the tags:write scope.
Company, 8 operations
add_contact_companyAdd contact companyPOSTAdd a company to the contact's memberships. Idempotent, and becomes the primary when the contact has none. Requires the contacts:write scope.create_companyCreate companyPOSTCreate a company. Linear customer is provisioned asynchronously once a domain is set. Requires the companies:write scope.delete_companyDelete companyDELETESoft-delete a company. Linear customer is deleted asynchronously and threads that lost the company link are reindexed. Requires the companies:write scope.get_companyGet companyGETFetch a company by id. Requires the companies:read scope.list_companiesList companiesGETList companies in the workspace. Cursor-paginated. Requires the companies:read scope.list_contact_companiesList contact companiesGETList every company this contact belongs to, primary first. Requires the contacts:read and companies:read scopes.remove_contact_companyRemove contact companyDELETERemove one of the contact's company memberships. When it was the primary, another membership takes over. Requires the contacts:write scope.update_companyUpdate companyPATCHUpdate a company. Linear identity fields are synced asynchronously. Requires the companies:write scope.
Issue, 6 operations
create_issueCreate issuePOSTCreate an issue, filed in Linear first and mirrored to Productlane. Requires Linear to be connected and the issues:write scope.delete_issueDelete issueDELETEArchive the issue in Linear and soft-delete it locally. Linear failures are logged but do not block the local soft-delete. Requires the issues:write scope.get_issueGet issueGETFetch an issue by id. Requires the issues:read scope.list_contact_issuesList contact issuesGETList issues this contact is linked to via customer needs on their threads. Cursor-paginated. Requires the contacts:read and issues:read scopes.list_issuesList issuesGETList roadmap issues in the workspace. Cursor-paginated. Requires the issues:read scope.update_issueUpdate issuePATCHUpdate an issue, synced to Linear. Linear sync failures are logged but do not block the local update. Requires the issues:write scope.
Project, 6 operations
create_projectCreate projectPOSTCreate a project, synced to Linear. Requires Linear to be connected and the projects:write scope.delete_projectDelete projectDELETEArchive the project in Linear and soft-delete it locally. Linear failures are logged but do not block the local soft-delete. Requires the projects:write scope.get_projectGet projectGETFetch a project by id. Requires the projects:read scope.list_contact_projectsList contact projectsGETList projects this contact is linked to via customer needs on their threads. Cursor-paginated. Requires the contacts:read and projects:read scopes.list_projectsList projectsGETList roadmap projects in the workspace. Cursor-paginated. Requires the projects:read scope.update_projectUpdate projectPATCHUpdate a project, synced to Linear. Linear sync failures are logged but do not block the local update. Requires the projects:write scope.
Tag, 6 operations
create_tagCreate tagPOSTCreate a thread tag. `tag_group_id` is required; fetch the workspace's groups via `list_tag_groups`. Requires the tags:write scope.delete_tagDelete tagDELETESoft-delete a tag. The tag is removed from any threads it was applied to. Requires the tags:write scope.get_tagGet tagGETFetch a tag by id. Requires the tags:read scope.get_tag_conversation_reportGet tag conversation reportGETThread count per tag for a date range, ordered by volume.list_tagsList tagsGETList thread tags in the workspace. Cursor-paginated. Requires the tags:read scope.update_tagUpdate tagPATCHUpdate a tag. Requires the tags:write scope.
Article, 5 operations
create_docs_articleCreate docs articlePOSTCreate a help-center article. Pass `language` to create a translation row instead of populating the base. Requires the docs:write scope.delete_docs_articleDelete docs articleDELETESoft-delete a help-center article. Requires the docs:write scope.get_docs_articleGet docs articleGETFetch a help-center article by id. Requires the docs:read scope.list_docs_articlesList docs articlesGETList help-center articles in the workspace. Pass sort=order to read them in the order the docs site renders. Cursor-paginated. Requires the docs:read scope.update_docs_articleUpdate docs articlePATCHUpdate a help-center article. content replaces the whole body and is refused when it drops an image the article still has (unless allow_image_removal). With language, it updates that translation. Requires docs:write.
Changelog, 5 operations
create_changelogCreate changelogPOSTCreate a changelog entry (unpublished unless published=true; publishing does not broadcast it). With language, the body goes to that translation row. Requires the changelogs:write scope.delete_changelogDelete changelogDELETESoft-delete a changelog. Requires the changelogs:write scope.get_changelogGet changelogGETFetch a changelog by id. Requires the changelogs:read scope.list_changelogsList changelogsGETList changelogs in the workspace. Cursor-paginated. Requires the changelogs:read scope.update_changelogUpdate changelogPATCHUpdate a changelog. content replaces the whole body: read it first with get_changelog and edit that. With language, translatable fields go to that translation. Requires the changelogs:write scope.
Contact, 5 operations
create_contactCreate contactPOSTCreate a contact. Requires the contacts:write scope.delete_contactDelete contactDELETESoft-delete a contact. Requires the contacts:write scope.get_contactGet contactGETFetch a contact by id. Requires the contacts:read scope.list_contactsList contactsGETList contacts in the workspace. Cursor-paginated. Requires the contacts:read scope.update_contactUpdate contactPATCHUpdate a contact. Requires the contacts:write scope.
Snippet, 5 operations
create_snippetCreate snippetPOSTCreate a reply snippet. Requires the Pro plan and the snippets:write scope.delete_snippetDelete snippetDELETESoft-delete a snippet. Requires the Pro plan and the snippets:write scope.get_snippetGet snippetGETFetch a snippet by id. Requires the Pro plan and the snippets:read scope.list_snippetsList snippetsGETList reply snippets in the workspace. Cursor-paginated. Requires the Pro plan and the snippets:read scope.update_snippetUpdate snippetPATCHUpdate a snippet. Requires the Pro plan and the snippets:write scope.
Tab, 5 operations
create_docs_tabCreate docs tabPOSTAdd a docs tab after the portal's other tabs; put groups in it with tab_id on create_docs_group or update_docs_group. Refused while the tab style is the header link.delete_docs_tabDelete docs tabDELETEDelete a docs tab. Its groups and articles move back to Documentation. An API reference can only be deleted from the dashboard.get_docs_tabGet docs tabGETFetch a docs tab by id.list_docs_tabsList docs tabsGETList the docs tabs in display order. Each portal also has a first tab, Documentation, which holds every group without a `tab_id`.update_docs_tabUpdate docs tabPATCHRename, change the icon of, or reorder a docs tab or an API reference.
Thread, 5 operations
create_threadCreate threadPOSTCreate a support thread and upsert its contact (by contact_email or contact_external_id), or import a whole conversation with messages. pain_level is required. Requires threads:write.delete_threadDelete threadDELETESoft-delete a thread. Requires the threads:write scope.get_threadGet threadGETFetch a thread by id. Use `expand` to inline messages and/or comments. Requires the threads:read scope.list_threadsList threadsGETList threads in the workspace. Cursor-paginated. Requires the threads:read scope.update_threadUpdate threadPATCHUpdate a thread (status, assignee, tags, company, pain level, AI draft). To change many threads use bulk_update_threads instead of looping. Requires the threads:write scope.
Changelog tag, 4 operations
create_changelog_tagCreate changelog tagPOSTCreate a tag that can be attached to changelogs. Give color, icon or both: with only color a colored dot is shown. Requires the Scale plan and the changelogs:write scope.delete_changelog_tagDelete changelog tagDELETEHard-delete a changelog tag. The tag is also unlinked from every changelog it was applied to. Requires the Scale plan and the changelogs:write scope.list_changelog_tagsList changelog tagsGETList tags that can be attached to changelogs. Requires the changelogs:read scope.update_changelog_tagUpdate changelog tagPATCHPatch a changelog tag's name, color, or icon. Pass `icon: null` to remove the icon and render a colored dot. Requires the Scale plan and the changelogs:write scope.
Comment, 4 operations
create_thread_commentCreate thread commentPOSTPost an internal comment on a thread. Visible to teammates only. Requires the comments:write scope.delete_thread_commentDelete thread commentDELETESoft-delete an internal comment. Requires the comments:write scope.list_thread_commentsList thread commentsGETList internal comments on a thread. Comments are visible to teammates only. Requires the threads:read scope.update_thread_commentUpdate thread commentPATCHEdit an internal comment. Requires the comments:write scope.
Blocked sender, 3 operations
block_senderBlock senderPOSTBlock an email address (type EMAIL) or a whole domain (type DOMAIN): blocked senders cannot create threads or post on existing ones. Requires the contacts:write scope.list_blocked_sendersList blocked sendersGETList blocked email addresses and domains in the workspace. Requires the contacts:read scope.unblock_senderUnblock senderDELETERemove a blocked sender entry. Requires the contacts:write scope.
Draft, 3 operations
create_docs_draftCreate docs draftPOSTPropose an article change for review: kind edit (article_id + content), create (title + content) or delete (article_id). submit_for_review=false keeps it a private draft. Requires docs:write.get_docs_draftGet docs draftGETFetch a single article draft by id.list_docs_draftsList docs draftsGETList article drafts (proposed edits, new articles or deletions), filterable by kind, status, article and group. Cursor-paginated. Requires the docs:read scope.
Activity, 2 operations
create_thread_activityCreate thread activityPOSTRecord a timeline event on a thread, optionally backdated (such as a routine run). Only records history: it changes no tag, issue or assignee, and cannot be deleted. Requires threads:write.list_thread_activitiesList thread activitiesGETList the timeline events on a thread, newest first: tags, importance, assignees, linked issues and routine runs. Cursor-paginated. Requires the threads:read scope.
Instance, 2 operations
get_portal_instanceGet portal instanceGETGet one portal instance with its sections, sign-in, links and theme. Requires the portal:read scope.list_portal_instancesList portal instancesGETList the workspace's portal instances. The Main (Root) portal is implicit and represented elsewhere as a null portal_instance_id. Requires the portal:read scope.
Message, 2 operations
list_thread_messagesList thread messagesGETList the conversation on a thread, merged across all channels and sorted oldest-first by default. Requires the threads:read scope.send_thread_messageSend thread messagePOSTSend a message to the customer on the thread's channel (email, Slack, live chat, Teams). validation_failed if that integration is off. Slack needs Pro, Teams Scale; messages:write.
Translate, 2 operations
translate_changelogTranslate changelogPOSTQueue an AI translation of a changelog into one language. Counts against the workspace's AI budget.translate_docs_articleTranslate docs articlePOSTQueue an AI translation of an article into one language. The translated row appears when the job finishes. Counts against the workspace's AI budget.
Accept, 1 operation
accept_docs_draftAccept docs draftPOSTAccept a draft: an edit writes a new article version, a create makes a new unpublished article, a delete soft-deletes the article. Answers superseded instead of accepted when it no longer applies.
Ai involvement, 1 operation
get_ai_involvement_reportGet ai involvement reportGETHow many conversations the AI answered, and how many closed without a human reply.
Ai spend, 1 operation
get_ai_spend_reportGet ai spend reportGETMonth-to-date AI spend, the monthly cap, and AI resolution usage against its limit. Requires the admin scope.
Broadcast, 1 operation
broadcast_changelogBroadcast changelogPOSTBroadcast a changelog: email=true emails subscribed contacts, slack=true posts to the connected Slack channels; at least one is required. Never changes published. Requires the Pro plan and changelogs:write.
Bulk update, 1 operation
bulk_update_threadsBulk update threadsPOSTApply one patch to up to 100 threads. The batch counts as a single write against the rate limit and reports per-thread rejects in `failed`. Requires the threads:write scope.
Conversation, 1 operation
get_conversation_volume_reportGet conversation volume reportGETConversation counts for a date range, split by state, reply status, and origin. Defaults to the last 30 days.
Customer need, 1 operation
link_thread_customer_needsLink thread customer needsPOSTLink a thread to one or more issues and/or projects via Linear's customer-need pipeline. Requires Linear to be connected and the threads:write scope.
Customer portal, 1 operation
get_customer_portal_viewGet customer portal viewGETReturns the requests a contact sees in their support portal, looked up by email. Requires the Scale plan and the portal:read scope.
Decline, 1 operation
decline_docs_draftDecline docs draftPOSTReject the draft. Keeps the row for audit but marks it as REJECTED so it stops appearing in the open queue.
Folder, 1 operation
list_snippet_foldersList snippet foldersGETList snippet folders in the workspace. Use a returned `id` as `folder_id` when creating or moving a snippet. Requires the Pro plan and the snippets:read scope.
Import, 1 operation
import_fileImport filePOSTStore a file from a public URL (up to 10 MB) or inline base64 (up to 1 MB) and return its CDN URL (file_url), usable as an image_url on articles and changelogs.
Linear option, 1 operation
get_company_linear_optionsGet company linear optionsGETReturns the Linear customer statuses, tiers and team members usable as a company owner (status_id, tier_id, owner_id). Fields are null when Linear is not connected. Requires companies:read.
Me, 1 operation
get_meGet meGETReturn the calling key's workspace_id, api_key_id and granted scopes, plus the workspace's Linear team selection (team ids needed by create_issue and create_project). Any valid key may call it.
Member, 1 operation
list_membersList membersGETList workspace members. Cursor-paginated. Requires the admin scope.
Merge, 1 operation
merge_companyMerge companyPOSTMerge source_id into this company: moves its threads, contacts and upvotes, fills empty properties, merges linked Linear customers, then deletes the source. Irreversible. Requires companies:write.
Move, 1 operation
move_docs_articlesMove docs articlesPOSTReassign articles to a group. Requires the docs:write scope.
Response time, 1 operation
get_response_times_reportGet response times reportGETAverage, median, and 90th percentile for first reply and resolution. Reads at most 5000 threads in the range.
Roadmap, 1 operation
get_public_roadmapGet public roadmapGETReturns the public roadmap as the portal renders it. Requires the portal:read scope.
Search, 1 operation
search_docs_articlesSearch docs articlesGETFull-text search across published help-center articles, ranked by relevance. Each result carries the article plus a snippet around the match. Requires the docs:read scope.
Status, 1 operation
list_project_statusesList project statusesGETList Linear project statuses configured at the organization level. Requires Linear to be connected and the projects:read scope.
Team, 1 operation
get_team_conversation_reportGet team conversation reportGETAssigned and resolved conversation counts per workspace member for a date range.
Workflow state, 1 operation
list_issue_workflow_statesList issue workflow statesGETList Linear workflow states for a team. Requires Linear to be connected and the issues:read scope.
Use Productlane from Claude Code, Cursor or Codex
Connect Productlane in LiveContext, create an API key in Settings, then add the LiveContext MCP server to your client. Its Productlane operations become tools the client can call, next to every other integration you connected.
claude mcp add --transport http livecontext https://livecontext.ai/mcp --header "X-API-Key: YOUR_API_KEY"[mcp_servers.livecontext]
url = "https://livecontext.ai/mcp"
[mcp_servers.livecontext.http_headers]
"X-API-Key" = "YOUR_API_KEY"{
"mcpServers": {
"livecontext": {
"type": "http",
"url": "https://livecontext.ai/mcp",
"headers": {
"X-API-Key": "YOUR_API_KEY"
}
}
}
}How to connect Productlane
- Create your workspace
Sign up free. Nothing to install.
- Connect Productlane once
Add your Productlane connection in Settings. Every tool from this integration reuses it, and secrets are encrypted at rest and visible only to you.
- Describe the job in chat
The workflow builds itself in front of you and picks the endpoints it needs. Drag the steps yourself on the canvas whenever you would rather be explicit.
Productlane integration FAQ
What can you do with the Productlane integration?
LiveContext exposes 110 operations on Productlane, covering group, company, issue and project.
