curl --request POST \
--url https://app.gtm-api.com/linkedin/v4/api/linkedin-posting/comment \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'Team-SID: <api-key>' \
--data '
{
"linkedin_account_sid": "<string>",
"entity_urn": "<string>",
"text": "<string>",
"parent_comment_urn": "<string>",
"mentions": [
{
"profile_id": "<string>",
"name": "<string>"
}
]
}
'import requests
url = "https://app.gtm-api.com/linkedin/v4/api/linkedin-posting/comment"
payload = {
"linkedin_account_sid": "<string>",
"entity_urn": "<string>",
"text": "<string>",
"parent_comment_urn": "<string>",
"mentions": [
{
"profile_id": "<string>",
"name": "<string>"
}
]
}
headers = {
"Authorization": "Bearer <token>",
"Team-SID": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
Authorization: 'Bearer <token>',
'Team-SID': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
linkedin_account_sid: '<string>',
entity_urn: '<string>',
text: '<string>',
parent_comment_urn: '<string>',
mentions: [{profile_id: '<string>', name: '<string>'}]
})
};
fetch('https://app.gtm-api.com/linkedin/v4/api/linkedin-posting/comment', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.gtm-api.com/linkedin/v4/api/linkedin-posting/comment",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'linkedin_account_sid' => '<string>',
'entity_urn' => '<string>',
'text' => '<string>',
'parent_comment_urn' => '<string>',
'mentions' => [
[
'profile_id' => '<string>',
'name' => '<string>'
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"Team-SID: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.gtm-api.com/linkedin/v4/api/linkedin-posting/comment"
payload := strings.NewReader("{\n \"linkedin_account_sid\": \"<string>\",\n \"entity_urn\": \"<string>\",\n \"text\": \"<string>\",\n \"parent_comment_urn\": \"<string>\",\n \"mentions\": [\n {\n \"profile_id\": \"<string>\",\n \"name\": \"<string>\"\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Team-SID", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://app.gtm-api.com/linkedin/v4/api/linkedin-posting/comment")
.header("Authorization", "Bearer <token>")
.header("Team-SID", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"linkedin_account_sid\": \"<string>\",\n \"entity_urn\": \"<string>\",\n \"text\": \"<string>\",\n \"parent_comment_urn\": \"<string>\",\n \"mentions\": [\n {\n \"profile_id\": \"<string>\",\n \"name\": \"<string>\"\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.gtm-api.com/linkedin/v4/api/linkedin-posting/comment")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Team-SID"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"linkedin_account_sid\": \"<string>\",\n \"entity_urn\": \"<string>\",\n \"text\": \"<string>\",\n \"parent_comment_urn\": \"<string>\",\n \"mentions\": [\n {\n \"profile_id\": \"<string>\",\n \"name\": \"<string>\"\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"operation": "action",
"action": "<string>",
"item": "<unknown>",
"result": {
"comment_urn": "<string>",
"activity_log": {}
},
"meta": {
"trace_id": "<string>",
"span_id": "<string>",
"timestamp": "<string>",
"duration_ms": 1,
"team_sid": "<string>",
"actor_type": "<string>"
}
}{
"success": false,
"error": {
"code": "validation_failed",
"message": "<string>",
"recoverable": true,
"suggestion": "<string>",
"field_errors": {},
"blockers": [
{
"type": "<string>",
"severity": "hard",
"description": "<string>",
"entity_sid": "<string>",
"resolution": "<string>",
"resolution_hint": "<string>",
"count": 123
}
],
"context": {}
},
"meta": {
"trace_id": "<string>",
"span_id": "<string>",
"timestamp": "<string>",
"duration_ms": 1,
"team_sid": "<string>",
"actor_type": "<string>"
}
}{
"success": false,
"error": {
"code": "validation_failed",
"message": "<string>",
"recoverable": true,
"suggestion": "<string>",
"field_errors": {},
"blockers": [
{
"type": "<string>",
"severity": "hard",
"description": "<string>",
"entity_sid": "<string>",
"resolution": "<string>",
"resolution_hint": "<string>",
"count": 123
}
],
"context": {}
},
"meta": {
"trace_id": "<string>",
"span_id": "<string>",
"timestamp": "<string>",
"duration_ms": 1,
"team_sid": "<string>",
"actor_type": "<string>"
}
}Create LinkedIn comment
Leave ONE outbound comment on any LinkedIn post, addressed by its social-thread urn in entity_urn (wire create-comment) - a post urn in any of the four families entity_urn documents. Outward and fire-on-success: the post does NOT need to be tracked or owned by us; nothing is persisted here. Identity-bound: linkedin_account_sid REQUIRED, spends the comment_posts bucket (30/day at a 360 s floor), saturation returns 429. Reply to an existing comment via parent_comment_urn. mentions turns exact substrings of text into clickable profile links ( pairs, matched left to right in list order - a name missing or out of order is a 422 with no dispatch spent). Returns the created comment ref plus the activity-log row. To react use react_linkedin_post; to read a post’s comments and who wrote them use the scraping get-post-comments tool; to resolve a post URL use get_activity_urn_by_url.
Contract:
- MCP tool
create_linkedin_comment, registry packagemcp.linkedin/linkedin_posting, mountlinkedin.content. - Operation
action, response envelopeaction. - Flags: dangerous: the MCP layer gates it behind a preview/commit token, and the effect cannot be undone through this API; mass action: this verb’s own request accepts a filter or targets[] set, which the owning service drains; step eligible: gtm.service.orchestration can run this verb as a mass-action plan step, once per item.
curl --request POST \
--url https://app.gtm-api.com/linkedin/v4/api/linkedin-posting/comment \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'Team-SID: <api-key>' \
--data '
{
"linkedin_account_sid": "<string>",
"entity_urn": "<string>",
"text": "<string>",
"parent_comment_urn": "<string>",
"mentions": [
{
"profile_id": "<string>",
"name": "<string>"
}
]
}
'import requests
url = "https://app.gtm-api.com/linkedin/v4/api/linkedin-posting/comment"
payload = {
"linkedin_account_sid": "<string>",
"entity_urn": "<string>",
"text": "<string>",
"parent_comment_urn": "<string>",
"mentions": [
{
"profile_id": "<string>",
"name": "<string>"
}
]
}
headers = {
"Authorization": "Bearer <token>",
"Team-SID": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
Authorization: 'Bearer <token>',
'Team-SID': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
linkedin_account_sid: '<string>',
entity_urn: '<string>',
text: '<string>',
parent_comment_urn: '<string>',
mentions: [{profile_id: '<string>', name: '<string>'}]
})
};
fetch('https://app.gtm-api.com/linkedin/v4/api/linkedin-posting/comment', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.gtm-api.com/linkedin/v4/api/linkedin-posting/comment",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'linkedin_account_sid' => '<string>',
'entity_urn' => '<string>',
'text' => '<string>',
'parent_comment_urn' => '<string>',
'mentions' => [
[
'profile_id' => '<string>',
'name' => '<string>'
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"Team-SID: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.gtm-api.com/linkedin/v4/api/linkedin-posting/comment"
payload := strings.NewReader("{\n \"linkedin_account_sid\": \"<string>\",\n \"entity_urn\": \"<string>\",\n \"text\": \"<string>\",\n \"parent_comment_urn\": \"<string>\",\n \"mentions\": [\n {\n \"profile_id\": \"<string>\",\n \"name\": \"<string>\"\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Team-SID", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://app.gtm-api.com/linkedin/v4/api/linkedin-posting/comment")
.header("Authorization", "Bearer <token>")
.header("Team-SID", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"linkedin_account_sid\": \"<string>\",\n \"entity_urn\": \"<string>\",\n \"text\": \"<string>\",\n \"parent_comment_urn\": \"<string>\",\n \"mentions\": [\n {\n \"profile_id\": \"<string>\",\n \"name\": \"<string>\"\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.gtm-api.com/linkedin/v4/api/linkedin-posting/comment")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Team-SID"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"linkedin_account_sid\": \"<string>\",\n \"entity_urn\": \"<string>\",\n \"text\": \"<string>\",\n \"parent_comment_urn\": \"<string>\",\n \"mentions\": [\n {\n \"profile_id\": \"<string>\",\n \"name\": \"<string>\"\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"operation": "action",
"action": "<string>",
"item": "<unknown>",
"result": {
"comment_urn": "<string>",
"activity_log": {}
},
"meta": {
"trace_id": "<string>",
"span_id": "<string>",
"timestamp": "<string>",
"duration_ms": 1,
"team_sid": "<string>",
"actor_type": "<string>"
}
}{
"success": false,
"error": {
"code": "validation_failed",
"message": "<string>",
"recoverable": true,
"suggestion": "<string>",
"field_errors": {},
"blockers": [
{
"type": "<string>",
"severity": "hard",
"description": "<string>",
"entity_sid": "<string>",
"resolution": "<string>",
"resolution_hint": "<string>",
"count": 123
}
],
"context": {}
},
"meta": {
"trace_id": "<string>",
"span_id": "<string>",
"timestamp": "<string>",
"duration_ms": 1,
"team_sid": "<string>",
"actor_type": "<string>"
}
}{
"success": false,
"error": {
"code": "validation_failed",
"message": "<string>",
"recoverable": true,
"suggestion": "<string>",
"field_errors": {},
"blockers": [
{
"type": "<string>",
"severity": "hard",
"description": "<string>",
"entity_sid": "<string>",
"resolution": "<string>",
"resolution_hint": "<string>",
"count": 123
}
],
"context": {}
},
"meta": {
"trace_id": "<string>",
"span_id": "<string>",
"timestamp": "<string>",
"duration_ms": 1,
"team_sid": "<string>",
"actor_type": "<string>"
}
}Authorizations
Access token issued by gtm.service.id. Its access_identity claim carries team_sid, actor_sid and actor_type, and that team scope is authoritative.
Team scope for tokens that do not carry one. Ignored when the token already names a team.
Body
Request body of create_linkedin_comment.
LinkedIn account sid (ln_ac_…), the authoring account. Identity-bound: REQUIRED, posts publish AS this account.
18^ln_ac_The target handle, in the wire's full social-thread vocabulary (2026-08-21): a post urn in any of the four families - urn:li:activity: (member posts), urn:li:share:, urn:li:ugcPost: (company pages and newsletters), urn:li:groupPost:- (group threads) - or a COMMENT key to target a comment, in either form: public urn:li:comment:((activity|share|ugcPost|groupPost):,) or the fsd urn:li:fsd_comment:(,) LinkedIn's own responses carry (normalized before the wire). All pass verbatim; a malformed urn is refused 422 before any dispatch. A post URL is also accepted when the id is in it: the feed permalink and the share link (/posts/-activity--) are both converted locally. A link WITHOUT an id (a shortlink, a bare slug URL) is refused 422 entity_urn_not_resolvable: reading those means opening the page, so call get_activity_urn_by_url first rather than have a write verb open a page silently. The post does NOT need to be tracked or owned by us. Renamed from activity_urn on 2026-07-30; the old name is no longer accepted.
1 - 512The comment body (caller-supplied, no templates or AI in-app).
1 - 1250Reply target: the comment URN to reply under. Omit or null for a top-level comment.
512Profile mentions (2026-08-21). Names are matched in text left to right in list order, each search starting after the previous mention. The node computes the character offsets itself.
Show child attributes
Show child attributes
Response
action success envelope.