Programmatically publish an author’s content and ensure it surfaces in target users’ apps (create → attach media → target → publish → verify).
The Content API, Channels API, and Feeds API work together to deliver content to users.
- The Content API creates and publishes posts.
- The Channels API defines where that content goes by organizing audiences and topics.
- Once published, the Feeds API makes sure each user sees the right content in their personal feed based on their memberships and permissions.
Created articles are always created as a draft, and need another step to publish them (PUT request).
This example shows how to create and publish an article using the Firstup API. This simulates how a publisher or admin might programmatically push content to the platform.
Before You Start
- You have an access token with
content.writescope. See our Authorization guidance. - You have at least one topic (channel) to publish content to.
- A sample test user account who follows the same test topic for verifying feed visibility via the Feeds API (Feeds are user-personalized). JWT Bearer auth is available for Feeds integrations when you need server-to-server feed checks.
Workflow Overview
- Use
GET /v2/channelsto list your available topics (channels) and pass thechannel_id. - Use
POST /v2/contentto create a draft article and link it to the topic by passing thechannel_id. - Use
PUT /v2/content/{content_id}/publishto publish your drafted article. - Use
GET /v2/feed/poststo varify the published content. Note: You need to authenticate as the test user. Alternatively, useGET /v2/contentwith thefilter.channels.idset to the topic used to publish the content.
Endpoints
GET /v2/channels
POST /v2/content
PUT /v2/content/{content_id}/publish
GET /v2/feed/posts
GET /v2/content
Before publishing, get the list of topics to find where your content should go.
GET /v2/channels
Authorization: Bearer YOUR_ACCESS_TOKEN
Pick a channel_id from the response to pass in the next step.
Example response
{
"data": [
{
"id": "3811518",
"name": "My Feed",
"description": "This is your program's default topic. Content published to this topic appears in every user's personalized feed.",
"state": "hidden",
"auto_publish": false,
"recommended": false,
"targeted": false,
"user_submittable": true,
"groups": [],
"contributor_count": 1,
"contributors": [
18366046
],
"auto_follow": false,
"follower_count": 0,
"created_at": "2021-10-12T22:37:01.170Z",
"updated_at": "2025-10-27T09:41:19.181Z"
},
{
"id": "4344268",
"name": "🗞️ Business News Updated! 🗞️",
"description": "News from around the world!",
"state": "published",
"auto_publish": false,
"recommended": false,
"targeted": false,
"user_submittable": true,
"groups": [],
"contributor_count": 3,
"contributors": [
19957904,
18366046,
20161654
],
"auto_follow": false,
"follower_count": 5,
"created_at": "2022-02-07T18:46:10.820Z",
"updated_at": "2024-02-21T20:14:56.476Z"
},
{
"id": "7538568",
"name": "! Important News !",
"description": "Important News",
"state": "published",
"auto_publish": false,
"recommended": false,
"targeted": false,
"user_submittable": false,
"groups": [],
"contributor_count": 0,
"contributors": [],
"auto_follow": false,
"follower_count": 5,
"created_at": "2024-02-21T19:53:22.542Z",
"updated_at": "2025-05-12T14:08:49.597Z"
},
{
"id": "7538468",
"name": "1 Sales Department",
"description": "Sales Department",
"state": "published",
"auto_publish": false,
"recommended": false,
"targeted": false,
"user_submittable": false,
"groups": [],
"contributor_count": 0,
"contributors": [],
"auto_follow": false,
"follower_count": 5,
"created_at": "2024-02-21T19:52:27.713Z",
"updated_at": "2024-02-21T19:59:12.825Z"
},
{
"id": "7538518",
"name": "2 Marketing Department",
"description": "Marketing Department",
"state": "published",
"auto_publish": false,
"recommended": false,
"targeted": false,
"user_submittable": false,
"groups": [],
"contributor_count": 0,
"contributors": [],
"auto_follow": false,
"follower_count": 5,
"created_at": "2024-02-21T19:52:58.120Z",
"updated_at": "2024-02-21T19:59:18.582Z"
},
{
"id": "7538618",
"name": "3 Training Department",
"description": "Training Department",
"state": "published",
"auto_publish": false,
"recommended": false,
"targeted": false,
"user_submittable": false,
"groups": [],
"contributor_count": 0,
"contributors": [],
"auto_follow": false,
"follower_count": 5,
"created_at": "2024-02-21T19:54:03.145Z",
"updated_at": "2024-02-21T19:59:26.047Z"
},
{
"id": "6346568",
"name": "BlockHeads",
"description": "The home of original Block Heads Content!",
"state": "published",
"auto_publish": false,
"recommended": false,
"targeted": true,
"user_submittable": true,
"groups": [
"justjoeca",
"justjoe",
"block_heads"
],
"contributor_count": 0,
"contributors": [],
"auto_follow": false,
"follower_count": 1,
"created_at": "2023-02-08T04:57:39.297Z",
"updated_at": "2024-08-11T08:41:43.742Z"
},
{
"id": "6346518",
"name": "Block Heads",
"description": "The home of original Block Heads Content!",
"state": "archived",
"auto_publish": false,
"recommended": false,
"targeted": true,
"user_submittable": false,
"groups": [
"justjoeca",
"justjoe"
],
"contributor_count": 0,
"contributors": [],
"auto_follow": false,
"follower_count": 0,
"created_at": "2023-02-08T04:57:31.023Z",
"updated_at": "2023-02-08T04:58:24.375Z"
},
{
"id": "5517818",
"name": "Company News",
"description": "asdf",
"state": "published",
"auto_publish": false,
"recommended": false,
"targeted": true,
"user_submittable": false,
"groups": [
"copy_and_paste_example"
],
"contributor_count": 0,
"contributors": [],
"auto_follow": false,
"follower_count": 1,
"created_at": "2022-09-08T21:28:12.008Z",
"updated_at": "2025-09-12T09:56:04.338Z"
},
{
"id": "5596518",
"name": "Company Updates",
"description": "Company updates",
"state": "published",
"auto_publish": false,
"recommended": true,
"targeted": false,
"user_submittable": false,
"groups": [],
"contributor_count": 0,
"contributors": [],
"auto_follow": false,
"follower_count": 20,
"created_at": "2022-09-21T14:57:28.346Z",
"updated_at": "2025-10-16T13:33:14.425Z"
}
],
"meta": {
"pagination": {
"page": 1,
"page_size": 10,
"total_records": 56
},
"filter": {}
}
}Submit the content as a draft:
- Creating your article as a draft is the default and only way. Publishing this requires another endpoint.
- This gives you a chance to review or edit before publishing.
POST /v2/content
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/jsonExample request
{
"content_type": "article",
"title": "How to Automate Engagement Campaigns",
"body": "<p>Engagement starts with relevance...</p>",
"summary": "Learn how to programmatically publish content using Firstup.",
"visibility": "private",
"channels": [
{ "id": 123 }
],
"featured": false
}The response contains the content_id of your draft article. Pass this into the next step.
Once you're ready, move the article from draft to published.
PUT /v2/content/{content_id}/publish
Authorization: Bearer YOUR_ACCESS_TOKENThe article is now live and visible according to its topic targeting and visibility settings.
Either authenticate as a test user who follows the topic you've posted to, and make a GET request to their feed:
GET /v2/feed/posts
Authorization: Bearer YOUR_ACCESS_TOKENOr, make a GET request as your user account to the content API.
GET /v2/content?filter.channels.id=123&page.size=10&page.number=1
Authorization: Bearer YOUR_ACCESS_TOKEN
This example shows how to create an article and attach an image to the body.
- Add up to 10 images per article.
- Images are not resized or hosted. Make sure they are production ready.
- You can update the article's body to explicitly reference or embed the image.
Before You Start
- You have an access token with
content.writescope. See our Authorization guidance. - An image URL hosted on a public CDN or trusted server.
- You have at least one topic (channel) to publish content to.
Workflow Overview
- Use
GET /v2/channelsto list your available topics (channels) and pass thechannel_id. - Use
POST /v2/contentto create a draft article and link it to the topic by passing thechannel_id. - Use
PUT /v2/content/{content_id}/imagesto add an image to your drafted article. - Use
PUT /v2/content/{content_id}/publishto publish your drafted article.
Endpoints
GET /v2/channels
POST /v2/content
PUT /v2/content/{content_id}/images
PUT /v2/content/{content_id}/publish
Before publishing, get the list of topics to find where your content should go.
GET /v2/channels
Authorization: Bearer YOUR_ACCESS_TOKEN
Pick a channel_id from the response to pass in the next step.
Submit the content as a draft:
- Creating your article as a draft is the default and only way. Publishing this requires another endpoint.
- This gives you a chance to review or edit before publishing.
POST /v2/content
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/json{
"content_type": "article",
"title": "How to Automate Engagement Campaigns",
"body": "<p>Engagement starts with relevance...</p>",
"summary": "Learn how to programmatically publish content using Firstup.",
"visibility": "private",
"channels": [
{ "id": 123 }
],
"featured": false
}The response contains the content_id of your draft article. Pass this into the next step.
Now, attach an image using the article’s content_id. The image URL must be accessible to Firstup’s servers (e.g., public S3 or CDN link).
PUT /v2/content/{content_id}/images
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/json
{
"image_url": "https://cdn.example.com/images/secure-api-guide.png"
}If successful, the image is now linked to the article and will be included in the rendered view.
Optionally add metadata fields. Examples:
featured: truefeatured_label: "Editor’s Pick"
Once you're ready, move the article from draft to published.
PUT /v2/content/{content_id}/publish
Authorization: Bearer YOUR_ACCESS_TOKENThe article is now live and visible according to its topic targeting and visibility settings.
This example shows how to create an article and attach a video to the body.
- You can add multiple videos, but only one at a time.
- Videos are not resized—optimize them for web streaming.
- Use
captionandpreview_image_urlfor accessibility and visual polish.
Before You Start
- You have an access token with
content.writescope. See our Authorization guidance. - A public video URL (e.g., MP4 or embed-safe platform).
- You have at least one topic (channel) to publish content to.
Workflow Overview
- Use
GET /v2/channelsto list your available topics (channels) and pass thechannel_id. - Use
POST /v2/contentto create a draft article and link it to the topic by passing thechannel_id. - Use
PUT /v2/content/{content_id}/videosto add a video to your drafted article. - Use
PUT /v2/content/{content_id}/publishto publish your drafted article.
Endpoints
GET /v2/channels
POST /v2/content
PUT /v2/content/{content_id}/videos
PUT /v2/content/{content_id}/publish
Before publishing, get the list of topics to find where your content should go.
GET /v2/channels
Authorization: Bearer YOUR_ACCESS_TOKEN
Pick a channel_id from the response to pass in the next step.
Submit the content as a draft:
- Creating your article as a draft is the default and only way. Publishing this requires another endpoint.
- This gives you a chance to review or edit before publishing.
POST /v2/content
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/json{
"content_type": "article",
"title": "How to Automate Engagement Campaigns",
"body": "<p>Engagement starts with relevance...</p>",
"summary": "Learn how to programmatically publish content using Firstup.",
"visibility": "private",
"channels": [
{ "id": 123 }
],
"featured": false
}The response contains the content_id of your draft article. Pass this into the next step.
Now, attach a video using the article’s content_id.
PUT /v2/content/{content_id}/videos
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/json
{
"video_url": "https://cdn.example.com/videos/ceo-interview.mp4",
"caption": "CEO Interview: Leading in 2025",
"preview_image_url": "https://cdn.example.com/images/ceo-video-thumbnail.jpg"
}
The response includes an embed_html snippet, which can be added to the article body if desired.
If you want control over where the video appears in the article, insert the embed_html into the body:
PUT /v2/content/{content_id}
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/json
{
"body": "<p>Watch our CEO talk about leadership:</p><iframe src='...'></iframe>"
}Once you're ready, move the article from draft to published.
PUT /v2/content/{content_id}/publish
Authorization: Bearer YOUR_ACCESS_TOKENThe article is now live and visible according to its topic targeting and visibility settings.