Skip to content

Profile Comments API Reference

The Profile Comments API exposes feedback that is scoped to a profile and location, rather than to an individual post. Today it surfaces Google Business Profile reviews — reviews live on a location, not on a post, so they cannot be expressed through the post-level Comments API.

All write operations are processed asynchronously.

MethodEndpointDescription
GET/api/profiles/:profile_id/commentsList top-level comments + their replies
GET/api/profiles/:profile_id/comments/:idGet a single comment
POST/api/profiles/:profile_id/commentsCreate a reply to an existing comment
DELETE/api/profiles/:profile_id/comments/:idDelete your reply (the original review stays)

Endpoints that accept a comment :id in the path, and the parent_id field on POST, accept either:

  • Postproxy ID: the comment’s hashid (e.g. abc123xyz)
  • External ID: the platform’s native resource path (e.g. accounts/1234/locations/5678/reviews/AbFvOq)

ActionGoogle Business
ListYes (reviews on the location)
ReplyYes (as a reply to an existing review only)
DeleteYes (removes your reply; the review stays)

Top-level comments cannot be authored — Google Business reviews come from end users. POST requests must supply a parent_id pointing at the review you are replying to.

Reviews are pulled from Google twice a day (06:00 and 18:00 UTC) for every active, eligible google_business profile. The Profile#comments_synced_at timestamp tracks the most recent sync.


GET /api/profiles/:profile_id/comments

Retrieves a paginated list of top-level comments for a profile. Each top-level comment includes a replies array containing all nested replies sorted by created_at ascending.

ParameterTypeRequiredDescription
profile_idstringYesProfile ID (hashid)
ParameterTypeRequiredDefaultDescription
placement_idstringNo-Filter to comments on a single location (the accounts/X/locations/Y path returned by List Placements)
pageintegerNo0Page number (zero-indexed)
per_pageintegerNo20Number of top-level comments per page
Terminal window
curl -X GET "https://api.postproxy.dev/api/profiles/PROFILE_ID/comments?page=0&per_page=20" \
-H "Authorization: Bearer YOUR_API_KEY"

Response:

{
"total": 2,
"page": 0,
"per_page": 20,
"data": [
{
"id": "abc123",
"external_id": "accounts/1234/locations/5678/reviews/AbFvOq",
"parent_external_id": null,
"placement_id": "accounts/1234/locations/5678",
"body": "Great coffee, friendly staff!",
"status": "synced",
"author_username": "Jane D.",
"author_avatar_url": "https://lh3.googleusercontent.com/...",
"platform_data": { "star_rating": 5, "update_time": "2026-05-10T12:00:00Z" },
"posted_at": "2026-05-10T11:55:00Z",
"created_at": "2026-05-13T06:00:01Z",
"replies": [
{
"id": "def456",
"external_id": "accounts/1234/locations/5678/reviews/AbFvOq/reply",
"parent_external_id": "accounts/1234/locations/5678/reviews/AbFvOq",
"placement_id": "accounts/1234/locations/5678",
"body": "Thanks Jane — see you again soon!",
"status": "published",
"author_username": null,
"author_avatar_url": null,
"platform_data": null,
"posted_at": "2026-05-12T15:00:00Z",
"created_at": "2026-05-12T15:00:01Z"
}
]
}
]
}
FieldTypeDescription
totalintegerTotal number of top-level comments
pageintegerCurrent page number
per_pageintegerItems per page
dataarrayArray of top-level comment objects, each with a replies array

Pagination applies to top-level comments only. All replies 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 /api/profiles/:profile_id/comments/:id

Retrieves a single comment with its direct replies.

ParameterTypeRequiredDescription
profile_idstringYesProfile ID
idstringYesComment ID or external ID
Terminal window
curl -X GET "https://api.postproxy.dev/api/profiles/PROFILE_ID/comments/COMMENT_ID" \
-H "Authorization: Bearer YOUR_API_KEY"

Response:

{
"id": "abc123",
"external_id": "accounts/1234/locations/5678/reviews/AbFvOq",
"parent_external_id": null,
"placement_id": "accounts/1234/locations/5678",
"body": "Great coffee, friendly staff!",
"status": "synced",
"author_username": "Jane D.",
"author_avatar_url": "https://lh3.googleusercontent.com/...",
"platform_data": { "star_rating": 5, "update_time": "2026-05-10T12:00:00Z" },
"posted_at": "2026-05-10T11:55:00Z",
"created_at": "2026-05-13T06:00:01Z",
"replies": [
{
"id": "def456",
"external_id": "accounts/1234/locations/5678/reviews/AbFvOq/reply",
"parent_external_id": "accounts/1234/locations/5678/reviews/AbFvOq",
"placement_id": "accounts/1234/locations/5678",
"body": "Thanks Jane — see you again soon!",
"status": "published",
"author_username": null,
"author_avatar_url": null,
"platform_data": null,
"posted_at": "2026-05-12T15:00:00Z",
"created_at": "2026-05-12T15:00:01Z"
}
]
}

POST /api/profiles/:profile_id/comments

Creates a reply to an existing review. The reply is stored immediately with status: "pending" and external_id: null; a background job then calls the Google Business API and updates the status to published once it lands (or failed / failed_waiting_for_retry with error_message populated).

Top-level comments cannot be created — the request returns 422 if parent_id is missing.

ParameterTypeRequiredDescription
parent_idstringYesPostproxy ID or external ID of the review being replied to
textstringYesReply body
Terminal window
curl -X POST "https://api.postproxy.dev/api/profiles/PROFILE_ID/comments" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"parent_id": "accounts/1234/locations/5678/reviews/AbFvOq",
"text": "Thanks for the kind words!"
}'

Response (201 Created):

{
"id": "ghi789",
"external_id": null,
"parent_external_id": "accounts/1234/locations/5678/reviews/AbFvOq",
"placement_id": "accounts/1234/locations/5678",
"body": "Thanks for the kind words!",
"status": "pending",
"author_username": null,
"author_avatar_url": null,
"platform_data": null,
"posted_at": null,
"created_at": "2026-05-13T10:30:00Z"
}

DELETE /api/profiles/:profile_id/comments/:id

Deletes your reply to a review. The Google Business API does not let businesses delete reviews themselves — the original review row stays.

ParameterTypeRequiredDescription
profile_idstringYesProfile ID
idstringYesComment ID or external ID
Terminal window
curl -X DELETE "https://api.postproxy.dev/api/profiles/PROFILE_ID/comments/COMMENT_ID" \
-H "Authorization: Bearer YOUR_API_KEY"

Response (200 OK):

{
"accepted": true
}

The profile_comment.created event fires whenever a new profile comment record appears — both for newly synced incoming reviews and for outgoing replies that have just been published. Subscribe to profile_comment.created (or *) under your webhook endpoint’s events list. See the Webhooks reference for delivery, retries, and signature verification.

Sample payload:

{
"id": "abc123",
"profile_id": "prof123abc",
"platform": "google_business",
"placement_id": "accounts/1234/locations/5678",
"external_id": "accounts/1234/locations/5678/reviews/AbFvOq",
"parent_external_id": null,
"body": "Great coffee, friendly staff!",
"status": "synced",
"author_username": "Jane D.",
"author_avatar_url": "https://lh3.googleusercontent.com/...",
"platform_data": { "star_rating": 5, "update_time": "2026-05-10T12:00:00Z" },
"posted_at": "2026-05-10T11:55:00Z",
"created_at": "2026-05-13T06:00:01Z"
}

FieldTypeDescription
idstringPostproxy comment ID (hashid)
external_idstring|nullPlatform’s native resource ID (null while a reply is pending publication)
parent_external_idstring|nullExternal ID of parent review (null for top-level reviews)
placement_idstringLocation path (e.g. accounts/X/locations/Y)
bodystringComment/review text
statusstringOne of synced, pending, published, failed, failed_waiting_for_retry
author_usernamestring|nullDisplay name of reviewer (null for your own replies)
author_avatar_urlstring|nullProfile image URL
platform_dataobject|nullPlatform-specific metadata (e.g. star_rating, update_time for Google reviews)
posted_atstring|nullISO 8601 timestamp of platform posting
created_atstringISO 8601 timestamp of record creation
repliesarrayNested replies to this comment (present on list/get responses)
StatusDescription
syncedReview fetched from the platform during sync
pendingReply created via API, awaiting publication
publishedReply successfully posted to the platform
failedReply failed to publish
failed_waiting_for_retryReply failed and is queued for retry

Missing parent_id (422):

{
"error": "parent_id is required"
}

Unsupported method (405):

{
"error": "Unsupported method for instagram"
}

Not found (404):

{
"error": "Not found"
}

Bad request (400):

{
"error": "param is missing or the value is empty"
}