curl --request GET \
--url https://api.superx.so/v1/engage/feeds/{id}/posts \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.superx.so/v1/engage/feeds/{id}/posts"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.superx.so/v1/engage/feeds/{id}/posts', 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://api.superx.so/v1/engage/feeds/{id}/posts",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.superx.so/v1/engage/feeds/{id}/posts"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.superx.so/v1/engage/feeds/{id}/posts")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.superx.so/v1/engage/feeds/{id}/posts")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"data": [
{
"id": "1941300000000000002",
"text": "We doubled activation by rewriting onboarding emails.",
"created_at": "2026-09-01T09:41:00.000Z",
"url": "https://x.com/founderhandle/status/1941300000000000002",
"author": {
"id": "944883311",
"username": "founderhandle",
"name": "Founder Name",
"description": "Bootstrapping a SaaS in public.",
"followers_count": 4210,
"following_count": 388,
"verified": true
},
"metrics": {
"likes": 142,
"replies": 18,
"reposts": 9,
"bookmarks": 27,
"impressions": 21400
},
"media": []
}
],
"has_more": true,
"feed": {
"id": "feed_kw_1",
"name": "Bootstrapped SaaS",
"type": "keywords"
}
}{
"error": {
"code": "invalid_parameter",
"message": "since must be a UTC ISO-8601 timestamp"
}
}{
"error": {
"code": "invalid_api_key",
"message": "Unknown or revoked API key"
}
}{
"error": "subscription_required: The SuperX API requires an active subscription"
}{
"error": {
"code": "feed_not_found",
"message": "No Engage feed with that id belongs to this account."
}
}{
"error": {
"code": "rate_limited",
"message": "Rate limit exceeded for the Pro plan (5 feed fetches/min). Upgrade for higher limits. A list feed that rotates its members costs 3 fetches. Retry after 27 seconds.",
"retry_after": 27,
"remaining_day": 41
}
}{
"error": {
"code": "internal_error",
"message": "Failed to fetch posts"
}
}{
"error": {
"code": "upstream_error",
"message": "Failed to fetch scheduled posts. Try again shortly."
}
}{
"error": {
"code": "upstream_unavailable",
"message": "The scheduling service is temporarily unavailable. Retry with the same Idempotency-Key."
}
}Get posts from an Engage feed
Candidate posts from one saved feed, with the author profile and engagement metrics you need to score them for relevance, author size and recency.
Paging works through exclude_post_ids, not page numbers: pass the
ids you already hold to get the next batch. There is no pagination
object; has_more tells you whether the feed had more to give.
limit applies to keyword feeds. List feeds ignore it upstream and
return one page per fetch: about 10 posts for a member list, 20 to 25
for an imported X list (limit only trims that page). The size
follows the list’s resolved kind rather than the feed’s type, so a
list feed backed by a pure imported X list pages like an x_list
feed. Page list feeds with exclude_post_ids instead of raising
limit.
Each fetch charges the plan’s feed bucket, and a list feed that
rotates its members costs 3 units instead of 1. On a keyword feed a
50-post page costs exactly the same as a 20-post page, so ask for
limit=50 a few times a day and filter on your side rather than
polling; feeds refresh over hours, so fetching more often than
hourly returns the same posts. Feed fetches also run a few at a time
across all API users; on a 429 with Retry-After, wait and retry.
The bucket is charged before the fetch, so a fetch that then fails
upstream still costs its units.
Posts returned here count as seen and are demoted in later fetches.
On a list feed, paging with exclude_post_ids also advances, and
fresh=true resets, the same list cursor the SuperX app uses, so
both move the position a person browsing that feed in the app sees.
A plain fetch after a pause resets that cursor too, matching the
app’s own session timeout.
Read-only by design. These endpoints return feed candidates for a person to review; replies are written and sent by a person in the SuperX app, which is why there is no reply endpoint here. Sending spammy, automated, or AI-generated replies that read as inauthentic may get your X account suspended under X’s inauthentic-behavior rules and your SuperX account terminated. AI suggestions must be reviewed and meaningfully edited before they are sent, and you are solely responsible for what you post. Reply activity is logged and may be audited.
curl --request GET \
--url https://api.superx.so/v1/engage/feeds/{id}/posts \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.superx.so/v1/engage/feeds/{id}/posts"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.superx.so/v1/engage/feeds/{id}/posts', 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://api.superx.so/v1/engage/feeds/{id}/posts",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.superx.so/v1/engage/feeds/{id}/posts"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.superx.so/v1/engage/feeds/{id}/posts")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.superx.so/v1/engage/feeds/{id}/posts")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"data": [
{
"id": "1941300000000000002",
"text": "We doubled activation by rewriting onboarding emails.",
"created_at": "2026-09-01T09:41:00.000Z",
"url": "https://x.com/founderhandle/status/1941300000000000002",
"author": {
"id": "944883311",
"username": "founderhandle",
"name": "Founder Name",
"description": "Bootstrapping a SaaS in public.",
"followers_count": 4210,
"following_count": 388,
"verified": true
},
"metrics": {
"likes": 142,
"replies": 18,
"reposts": 9,
"bookmarks": 27,
"impressions": 21400
},
"media": []
}
],
"has_more": true,
"feed": {
"id": "feed_kw_1",
"name": "Bootstrapped SaaS",
"type": "keywords"
}
}{
"error": {
"code": "invalid_parameter",
"message": "since must be a UTC ISO-8601 timestamp"
}
}{
"error": {
"code": "invalid_api_key",
"message": "Unknown or revoked API key"
}
}{
"error": "subscription_required: The SuperX API requires an active subscription"
}{
"error": {
"code": "feed_not_found",
"message": "No Engage feed with that id belongs to this account."
}
}{
"error": {
"code": "rate_limited",
"message": "Rate limit exceeded for the Pro plan (5 feed fetches/min). Upgrade for higher limits. A list feed that rotates its members costs 3 fetches. Retry after 27 seconds.",
"retry_after": 27,
"remaining_day": 41
}
}{
"error": {
"code": "internal_error",
"message": "Failed to fetch posts"
}
}{
"error": {
"code": "upstream_error",
"message": "Failed to fetch scheduled posts. Try again shortly."
}
}{
"error": {
"code": "upstream_unavailable",
"message": "The scheduling service is temporarily unavailable. Retry with the same Idempotency-Key."
}
}Authorizations
A SuperX API key ("sxk_..."), created in the SuperX app under Account > API / MCP / CLI. Keys are server-side secrets.
Path Parameters
Feed id from GET /v1/engage/feeds.
Query Parameters
Account to act on, from GET /v1/accounts. Defaults to your main account. An id outside your accounts returns 404 account_not_found.
Posts to return, up to 50. Default 20. Applies to keyword feeds; list feeds return one page per fetch whatever you ask for, about 10 posts for a member list and 20 to 25 for an imported X list. On a keyword feed a big page costs the same as a small one.
1 <= x <= 50Ranking for keyword feeds. top (default) blends quality and relevance, latest is pure recency.
top, latest Skip the short-lived result cache and refetch. Default false.
Keep posts the account already replied to, flagged with replied: true. Default false removes them.
Comma-separated post ids to leave out, up to 100. This is how you page.