Comments API Reference
The Comments API allows you to retrieve, create, delete, hide/unhide, and like/unlike comments on published posts. All write operations are processed asynchronously.
Endpoints
Section titled “Endpoints”| Method | Endpoint | Description |
|---|---|---|
GET | /api/posts/:post_id/comments | List comments |
GET | /api/posts/:post_id/comments/:id | Get a single comment |
POST | /api/posts/:post_id/comments | Create a comment or reply |
DELETE | /api/posts/:post_id/comments/:id | Delete a comment |
POST | /api/posts/:post_id/comments/:id/hide | Hide a comment |
POST | /api/posts/:post_id/comments/:id/unhide | Unhide a comment |
POST | /api/posts/:post_id/comments/:id/like | Like a comment |
POST | /api/posts/:post_id/comments/:id/unlike | Unlike a comment |
All endpoints require the profile_id query parameter to identify which platform profile’s comments to interact with.
Comment ID resolution
Section titled “Comment ID resolution”Endpoints that accept a comment :id in the path (get, delete, hide, unhide, like, unlike) accept either:
- Postproxy ID: The comment’s hashid (e.g.
abc123xyz) - External ID: The platform’s native comment ID (e.g.
17858893269123456)
Platform support
Section titled “Platform support”Not all platforms support all comment actions. Attempting an unsupported action returns 405 Method Not Allowed.
| Action | Threads | Bluesky | YouTube | |||
|---|---|---|---|---|---|---|
| List | Yes | Yes | Yes | Yes | Coming soon | Coming soon |
| Reply | Yes | Yes | Yes | No | Coming soon | Coming soon |
| Delete | Yes | Yes | No | No | Coming soon | Coming soon |
| Hide/Unhide | Yes | Yes | Yes | No | Coming soon | Coming soon |
| Like/Unlike | No | Yes | No | No | Coming soon | Coming soon |
List comments
Section titled “List comments”GET /api/posts/:post_id/comments
Retrieves a paginated list of top-level comments for a published post on a specific profile. Each top-level comment includes a flat replies array containing all nested replies sorted by creation date.
Query parameters
Section titled “Query parameters”| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
profile_id | string | Yes | - | Profile ID |
page | integer | No | 0 | Page number (zero-indexed) |
per_page | integer | No | 20 | Number of top-level comments per page |
Example
Section titled “Example”curl -X GET "https://api.postproxy.dev/api/posts/POST_ID/comments?profile_id=PROFILE_ID&page=0&per_page=20" \ -H "Authorization: Bearer YOUR_API_KEY"import PostProxy from "postproxy-sdk";
const client = new PostProxy("YOUR_API_KEY");const comments = await client.comments.list("POST_ID", "PROFILE_ID");console.log(`Total comments: ${comments.total}`);for (const comment of comments.data) { console.log(`${comment.author_username}: ${comment.body}`); for (const reply of comment.replies) { console.log(` ${reply.author_username}: ${reply.body}`); }}package main
import ( "context" "fmt" postproxy "github.com/postproxy/postproxy-go")
func main() { client := postproxy.NewClient("YOUR_API_KEY") comments, _ := client.Comments.List(context.Background(), "POST_ID", "PROFILE_ID", nil) fmt.Printf("Total comments: %d\n", comments.Total) for _, c := range comments.Data { fmt.Printf("%v: %s\n", c.AuthorUsername, c.Body) for _, r := range c.Replies { fmt.Printf(" %v: %s\n", r.AuthorUsername, r.Body) } }}require "postproxy"
client = PostProxy::Client.new("YOUR_API_KEY")comments = client.comments.list("POST_ID", profile_id: "PROFILE_ID")puts "Total comments: #{comments.total}"comments.data.each do |comment| puts "#{comment.author_username}: #{comment.body}" comment.replies.each do |reply| puts " #{reply.author_username}: #{reply.body}" endenduse PostProxy\Client;
$client = new Client("YOUR_API_KEY");$comments = $client->comments()->list("POST_ID", "PROFILE_ID");echo "Total comments: {$comments->total}\n";foreach ($comments->data as $comment) { echo "{$comment->authorUsername}: {$comment->body}\n"; foreach ($comment->replies as $reply) { echo " {$reply->authorUsername}: {$reply->body}\n"; }}import dev.postproxy.sdk.PostProxy;
var client = PostProxy.builder("YOUR_API_KEY").build();var comments = client.comments().list("POST_ID", "PROFILE_ID");System.out.println("Total comments: " + comments.total());for (var comment : comments.data()) { System.out.println(comment.authorUsername() + ": " + comment.body()); for (var reply : comment.replies()) { System.out.println(" " + reply.authorUsername() + ": " + reply.body()); }}using PostProxy;
var client = PostProxyClient.Builder("YOUR_API_KEY").Build();var comments = await client.Comments.ListAsync("POST_ID", "PROFILE_ID");Console.WriteLine($"Total comments: {comments.Total}");foreach (var comment in comments.Data){ Console.WriteLine($"{comment.AuthorUsername}: {comment.Body}"); if (comment.Replies is not null) { foreach (var reply in comment.Replies) { Console.WriteLine($" {reply.AuthorUsername}: {reply.Body}"); } }}Response:
{ "total": 42, "page": 0, "per_page": 20, "data": [ { "id": "abc123xyz", "external_id": "17858893269123456", "body": "Great post!", "status": "synced", "author_username": "someuser", "author_avatar_url": null, "author_external_id": "12345", "metadata": { "is_verified_user": false, "is_user_follow_business": true, "is_business_follow_user": false, "follower_count": 482, "author_fetched_at": "2026-03-25T10:01:05Z" }, "parent_external_id": null, "like_count": 3, "is_hidden": false, "permalink": null, "platform_data": null, "attachments": [ { "id": "att_xyz321", "type": "image", "url": "https://storage.postproxy.dev/.../comment_attachment_1780324589", "status": "processed", "external_id": "529233764205652" } ], "posted_at": "2026-03-25T10:00:00.000Z", "created_at": "2026-03-25T10:01:00.000Z", "replies": [ { "id": "def456abc", "external_id": "17858893269123457", "body": "Thanks!", "status": "synced", "author_username": "author", "author_avatar_url": null, "author_external_id": "67890", "metadata": null, "parent_external_id": "17858893269123456", "like_count": 1, "is_hidden": false, "permalink": null, "platform_data": null, "attachments": [], "posted_at": "2026-03-25T10:05:00.000Z", "created_at": "2026-03-25T10:05:00.000Z" } ] } ]}Response fields
Section titled “Response fields”| Field | Type | Description |
|---|---|---|
total | integer | Total number of top-level comments |
page | integer | Current page number |
per_page | integer | Items per page |
data | array | Array of top-level comment objects, each with a replies array |
Reply nesting
Section titled “Reply nesting”Pagination applies to top-level comments only. All replies (regardless of nesting depth) are flattened into the replies array of their root top-level comment, sorted by created_at ascending. Each reply retains its parent_external_id so the client can reconstruct the tree if needed.
Get comment
Section titled “Get comment”GET /api/posts/:post_id/comments/:id
Retrieves a single comment with its direct replies.
Path parameters
Section titled “Path parameters”| Parameter | Type | Required | Description |
|---|---|---|---|
post_id | string | Yes | Post ID |
id | string | Yes | Comment ID or external ID |
Example
Section titled “Example”curl -X GET "https://api.postproxy.dev/api/posts/POST_ID/comments/COMMENT_ID?profile_id=PROFILE_ID" \ -H "Authorization: Bearer YOUR_API_KEY"import PostProxy from "postproxy-sdk";
const client = new PostProxy("YOUR_API_KEY");const comment = await client.comments.get("POST_ID", "COMMENT_ID", "PROFILE_ID");console.log(comment);package main
import ( "context" "fmt" postproxy "github.com/postproxy/postproxy-go")
func main() { client := postproxy.NewClient("YOUR_API_KEY") comment, _ := client.Comments.Get(context.Background(), "POST_ID", "COMMENT_ID", "PROFILE_ID") fmt.Println(comment)}require "postproxy"
client = PostProxy::Client.new("YOUR_API_KEY")comment = client.comments.get("POST_ID", "COMMENT_ID", profile_id: "PROFILE_ID")puts commentuse PostProxy\Client;
$client = new Client("YOUR_API_KEY");$comment = $client->comments()->get("POST_ID", "COMMENT_ID", "PROFILE_ID");print_r($comment);import dev.postproxy.sdk.PostProxy;
var client = PostProxy.builder("YOUR_API_KEY").build();var comment = client.comments().get("POST_ID", "COMMENT_ID", "PROFILE_ID");System.out.println(comment);using PostProxy;
var client = PostProxyClient.Builder("YOUR_API_KEY").Build();var comment = await client.Comments.GetAsync("POST_ID", "COMMENT_ID", "PROFILE_ID");Console.WriteLine(comment);Response:
{ "id": "abc123xyz", "external_id": "17858893269123456", "body": "Great post!", "status": "synced", "author_username": "someuser", "author_avatar_url": null, "author_external_id": "12345", "metadata": { "is_verified_user": false, "is_user_follow_business": true, "is_business_follow_user": false, "follower_count": 482, "author_fetched_at": "2026-03-25T10:01:05Z" }, "parent_external_id": null, "like_count": 3, "is_hidden": false, "permalink": null, "platform_data": null, "attachments": [ { "id": "att_xyz321", "type": "image", "url": "https://storage.postproxy.dev/.../comment_attachment_1780324589", "status": "processed", "external_id": "529233764205652" } ], "posted_at": "2026-03-25T10:00:00.000Z", "created_at": "2026-03-25T10:01:00.000Z", "replies": [ { "id": "def456abc", "external_id": "17858893269123457", "body": "Thanks!", "status": "synced", "author_username": "author", "author_avatar_url": null, "author_external_id": "67890", "metadata": null, "parent_external_id": "17858893269123456", "like_count": 1, "is_hidden": false, "permalink": null, "platform_data": null, "attachments": [], "posted_at": "2026-03-25T10:05:00.000Z", "created_at": "2026-03-25T10:05:00.000Z" } ]}Create comment
Section titled “Create comment”POST /api/posts/:post_id/comments
Creates a new comment on a published post. The comment is stored immediately and published to the platform asynchronously.
Request body
Section titled “Request body”| Parameter | Type | Required | Description |
|---|---|---|---|
body | string | Yes | Comment text content. (The legacy text parameter is still accepted as an alias.) |
parent_id | string | No | ID of comment to reply to (Postproxy ID or external ID). Omit to comment on the post itself. |
Example: Comment on post
Section titled “Example: Comment on post”curl -X POST "https://api.postproxy.dev/api/posts/POST_ID/comments?profile_id=PROFILE_ID" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "body": "Thanks for the feedback everyone!" }'import PostProxy from "postproxy-sdk";
const client = new PostProxy("YOUR_API_KEY");const comment = await client.comments.create("POST_ID", "PROFILE_ID", "Thanks for the feedback everyone!");console.log(comment);package main
import ( "context" "fmt" postproxy "github.com/postproxy/postproxy-go")
func main() { client := postproxy.NewClient("YOUR_API_KEY") comment, _ := client.Comments.Create(context.Background(), "POST_ID", "PROFILE_ID", "Thanks for the feedback everyone!", nil) fmt.Println(comment)}require "postproxy"
client = PostProxy::Client.new("YOUR_API_KEY")comment = client.comments.create("POST_ID", "Thanks for the feedback everyone!", profile_id: "PROFILE_ID")puts commentuse PostProxy\Client;
$client = new Client("YOUR_API_KEY");$comment = $client->comments()->create("POST_ID", "PROFILE_ID", "Thanks for the feedback everyone!");print_r($comment);import dev.postproxy.sdk.PostProxy;
var client = PostProxy.builder("YOUR_API_KEY").build();var comment = client.comments().create("POST_ID", "PROFILE_ID", "Thanks for the feedback everyone!");System.out.println(comment);using PostProxy;
var client = PostProxyClient.Builder("YOUR_API_KEY").Build();var comment = await client.Comments.CreateAsync("POST_ID", "PROFILE_ID", "Thanks for the feedback everyone!");Console.WriteLine(comment);Response (201 Created):
{ "id": "ghi789def", "external_id": null, "body": "Thanks for the feedback everyone!", "status": "pending", "author_username": null, "author_avatar_url": null, "author_external_id": null, "metadata": null, "parent_external_id": null, "like_count": 0, "is_hidden": false, "permalink": null, "platform_data": null, "attachments": [], "posted_at": null, "created_at": "2026-03-25T12:00:00.000Z"}The comment is created with status: "pending" and external_id: null. Once the async job publishes it to the platform, the status updates to "published" and external_id is populated. If publishing fails, the status becomes "failed".
Example: Reply to a comment
Section titled “Example: Reply to a comment”curl -X POST "https://api.postproxy.dev/api/posts/POST_ID/comments?profile_id=PROFILE_ID" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "body": "Glad you liked it!", "parent_id": "COMMENT_ID" }'import PostProxy from "postproxy-sdk";
const client = new PostProxy("YOUR_API_KEY");const reply = await client.comments.create("POST_ID", "PROFILE_ID", "Glad you liked it!", { parentId: "COMMENT_ID",});console.log(reply);package main
import ( "context" "fmt" postproxy "github.com/postproxy/postproxy-go")
func main() { client := postproxy.NewClient("YOUR_API_KEY") parentID := "COMMENT_ID" reply, _ := client.Comments.Create(context.Background(), "POST_ID", "PROFILE_ID", "Glad you liked it!", &postproxy.CommentCreateOptions{ParentID: &parentID}) fmt.Println(reply)}require "postproxy"
client = PostProxy::Client.new("YOUR_API_KEY")reply = client.comments.create("POST_ID", "Glad you liked it!", profile_id: "PROFILE_ID", parent_id: "COMMENT_ID")puts replyuse PostProxy\Client;
$client = new Client("YOUR_API_KEY");$reply = $client->comments()->create("POST_ID", "PROFILE_ID", "Glad you liked it!", parentId: "COMMENT_ID");print_r($reply);import dev.postproxy.sdk.PostProxy;
var client = PostProxy.builder("YOUR_API_KEY").build();var reply = client.comments().create("POST_ID", "PROFILE_ID", "Glad you liked it!", "COMMENT_ID");System.out.println(reply);using PostProxy;
var client = PostProxyClient.Builder("YOUR_API_KEY").Build();var reply = await client.Comments.CreateAsync("POST_ID", "PROFILE_ID", "Glad you liked it!", parentId: "COMMENT_ID");Console.WriteLine(reply);Error responses
Section titled “Error responses”Post not published (422):
{ "error": "Post is not published"}Unsupported platform (405):
{ "error": "Unsupported method for pinterest"}Parent comment not found (404):
{ "error": "Parent comment not found"}Delete comment
Section titled “Delete comment”DELETE /api/posts/:post_id/comments/:id
Deletes a comment from the platform asynchronously.
Path parameters
Section titled “Path parameters”| Parameter | Type | Required | Description |
|---|---|---|---|
post_id | string | Yes | Post ID |
id | string | Yes | Comment ID or external ID |
Example
Section titled “Example”curl -X DELETE "https://api.postproxy.dev/api/posts/POST_ID/comments/COMMENT_ID?profile_id=PROFILE_ID" \ -H "Authorization: Bearer YOUR_API_KEY"import PostProxy from "postproxy-sdk";
const client = new PostProxy("YOUR_API_KEY");await client.comments.delete("POST_ID", "COMMENT_ID", "PROFILE_ID");package main
import ( "context" postproxy "github.com/postproxy/postproxy-go")
func main() { client := postproxy.NewClient("YOUR_API_KEY") client.Comments.Delete(context.Background(), "POST_ID", "COMMENT_ID", "PROFILE_ID")}require "postproxy"
client = PostProxy::Client.new("YOUR_API_KEY")client.comments.delete("POST_ID", "COMMENT_ID", profile_id: "PROFILE_ID")use PostProxy\Client;
$client = new Client("YOUR_API_KEY");$client->comments()->delete("POST_ID", "COMMENT_ID", "PROFILE_ID");import dev.postproxy.sdk.PostProxy;
var client = PostProxy.builder("YOUR_API_KEY").build();client.comments().delete("POST_ID", "COMMENT_ID", "PROFILE_ID");using PostProxy;
var client = PostProxyClient.Builder("YOUR_API_KEY").Build();await client.Comments.DeleteAsync("POST_ID", "COMMENT_ID", "PROFILE_ID");Response (200 OK):
{ "accepted": true}Error responses
Section titled “Error responses”Unsupported platform (405):
{ "error": "Unsupported method for threads"}Comment not yet published (422):
{ "error": "Comment has not been published yet"}Hide comment
Section titled “Hide comment”POST /api/posts/:post_id/comments/:id/hide
Hides a comment on the platform asynchronously. Hidden comments are not visible to the public.
Example
Section titled “Example”curl -X POST "https://api.postproxy.dev/api/posts/POST_ID/comments/COMMENT_ID/hide?profile_id=PROFILE_ID" \ -H "Authorization: Bearer YOUR_API_KEY"import PostProxy from "postproxy-sdk";
const client = new PostProxy("YOUR_API_KEY");await client.comments.hide("POST_ID", "COMMENT_ID", "PROFILE_ID");package main
import ( "context" postproxy "github.com/postproxy/postproxy-go")
func main() { client := postproxy.NewClient("YOUR_API_KEY") client.Comments.Hide(context.Background(), "POST_ID", "COMMENT_ID", "PROFILE_ID")}require "postproxy"
client = PostProxy::Client.new("YOUR_API_KEY")client.comments.hide("POST_ID", "COMMENT_ID", profile_id: "PROFILE_ID")use PostProxy\Client;
$client = new Client("YOUR_API_KEY");$client->comments()->hide("POST_ID", "COMMENT_ID", "PROFILE_ID");import dev.postproxy.sdk.PostProxy;
var client = PostProxy.builder("YOUR_API_KEY").build();client.comments().hide("POST_ID", "COMMENT_ID", "PROFILE_ID");using PostProxy;
var client = PostProxyClient.Builder("YOUR_API_KEY").Build();await client.Comments.HideAsync("POST_ID", "COMMENT_ID", "PROFILE_ID");Response (200 OK):
{ "accepted": true}Unhide comment
Section titled “Unhide comment”POST /api/posts/:post_id/comments/:id/unhide
Unhides a previously hidden comment on the platform asynchronously.
Example
Section titled “Example”curl -X POST "https://api.postproxy.dev/api/posts/POST_ID/comments/COMMENT_ID/unhide?profile_id=PROFILE_ID" \ -H "Authorization: Bearer YOUR_API_KEY"import PostProxy from "postproxy-sdk";
const client = new PostProxy("YOUR_API_KEY");await client.comments.unhide("POST_ID", "COMMENT_ID", "PROFILE_ID");package main
import ( "context" postproxy "github.com/postproxy/postproxy-go")
func main() { client := postproxy.NewClient("YOUR_API_KEY") client.Comments.Unhide(context.Background(), "POST_ID", "COMMENT_ID", "PROFILE_ID")}require "postproxy"
client = PostProxy::Client.new("YOUR_API_KEY")client.comments.unhide("POST_ID", "COMMENT_ID", profile_id: "PROFILE_ID")use PostProxy\Client;
$client = new Client("YOUR_API_KEY");$client->comments()->unhide("POST_ID", "COMMENT_ID", "PROFILE_ID");import dev.postproxy.sdk.PostProxy;
var client = PostProxy.builder("YOUR_API_KEY").build();client.comments().unhide("POST_ID", "COMMENT_ID", "PROFILE_ID");using PostProxy;
var client = PostProxyClient.Builder("YOUR_API_KEY").Build();await client.Comments.UnhideAsync("POST_ID", "COMMENT_ID", "PROFILE_ID");Response (200 OK):
{ "accepted": true}Like comment
Section titled “Like comment”POST /api/posts/:post_id/comments/:id/like
Likes a comment on the platform asynchronously.
Example
Section titled “Example”curl -X POST "https://api.postproxy.dev/api/posts/POST_ID/comments/COMMENT_ID/like?profile_id=PROFILE_ID" \ -H "Authorization: Bearer YOUR_API_KEY"import PostProxy from "postproxy-sdk";
const client = new PostProxy("YOUR_API_KEY");await client.comments.like("POST_ID", "COMMENT_ID", "PROFILE_ID");package main
import ( "context" postproxy "github.com/postproxy/postproxy-go")
func main() { client := postproxy.NewClient("YOUR_API_KEY") client.Comments.Like(context.Background(), "POST_ID", "COMMENT_ID", "PROFILE_ID")}require "postproxy"
client = PostProxy::Client.new("YOUR_API_KEY")client.comments.like("POST_ID", "COMMENT_ID", profile_id: "PROFILE_ID")use PostProxy\Client;
$client = new Client("YOUR_API_KEY");$client->comments()->like("POST_ID", "COMMENT_ID", "PROFILE_ID");import dev.postproxy.sdk.PostProxy;
var client = PostProxy.builder("YOUR_API_KEY").build();client.comments().like("POST_ID", "COMMENT_ID", "PROFILE_ID");using PostProxy;
var client = PostProxyClient.Builder("YOUR_API_KEY").Build();await client.Comments.LikeAsync("POST_ID", "COMMENT_ID", "PROFILE_ID");Response (200 OK):
{ "accepted": true}Unlike comment
Section titled “Unlike comment”POST /api/posts/:post_id/comments/:id/unlike
Removes a like from a comment on the platform asynchronously.
Example
Section titled “Example”curl -X POST "https://api.postproxy.dev/api/posts/POST_ID/comments/COMMENT_ID/unlike?profile_id=PROFILE_ID" \ -H "Authorization: Bearer YOUR_API_KEY"import PostProxy from "postproxy-sdk";
const client = new PostProxy("YOUR_API_KEY");await client.comments.unlike("POST_ID", "COMMENT_ID", "PROFILE_ID");package main
import ( "context" postproxy "github.com/postproxy/postproxy-go")
func main() { client := postproxy.NewClient("YOUR_API_KEY") client.Comments.Unlike(context.Background(), "POST_ID", "COMMENT_ID", "PROFILE_ID")}require "postproxy"
client = PostProxy::Client.new("YOUR_API_KEY")client.comments.unlike("POST_ID", "COMMENT_ID", profile_id: "PROFILE_ID")use PostProxy\Client;
$client = new Client("YOUR_API_KEY");$client->comments()->unlike("POST_ID", "COMMENT_ID", "PROFILE_ID");import dev.postproxy.sdk.PostProxy;
var client = PostProxy.builder("YOUR_API_KEY").build();client.comments().unlike("POST_ID", "COMMENT_ID", "PROFILE_ID");using PostProxy;
var client = PostProxyClient.Builder("YOUR_API_KEY").Build();await client.Comments.UnlikeAsync("POST_ID", "COMMENT_ID", "PROFILE_ID");Response (200 OK):
{ "accepted": true}Comment object fields
Section titled “Comment object fields”| Field | Type | Description |
|---|---|---|
id | string | Unique comment identifier (ID) |
external_id | string|null | Platform’s native comment ID (null for pending comments) |
body | string | Comment text content |
status | string | Comment status: synced, pending, published, failed, failed_waiting_for_retry |
error | string|null | Error summary if the comment failed to publish (null otherwise) |
error_details | object|null | Structured platform error (omitted when no platform error info is available) |
error_details.platform_error_code | string|null | Error code returned by the platform API |
error_details.platform_error_subcode | string|null | Error subcode returned by the platform API |
error_details.platform_error_message | string|null | Error message returned by the platform API |
error_details.postproxy_note | string|null | Additional context from Postproxy about the error |
author_username | string|null | Author’s display name or username |
author_avatar_url | string|null | Author’s profile image URL |
author_external_id | string|null | Author’s platform-specific ID |
metadata | object|null | Additional author signals fetched from the platform. See Metadata fields. |
parent_external_id | string|null | Parent comment’s external ID (null for top-level comments) |
like_count | integer | Number of likes on the comment |
is_hidden | boolean | Whether the comment is hidden |
permalink | string|null | Direct URL to the comment on the platform (when available) |
platform_data | object|null | Platform-specific metadata |
attachments | array | Media attached to the comment. Empty array when there are none. See Attachments. |
posted_at | string|null | ISO 8601 timestamp when the comment was posted on the platform |
created_at | string | ISO 8601 timestamp of record creation |
Attachments
Section titled “Attachments”When a synced comment carries media on the platform, Postproxy downloads each asset to durable storage and exposes it on the comment’s attachments array. The url is stable once status is processed — it does not depend on the platform’s CDN tokens.
"attachments": [ { "id": "att_xyz321", "type": "image", "url": "https://storage.postproxy.dev/.../comment_attachment_1780324589", "status": "processed", "external_id": "529233764205652" }]| Field | Type | Description |
|---|---|---|
id | string | Attachment hashid |
type | string | image, video, audio, gif, external, file |
url | string|null | Stable storage URL to the asset. While status is pending, this temporarily falls back to the source URL on the platform until the file is mirrored to Postproxy storage. |
status | string | pending (still being mirrored), processed (stored and ready), failed (could not be downloaded) |
external_id | string|null | Platform-side identifier for the attachment (e.g. Facebook attachment target ID). Omitted when the platform did not provide one. |
Comment attachments are populated for the platforms whose APIs return media on comment payloads:
| Platform | Notes |
|---|---|
| Photo, video, sticker, and share attachments | |
| Threads | IMAGE, VIDEO, AUDIO, GIF media on top-level comments and replies |
| Bluesky | Image embeds (multiple per comment), video thumbnails / HLS playlists, external-link thumbnails |
Comments are text-only — attachments is always empty | |
| YouTube | Comments are text-only — attachments is always empty |
Comments are text-only — attachments is always empty |
Attachments created via the Create comment endpoint are not yet supported — the attachments array on a freshly created (status: "pending") comment is always empty.
Metadata fields
Section titled “Metadata fields”The metadata object holds extra author signals fetched asynchronously from the platform after the comment is ingested. It is null until the lookup completes, and individual keys may be absent depending on platform support.
| Key | Platform | Type | Description |
|---|---|---|---|
author_fetched_at | both | string | ISO 8601 timestamp of the last author-info refresh |
is_verified_user | instagram, facebook | boolean | Author has a verified account |
is_user_follow_business | instagram, facebook | boolean | Author follows the business profile |
is_business_follow_user | instagram, facebook | boolean | The business profile follows the author |
follower_count | instagram, facebook | integer | Author’s follower count |
Comment statuses
Section titled “Comment statuses”| Status | Description |
|---|---|
synced | Comment was fetched from the platform during sync |
pending | Comment was created via API and is being published to the platform |
published | Comment was successfully published to the platform |
failed | Comment failed to publish to the platform |
Common error responses
Section titled “Common error responses”Missing profile_id (400):
{ "status": 400, "error": "Bad Request", "message": "param is missing or the value is empty: profile_id"}Post not found (404):
{ "error": "Not found"}Comment not found (404):
{ "error": "Not found"}Unsupported method (405):
{ "error": "Unsupported method for {network}"}