Developers
API documentation
Read your LinkedIn content, manage your engagement feeds, and drive outreach campaigns from your own scripts and automations.
https://myfeedin.co/api/v1Introduction
The MyFeedIn API is a REST API over HTTPS. It returns JSON, uses standard HTTP status codes, and is authenticated with an API key. Every request is scoped to the account or workspace that key belongs to, so a key never sees data outside its scope.
Create and manage keys in Settings, API keys.
Prefer chatting with your data from Claude instead of writing code? Connect the MyFeedIn MCP server, it exposes the same posts, analytics, feeds and campaigns as conversational tools, including adding profiles to a campaign by URL.
Authentication
Pass your key as a bearer token on every request. Keys are shown once at creation and stored hashed, so keep yours somewhere safe and never expose it in client-side code.
curl https://myfeedin.co/api/v1/me \
-H "Authorization: Bearer mfi_live_your_key_here"A missing or invalid key returns 401. An inactive subscription returns 402.
Scopes
Each key grants a chosen subset of permissions. The campaign scopes require an active Growth plan, checked at request time. Feed scopes work on every plan, except adding people to a feed, which also needs Growth.
| Field | Type | Description |
|---|---|---|
| posts:read | scope | Read your published LinkedIn posts and their analytics. Analytics sit here rather than under a scope of their own because they are sums of the posts this scope already returns. |
| comments:read | scope | Read the comments you left on other people's posts. |
| feeds:read | scope | List your feeds and the people in them. |
| feeds:write | scope | Create feeds, remove people, and add people by URL (adding requires Growth). |
| campaigns:read | scope | List campaigns and read their stats. Requires Growth. |
| campaigns:write | scope | Create campaigns and add profiles. Requires Growth. |
Rate limits
Requests are rate limited per key. When you exceed the limit the API returns 429 with a retry_after value in seconds. Back off and retry after that window.
Errors
Errors return a JSON body of the shape { "error": "message" } with a conventional status code.
| Field | Type | Description |
|---|---|---|
| 400 | Bad Request | Missing or malformed parameters. |
| 401 | Unauthorized | Missing, invalid, or revoked key. |
| 402 | Payment Required | Subscription inactive. |
| 403 | Forbidden | Key lacks the required scope or plan. |
| 404 | Not Found | Resource does not exist in this scope. |
| 429 | Too Many Requests | Rate limit exceeded. |
Personal keys and workspace keys
A key is bound to one scope when you create it: either your personal account, or one workspace. That binding is permanent. To switch, revoke the key and mint a new one. GET /v1/me tells you which kind you are holding.
The difference matters because MyFeedIn stores two kinds of data. Content belongs to a person: your posts and your comments carry your user id, and a workspace never owns them. Everything else, feeds, saved people and campaigns, belongs to the workspace.
So a workspace key reads the posts, comments and analytics of every member, not just the person who created the key. Each row then carries an author naming who it belongs to, and the member parameter narrows a request to one person. A personal key reads exactly one account and never returns author.
| Field | Type | Description |
|---|---|---|
| member | string | Accepted by /v1/posts, /v1/posts/{id}, /v1/comments and both analytics endpoints. A member's name, email or id — call /v1/workspace/members to list them. Omit to cover every member. Passing it on a personal key returns 400. |
| author | object | Present on every post and comment when the scope spans more than one person: { user_id, name }. |
curl "https://myfeedin.co/api/v1/posts?member=John&limit=5" \
-H "Authorization: Bearer mfi_live_your_key_here"Account
Current key
Returns the calling key's user id, scope, and granted scopes. The simplest way to confirm a key works.
{
"user_id": "a418d3f9-…",
"workspace_id": null,
"scope": "personal",
"scopes": ["posts:read", "campaigns:read", "campaigns:write"]
}Posts
List posts
Published LinkedIn posts. Newest first by default; pass sort to rank by engagement instead, and q to search the post body. Requires posts:read.
| Field | Type | Description |
|---|---|---|
| q | string | Case-insensitive search across the post body. |
| sort | string | recent (default), impressions, comments or reactions. Combines with q to rank the matches. |
| period | string | 30d, 90d, 365d or all. Defaults to 90d for ranked sorts, unbounded otherwise. |
| since | string | Earliest published_at, ISO 8601. |
| until | string | Latest published_at, ISO 8601. |
| member | string | Workspace keys only. Restrict to one member. |
| limit | integer | 1 to 100. Default 20. |
Workspace keys
author. Narrow with member.curl "https://myfeedin.co/api/v1/posts?q=hiring&sort=impressions&period=365d" \
-H "Authorization: Bearer mfi_live_your_key_here"{
"count": 1,
"posts": [
{
"id": "9ba6e7c7-…",
"url": "https://www.linkedin.com/posts/…",
"num_likes": 24,
"num_comments": 5,
"num_impressions": 1330,
"num_shares": 3,
"published_at": "2026-06-17T06:58:07Z",
"excerpt": "I posted the exact same article on X and LinkedIn…",
"author": { "user_id": "6938a74e-…", "name": "John Schapmann" }
}
]
}Get a post
One post with its full body and media arrays. The list endpoint returns a 500-character excerpt to keep payloads small; this returns everything. Requires posts:read.
Workspace keys
404.curl https://myfeedin.co/api/v1/posts/POST_ID \
-H "Authorization: Bearer mfi_live_your_key_here"Analytics
Aggregate analytics
Totals and averages across the period: post count, likes, comments, impressions, shares, and an average-engagement figure. Requires posts:read, since these are sums of the posts that scope already returns.
| Field | Type | Description |
|---|---|---|
| period | string | 30d (default), 90d, 365d or all. |
| compare_to | string | Pass 'previous' to also return the preceding window and the percent deltas. Not available with period=all. |
| member | string | Workspace keys only. Restrict to one member. |
Workspace keys
by_member array, so one member publishing nothing stays visible instead of being averaged away.{
"period": "30d",
"post_count": 14,
"total_impressions": 41230,
"avg_engagement": 38.5,
"by_member": [
{ "member": { "user_id": "a418d3f9-…", "name": "Axel Schapmann" }, "post_count": 14, "total_impressions": 41230 },
{ "member": { "user_id": "6938a74e-…", "name": "John Schapmann" }, "post_count": 0, "total_impressions": 0 }
]
}Engagement patterns
Best day of week, best hour of day, and average engagement per post length bucket, computed from your own history rather than generic advice. Requires posts:read.
| Field | Type | Description |
|---|---|---|
| period | string | 90d or 365d (default). Shorter windows produce confident-looking noise. |
| member | string | Workspace keys only. Restrict to one member. |
Workspace keys
members_pooled so you know how many went into the sample; pass member for an individual.Comments
List comments
Comments left on other people's posts, newest first, each with context about the post it was left under. Requires comments:read, a separate scope from posts:read because this is a different dataset: what you wrote under other people's content.
| Field | Type | Description |
|---|---|---|
| q | string | Case-insensitive search across the comment body. |
| since | string | Earliest comment date, ISO 8601. |
| member | string | Workspace keys only. Restrict to one member. |
| limit | integer | 1 to 100. Default 20. |
Workspace keys
author.curl "https://myfeedin.co/api/v1/comments?q=pricing&limit=10" \
-H "Authorization: Bearer mfi_live_your_key_here"People
Search saved people
Search everyone saved across your feeds and lists by name or headline, without knowing which feed they sit in. Requires feeds:read.
| Field | Type | Description |
|---|---|---|
| q | string | Required. Name or headline keyword. |
| limit | integer | 1 to 100. Default 20. |
Workspace keys
member parameter here.Workspace
List workspace members
Who the key can read, and how to name them in the member parameter. No scope required. Emails are not returned: member matches on name or id.
Workspace keys
200 with an empty roster rather than an error, so one code path handles both kinds of key.{
"scope": "workspace",
"workspace_id": "aa22756a-…",
"count": 2,
"members": [
{ "id": "a418d3f9-…", "name": "Axel Schapmann", "role": "owner", "post_count": 841, "is_key_owner": true },
{ "id": "6938a74e-…", "name": "John Schapmann", "role": "editor", "post_count": 48, "is_key_owner": false }
]
}Feeds
List feeds
Your engagement feeds, newest first, each with a member count. Requires feeds:read.
curl https://myfeedin.co/api/v1/feeds \
-H "Authorization: Bearer mfi_live_your_key_here"{
"count": 2,
"feeds": [
{
"id": "7f2c9a10-…",
"name": "SaaS founders",
"member_count": 24,
"created_at": "2026-05-02T09:12:44Z"
},
{
"id": "b81d4e63-…",
"name": "Clients",
"member_count": 9,
"created_at": "2026-03-18T14:03:21Z"
}
]
}Create feed
Creates an empty feed. Requires feeds:write. Fill it from the app, the Chrome extension, or the add-people endpoint below (Growth plan).
| Field | Type | Description |
|---|---|---|
| name | string | Feed name. Required, max 120 characters. |
curl -X POST https://myfeedin.co/api/v1/feeds \
-H "Authorization: Bearer mfi_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"name":"SaaS founders"}'{
"feed": {
"id": "7f2c9a10-…",
"name": "SaaS founders",
"member_count": 0,
"created_at": "2026-07-20T10:04:12Z"
}
}List people in a feed
The people in one feed. Use the returned person ids with the remove endpoint below. Requires feeds:read.
| Field | Type | Description |
|---|---|---|
| limit | integer | 1 to 200. Default 100. |
curl "https://myfeedin.co/api/v1/feeds/FEED_ID/people?limit=50" \
-H "Authorization: Bearer mfi_live_your_key_here"{
"feed": { "id": "7f2c9a10-…", "name": "SaaS founders" },
"count": 1,
"people": [
{
"id": "c3f81b52-…",
"full_name": "Jane Doe",
"headline": "Founder at Acme",
"linkedin_url": "https://www.linkedin.com/in/jane-doe",
"picture_url": "https://media.licdn.com/dms/image/…"
}
]
}Add people to a feed
Adds LinkedIn profiles to a feed by URL. Each URL is resolved through your connected LinkedIn account to its real LinkedIn identifier (a feed member without one would never appear in the feed), created in your CRM if new, then attached to the feed. Requires feeds:write, the Growth plan, and a connected LinkedIn account. Keys on other plans get a 403; without a connected account the API returns 400.
| Field | Type | Description |
|---|---|---|
| linkedin_url | string | A single profile URL. |
| linkedin_urls | string[] | Up to 25 profile URLs. Use instead of linkedin_url for batches. |
curl -X POST https://myfeedin.co/api/v1/feeds/FEED_ID/people \
-H "Authorization: Bearer mfi_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"linkedin_urls":["https://www.linkedin.com/in/jane-doe"]}'{
"added": 1,
"created": 1,
"matched": 0,
"already_in_feed": 0
}created counts people new to your CRM, matched counts people you already had. Someone already in the feed is skipped and counted in already_in_feed. A URL that cannot be resolved (private or out of network) is reported in an errors array without failing the rest of the batch.
Remove person from feed
Removes a person from the feed. The person stays in your CRM and in any other feed they belong to; only this membership is deleted. The personId comes from the list endpoint above. Requires feeds:write.
curl -X DELETE https://myfeedin.co/api/v1/feeds/FEED_ID/people/PERSON_ID \
-H "Authorization: Bearer mfi_live_your_key_here"{ "removed": true }Campaigns
List campaigns
Lists your outreach campaigns with per-campaign enrollment counts and step counts. Requires campaigns:read.
{
"campaigns": [
{
"id": "…",
"name": "Solopreneurs Q3",
"status": "active",
"step_count": 3,
"enrollment_counts": { "total": 42, "active": 30, "replied": 4 }
}
]
}Create campaign
Creates a draft campaign, locked to your connected LinkedIn account. Requires campaigns:write and a connected account.
| Field | Type | Description |
|---|---|---|
| name | string | Campaign name. Defaults to Untitled campaign. |
| icon | string | Optional icon name. Defaults to Megaphone. |
curl -X POST https://myfeedin.co/api/v1/campaigns \
-H "Authorization: Bearer mfi_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"name":"Solopreneurs Q3"}'Get campaign
One campaign with its ordered steps, warmup state, and enrollments (each joined to its person). Requires campaigns:read.
Add profiles by URL
Adds LinkedIn profiles to a campaign by URL. Each URL is resolved through your connected LinkedIn account, upserted into your CRM, then enrolled. Requires campaigns:write and the Growth plan.
| Field | Type | Description |
|---|---|---|
| linkedin_url | string | A single profile URL. |
| linkedin_urls | string[] | Up to 25 profile URLs. Use instead of linkedin_url for batches. |
curl -X POST https://myfeedin.co/api/v1/campaigns/CAMPAIGN_ID/profiles \
-H "Authorization: Bearer mfi_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"linkedin_url":"https://www.linkedin.com/in/some-person"}'{
"enrolled": 1,
"created": 1,
"matched": 0,
"skipped": 0,
"skipped_active_elsewhere": 0
}Guides
Guide: add a profile to a campaign
The most common workflow: find a campaign, then push profiles into it by URL. First list your campaigns to get an id.
curl https://myfeedin.co/api/v1/campaigns \
-H "Authorization: Bearer mfi_live_your_key_here"Then add one or more profiles to it.
curl -X POST https://myfeedin.co/api/v1/campaigns/CAMPAIGN_ID/profiles \
-H "Authorization: Bearer mfi_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"linkedin_urls": [
"https://www.linkedin.com/in/person-a",
"https://www.linkedin.com/in/person-b"
]
}'A person already active in another campaign is skipped rather than enrolled twice, and appears in skipped_active_elsewhere. A URL that cannot be resolved (private or out of network) is reported in an errors array without failing the rest of the batch.
Guide: manage a feed
Keep a feed clean from a script: list your feeds to get an id, list the people in it, then remove the ones that no longer belong.
curl https://myfeedin.co/api/v1/feeds \
-H "Authorization: Bearer mfi_live_your_key_here"curl https://myfeedin.co/api/v1/feeds/FEED_ID/people \
-H "Authorization: Bearer mfi_live_your_key_here"curl -X DELETE https://myfeedin.co/api/v1/feeds/FEED_ID/people/PERSON_ID \
-H "Authorization: Bearer mfi_live_your_key_here"Removing a person only detaches them from that feed; their CRM record and their other feed memberships are untouched. To rebuild the list, add people again from the app, the Chrome extension, or the add-people endpoint if you are on the Growth plan.