Posts
List Threads posts: an account's threads, reposts or replies, a search, or a topic tag.
GET | POST /v1/threads/postsSend parameters as a query string with GET, or as a JSON body with POST. Both are equivalent.
What to Pass
| Pass | Reads | Notes |
|---|---|---|
username | A creator's threads | type: posts (default), reposts, replies |
query | A post search (one page) | sort: top (default) or recent |
hashtag | Posts under a topic tag (one page) |
Pass one source per call. Every identifier also takes the page URL.
Parameters
| Parameter | Type | Required | Notes |
|---|---|---|---|
cursor | string | Opaque cursor from the previous page's cursor. Pass it alone for the next page. | |
hashtag | string | Posts for a topic tag, with or without # (one page). Threads often answers a tag as a keyword match over post text and topic names; the page's ext.matchedBy says tag or keyword. | |
query | string | Search posts by keyword (one page). | |
sort | enum | query only: top (default) or recent. top recent | |
type | enum | username: the creator's threads (default), reposts or replies. posts reposts replies | |
username | string | Creator @handle (with or without @), or the profile URL. |
Request
curl "https://gateway.apinoa.com/v1/threads/posts?username=zuck" \
-H "x-api-key: $APINOA_API_KEY"Response
Returns Page of Post in data. A real response, shortened: arrays keep their first entries and long text is cut.
{
"success": true,
"data": {
"platform": "threads",
"items": [
{
"platform": "threads",
"id": "4006434140014576097",
"url": "https://www.threads.com/@zuck/post/DeZtp-TkQHh",
"author": {
"platform": "threads",
"id": "63055343223",
"handle": "zuck",
"displayName": "Mark Zuckerberg",
"url": "https://www.threads.com/@zuck",
"avatarUrl": "https://scontent-iad6-1.cdninstagram.com/v/t51.82787-19/825322135_17989325280103224_1252773933700107438_n.jpg?stp=dst-j…",
"verified": true
},
"text": "Introducing Muse Wonder, our new family of frontier models with state of the art performance for personal and professio…",
"createdAt": "2026-10-12T16:56:29.000Z",
"media": [
{
"type": "image",
"url": "https://scontent-iad6-1.cdninstagram.com/v/t51.82787-15/844965867_17991705567103224_8296143909108287920_n.webp?_nc_cat=…",
"width": 2160,
"height": 3260,
"variants": [
{
"url": "https://scontent-iad6-1.cdninstagram.com/v/t51.82787-15/844965867_17991705567103224_8296143909108287920_n.webp?_nc_cat=…",
"width": 2160,
"height": 3260
}
]
}
],
"metrics": {
"likes": 2117,
"comments": 550,
"shares": 145,
"reposts": 168,
"quotes": 60
},
"ext": {
"code": "DeZtp-TkQHh",
"mediaType": 1,
"replyControl": "everyone",
"selfThreadIndex": 0,
"selfThreadSize": 4
}
}
],
"cursor": "Gs36BDWiPDJe0VPmI7U4baxcdC58rWMYV5H7psEjv0MYhbfdiqASGVlCk0zQCRy0KrTNDL1Vpdi3w-NI9JywIUEQRbxyczLHaaMydmyXc06-Zmr0KmQCssI…"
}
}Errors
| Status | Code | Meaning |
|---|---|---|
| 400 | INVALID_CURSOR | The cursor is not one this operation returned. Start again without it. |
| 400 | INVALID_PARAMS | A parameter is missing, unknown or out of range. The message names it. |
| 401 | UNAUTHORIZED | The x-api-key header is missing, or the key is revoked or unknown. |
| 402 | INSUFFICIENT_BALANCE | The balance does not cover this call. Top up in the dashboard. |
| 404 | NOT_FOUND | The account, post or group does not exist, or is private, deleted or age-restricted. |
| 429 | MARKETPLACE_SATURATED | Too many concurrent calls. Retry after the Retry-After seconds. |
| 502 | UPSTREAM_ERROR | The platform answered with something unusable. Retry with backoff. |
Every code is listed in Errors. Failed calls are not billed.
Pricing
Price $0.001 per call. List price; the rate steps down above 1,000 calls a day.