Apex Connect Api Chatter
Activate this skill when Apex needs to post to Chatter, reply to a feed item, or @mention a user programmatically. The ConnectApi namespace is the only supported way to produce rich-content posts (mentions, links, files, polls) — direct DML on FeedItem is limited and does NOT support mention rendering.
Before Starting
Gather this context before working on anything in this domain:
- Is Chatter enabled in the org?
ConnectApithrowsConnectApi.ConnectApiExceptionif disabled. - What's the execution context?
ConnectApihas strict restrictions in@futureand test methods. - What sort of post? Plain text, text-with-mentions, link, file attachment, poll, or announcement?
- Who's the author? Running user by default; can impersonate only via
ConnectApi.ChatterFeeds.postFeedElementparameters in limited cases.
Core Concepts
ConnectApi vs Direct DML On FeedItem
insert new FeedItem(...)works but produces plain text only. No mentions, no files, no polls.ConnectApi.ChatterFeeds.postFeedElement(...)supports the full post capability set (mentions, files, links, polls, announcements).- Rule: if the post has any rich content, use ConnectApi. Use direct DML only for the simplest text post where capabilities are not needed.
FeedItemInput + MessageBodyInput + MessageSegmentInput
Rich posts are assembled from segments:
TextSegmentInput— plain textMentionSegmentInput—@useror@groupLinkSegmentInput— inline URLHashtagSegmentInput—#topic
Segments are concatenated in order into a MessageBodyInput, which is wrapped in a FeedItemInput.
Test Context Restrictions
ConnectApimethods throw in synchronous test methods unlessTest.setMock(ConnectApi.ConnectApi.class, mock)or theSeeAllData=trueannotation is used.SeeAllData=trueis a code-smell in most orgs; prefer the mock framework.@futuremethods CAN callConnectApi, but the calls run as the user who enqueued (or the automated user in some contexts) — test this explicitly.
Feed Parent Id Types
Feeds hang off a parent record. Common parent types:
- User Ids (
005...) — user's personal feed - Group Ids (
0F9...) — Chatter group - Record Ids (
001...etc.) — any object with feed tracking enabled 'me'— shorthand for the running user
Common Patterns
Plain-Text Post With @Mention
When to use: A trigger or service needs to notify an owner by @mentioning them in a record feed.
How it works:
public static void postMentionToRecord(Id recordId, Id userToMention, String message) {
ConnectApi.FeedItemInput post = new ConnectApi.FeedItemInput();
ConnectApi.MessageBodyInput body = new ConnectApi.MessageBodyInput();
body.messageSegments = new List<ConnectApi.MessageSegmentInput>();
ConnectApi.MentionSegmentInput mention = new ConnectApi.MentionSegmentInput();
mention.id = userToMention;
body.messageSegments.add(mention);
ConnectApi.TextSegmentInput text = new ConnectApi.TextSegmentInput();
text.text = ' ' + message;
body.messageSegments.add(text);
post.body = body;
ConnectApi.ChatterFeeds.postFeedElement(Network.getNetworkId(), recordId, post);
}
Why not the alternative: insert new FeedItem(Body='@Jane ...') shows literal @Jane text — no notification fires, no link is rendered.
Post With File Attachment
When to use: Uploading a report PDF and posting it to a record feed in one go.
How it works:
ConnectApi.FeedItemInput input = new ConnectApi.FeedItemInput();
ConnectApi.MessageBodyInput body = new ConnectApi.MessageBodyInput();
body.messageSegments = new List<ConnectApi.MessageSegmentInput>{
new ConnectApi.TextSegmentInput()
};
((ConnectApi.TextSegmentInput) body.messageSegments[0]).text = 'See attached report.';
input.body = body;
ConnectApi.NewFileAttachmentInput file = new ConnectApi.NewFileAttachmentInput();
file.title = 'Weekly Report';
input.capabilities = new ConnectApi.FeedElementCapabilitiesInput();
input.capabilities.content = new ConnectApi.ContentCapabilityInput();
input.capabilities.content.title = file.title;
ConnectApi.BinaryInput binary = new ConnectApi.BinaryInput(
Blob.valueOf(pdfBytes), 'application/pdf', 'report.pdf');
ConnectApi.ChatterFeeds.postFeedElement(
Network.getNetworkId(), recordId, input, binary);
Decision Guidance
| Situation | Recommended Approach | Reason |
|---|---|---|
| Plain text post, no mentions | Either ConnectApi or DML | Choose by team convention |
| Text with @mention | ConnectApi MentionSegmentInput |
DML produces literal text |
| Post + file attachment | ConnectApi with BinaryInput |
No DML equivalent |
| Poll post | ConnectApi PollCapabilityInput |
No DML equivalent |
| Scheduled reminder post | Queueable calling ConnectApi | Governor-safe |
| Bulk posts (100s) | Batch + ConnectApi per record | Respects limits per execution |
| Experience Cloud posts | Network.getNetworkId() arg |
null posts to internal Chatter |
Recommended Workflow
- Confirm Chatter is enabled — feature check via
FeatureManagementor an admin confirm. - Identify feed parent — user, group, or record with feed tracking enabled.
- Build the
FeedItemInputby assembling message segments; handle null/empty text explicitly. - Decide sync vs async — post in the current transaction unless you need isolation; if async, write a governor-bounded Queueable.
- Write tests —
Test.setMock(ConnectApi.ConnectApi.class, ...)to avoid real feed writes; assert the payload shape. - Test Experience Cloud separately if posts must appear in a partner/customer community —
Network.getNetworkId()argument matters.
Review Checklist
- No literal
@usernamestrings in FeedItem.Body — mentions are alwaysMentionSegmentInput. -
Network.getNetworkId()(not hardcoded network Id) for community context. - Tests use
Test.setMock(ConnectApi.ConnectApi.class, ...). - ConnectApi call wrapped in try/catch of
ConnectApi.ConnectApiException. - Messages under Chatter's 10,000 char soft limit.
- File attachments under 2GB / org-specific limit.
Salesforce-Specific Gotchas
- Chatter off means ConnectApiException — orgs with Chatter disabled throw on every call; feature-flag the code.
FeedItemDML cannot render mentions —@Janeappears as literal text, no notification fires.ConnectApiin test requires mocks —SeeAllData=false(the default) blocks real Chatter calls; useTest.setMockor the call throws.- Network Id must be passed — omitting or using the wrong community Id posts to the wrong feed silently.
- Mentions require feed visibility — user must have access to the parent record; otherwise the mention is rendered but no notification fires.
- Feed tracking must be on — posting to a record whose object lacks feed tracking fails with a specific ConnectApiException.
- Polls cannot be edited after posting — only deleted and reposted.
- ConnectApi does NOT call triggers on FeedItem —
FeedItemtriggers fire on DML, but ConnectApi writes go through a separate path; relying on FeedItem triggers for ConnectApi posts is unreliable.
Data 360 ConnectApi data graph reads (Spring '25–Spring '26)
Chatter is the primary ConnectApi surface for this skill, but teams mixing Data 360 data graphs into Apex should know the ConnectApi.CdpQuery additions (check each method's documented API version):
| Method family | API version | Use |
|---|---|---|
getDataGraphData(..., live) |
63.0 (Spring '25) | Live/real-time data graph reads |
getDataGraphDataWithLookupKeys(..., noCache) |
64.0 (Summer '25) | Lookup-key reads that bypass cache |
getMetadataEntities() (+ overloads with dataspace) |
66.0 (Spring '26) | Discover graph entity metadata |
Earlier APIs expose materialized-view reads only. Version-gate call sites on apiVersion, not org release calendar.
Output Artifacts
| Artifact | Description |
|---|---|
scripts/check_apex_connect_api_chatter.py |
Scans for literal @ mentions in FeedItem DML, missing ConnectApi mocks in tests, and unsafe error handling |
templates/apex-connect-api-chatter-template.md |
Work template for assembling FeedItemInput with mentions and attachments |
Related Skills
apex-custom-notifications-from-apex— bell notifications (different system from Chatter)apex-email-messaging— email outreach (Chatter is not email)apex-blob-and-content-version— managing files attached to Chatter posts