Get All Forum Posts

URL: https://api.gradual-api.com/public-api/v1/forum/posts

HTTP Method: GET

Content type: application/json

Tier: Medium

Query Parameters:

  • pageNum, integer, optional, page number (minimum 1, defaults to 1)
  • pageSize, integer, optional, number of results per page (1–200, defaults to 50)
  • sortBy, string, optional, the literal createdAt (the default, and currently the only supported value)
  • sortOrder, string, optional, sort direction: asc or desc (defaults to desc)
  • status, string, optional, comma-separated list of initialCheck, published, deleted, selfDeleted, or the literal all. Defaults to all statuses — pass status=published if you only want live content
  • reviewType, string, optional, one of ai, moderator. Use moderator to restrict to content that went through human review
  • boardIds, string, optional, comma-separated forum board identifiers
  • authorEmail, string, optional, restrict to content written by one member

To list the pending-review queue:

GET /forum/posts?status=initialCheck&reviewType=moderator

Response Example:

{
"size": 2,
"pageNumber": 1,
"pageSize": 50,
"sortBy": "createdAt",
"sortOrder": "desc",
"results": [
{
"id": "6553ce608b3f645e79d95034",
"slug": "how-to-get-started",
"title": "How to get started",
"content": "Here is a guide on how to get started...",
"type": "discussion",
"status": "published",
"reviewType": "ai",
"deleteReason": [],
"boardId": "6553ce608b3f645e79d95001",
"active": true,
"viewCount": 42,
"commentsCount": 3,
"reactionSummary": {
"totalCount": 5,
"positiveCount": 5,
"negativeCount": 0,
"details": {}
},
"tags": ["Getting Started", "Guide"],
"posterUrl": "",
"locked": false,
"answered": false,
"createdAt": "2024-11-14T10:30:00.000Z",
"updatedAt": "2024-11-14T10:30:00.000Z",
"lastEditAt": "2024-11-14T10:30:00.000Z",
"lastCommentedAt": "2024-11-15T08:00:00.000Z",
"board": "General Discussion",
"poster": {
"email": "[email protected]",
"firstName": "Jane",
"lastName": "Doe",
"pictureUrl": "https://example.com/avatar.jpg",
"headline": "Software Engineer at Test Company"
}
},
{
"id": "6553ce608b3f645e79d95035",
"slug": "feature-request-dark-mode",
"title": "Feature Request: Dark Mode",
"content": "It would be great to have a dark mode option...",
"type": "question",
"status": "published",
"reviewType": "moderator",
"deleteReason": [],
"boardId": "6553ce608b3f645e79d95002",
"active": true,
"viewCount": 18,
"commentsCount": 1,
"reactionSummary": {
"totalCount": 2,
"positiveCount": 2,
"negativeCount": 0,
"details": {}
},
"tags": ["Feature Request"],
"posterUrl": "",
"locked": false,
"answered": true,
"createdAt": "2024-11-13T14:00:00.000Z",
"updatedAt": "2024-11-13T14:00:00.000Z",
"lastEditAt": "2024-11-13T14:00:00.000Z",
"lastCommentedAt": "2024-11-14T09:15:00.000Z",
"board": "Ideas & Feedback",
"poster": {
"email": "[email protected]",
"firstName": "John",
"lastName": "Smith",
"pictureUrl": "",
"headline": "Product Manager"
}
}
]
}

Forum Post Fields:

  • id, string, the post's unique identifier
  • slug, string, URL-friendly identifier for the post
  • title, string, the post title
  • content, string, the post body content
  • type, string, post type (e.g. discussion, question)
  • status, string, moderation status: initialCheck (awaiting review), published, deleted (removed by a moderator), or selfDeleted (removed by its author)
  • reviewType, string, how the post was reviewed: ai or moderator. Absent on posts that never went through review
  • deleteReason, array of strings, the moderation categories recorded when the post was deleted (see Moderation categories). Empty for posts that have not been deleted
  • boardId, string, the identifier of the forum board the post belongs to — pass it to the boardIds filter
  • active, boolean, whether the post is active
  • viewCount, number, total number of views
  • commentsCount, number, total number of comments
  • reactionSummary, object, aggregated reaction counts (totalCount, positiveCount, negativeCount, details)
  • tags, array of strings, tag names associated with the post
  • board, string, name of the forum board the post belongs to
  • poster, object, author information (email, firstName, lastName, pictureUrl, headline)
  • posterUrl, string, URL of the post's cover image (if any)
  • locked, boolean, whether the post is locked for new comments
  • answered, boolean, whether the post has an accepted answer (relevant for question type posts)
  • createdAt, string, ISO 8601 timestamp of when the post was created
  • updatedAt, string, ISO 8601 timestamp of the last record update. Moderation actions do not move it — see Notes on usage at volume
  • lastEditAt, string, ISO 8601 timestamp of the last edit
  • lastCommentedAt, string, ISO 8601 timestamp of the last comment

Get Forum Post by ID

URL: https://api.gradual-api.com/public-api/v1/forum/posts/:postId

HTTP Method: GET

Content type: application/json

Tier: Light

Path Parameters:

  • postId, string, required, the post's ID

Response Example:

{
"id": "6553ce608b3f645e79d95034",
"slug": "how-to-get-started",
"title": "How to get started",
"content": "Here is a guide on how to get started...",
"type": "discussion",
"status": "published",
"reviewType": "ai",
"deleteReason": [],
"boardId": "6553ce608b3f645e79d95001",
"active": true,
"viewCount": 42,
"commentsCount": 3,
"reactionSummary": {
"totalCount": 5,
"positiveCount": 5,
"negativeCount": 0,
"details": {}
},
"tags": ["Getting Started", "Guide"],
"posterUrl": "",
"locked": false,
"answered": false,
"createdAt": "2024-11-14T10:30:00.000Z",
"updatedAt": "2024-11-14T10:30:00.000Z",
"lastEditAt": "2024-11-14T10:30:00.000Z",
"lastCommentedAt": "2024-11-15T08:00:00.000Z",
"board": "General Discussion",
"poster": {
"email": "[email protected]",
"firstName": "Jane",
"lastName": "Doe",
"pictureUrl": "https://example.com/avatar.jpg",
"headline": "Software Engineer at Test Company"
}
}

Notes:

  • The response fields are the same as a single item in the Get All Forum Posts response.
  • Returns 400 if the post is not found or the poster's account has been archived.

Get All Forum Comments

URL: https://api.gradual-api.com/public-api/v1/forum/comments

HTTP Method: GET

Content type: application/json

Tier: Medium

Query Parameters:

  • pageNum, integer, optional, page number (minimum 1, defaults to 1)
  • pageSize, integer, optional, number of results per page (1–200, defaults to 50)
  • sortBy, string, optional, the literal createdAt (the default, and currently the only supported value)
  • sortOrder, string, optional, sort direction: asc or desc (defaults to desc)
  • status, string, optional, comma-separated list of initialCheck, published, deleted, selfDeleted, or the literal all. Defaults to all statuses — pass status=published if you only want live content
  • reviewType, string, optional, one of ai, moderator. Use moderator to restrict to content that went through human review
  • boardIds, string, optional, comma-separated forum board identifiers
  • authorEmail, string, optional, restrict to content written by one member
  • postId, string, optional, restrict to comments on one specific post

To list the pending-review queue:

GET /forum/comments?status=initialCheck&reviewType=moderator

Response Example:

{
"size": 2,
"pageNumber": 1,
"pageSize": 50,
"sortBy": "createdAt",
"sortOrder": "desc",
"results": [
{
"id": "6553ce608b3f645e79d95040",
"content": "Great post! This was very helpful.",
"createdAt": "2024-11-15T08:00:00.000Z",
"updatedAt": "2024-11-15T08:00:00.000Z",
"lastEditAt": "2024-11-15T08:00:00.000Z",
"acceptedAsAnswer": false,
"status": "published",
"reviewType": "ai",
"deleteReason": [],
"postId": "6553ce608b3f645e79d95034",
"postSlug": "how-to-get-started",
"postTitle": "How to get started",
"boardId": "6553ce608b3f645e79d95001",
"board": "General Discussion",
"commenter": {
"email": "[email protected]",
"firstName": "John",
"lastName": "Smith",
"pictureUrl": "https://example.com/avatar.jpg",
"headline": "Product Manager"
}
},
{
"id": "6553ce608b3f645e79d95041",
"content": "You can enable it in Settings > Appearance.",
"createdAt": "2024-11-14T09:15:00.000Z",
"updatedAt": "2024-11-14T09:15:00.000Z",
"lastEditAt": "2024-11-14T09:15:00.000Z",
"acceptedAsAnswer": true,
"status": "published",
"reviewType": "ai",
"deleteReason": [],
"postId": "6553ce608b3f645e79d95035",
"postSlug": "feature-request-dark-mode",
"postTitle": "Feature Request: Dark Mode",
"boardId": "6553ce608b3f645e79d95002",
"board": "Ideas & Feedback",
"commenter": {
"email": "[email protected]",
"firstName": "Jane",
"lastName": "Doe",
"pictureUrl": "",
"headline": "Software Engineer at Test Company"
}
}
]
}

Forum Comment Fields:

  • id, string, the comment's unique identifier
  • content, string, the comment body
  • createdAt, string, ISO 8601 timestamp of when the comment was created
  • updatedAt, string, ISO 8601 timestamp of the last record update. Moderation actions do not move it — see Notes on usage at volume
  • lastEditAt, string, ISO 8601 timestamp of the last edit
  • acceptedAsAnswer, boolean, whether the comment has been accepted as the answer to the post
  • status, string, moderation status: initialCheck (awaiting review), published, deleted (removed by a moderator), or selfDeleted (removed by its author)
  • reviewType, string, how the comment was reviewed: ai or moderator. Absent on comments that never went through review
  • deleteReason, array of strings, the moderation categories recorded when the comment was deleted (see Moderation categories). Empty for comments that have not been deleted
  • postId, string, ID of the parent post
  • postSlug, string, URL-friendly identifier of the parent post
  • postTitle, string, title of the parent post
  • boardId, string, the identifier of the forum board the parent post belongs to — pass it to the boardIds filter
  • board, string, name of the forum board the parent post belongs to
  • commenter, object, author information (email, firstName, lastName, pictureUrl, headline)

Notes:

  • This endpoint returns comments across all posts. To get comments for a specific post, use Get Comments by Post ID instead.

Get Comments by Post ID

URL: https://api.gradual-api.com/public-api/v1/forum/posts/:postId/comments

HTTP Method: GET

Content type: application/json

Tier: Medium

Path Parameters:

  • postId, string, required, the post's ID

Query Parameters:

  • pageNum, integer, optional, page number (minimum 1, defaults to 1)
  • pageSize, integer, optional, number of results per page (1–200, defaults to 50)
  • sortBy, string, optional, the literal createdAt (the default, and currently the only supported value)
  • sortOrder, string, optional, sort direction: asc or desc (defaults to desc)

Response Example:

{
"size": 2,
"pageNumber": 1,
"pageSize": 50,
"sortBy": "createdAt",
"sortOrder": "desc",
"results": [
{
"id": "6553ce608b3f645e79d95040",
"content": "Great post! This was very helpful.",
"createdAt": "2024-11-15T08:00:00.000Z",
"updatedAt": "2024-11-15T08:00:00.000Z",
"lastEditAt": "2024-11-15T08:00:00.000Z",
"acceptedAsAnswer": false,
"status": "published",
"reviewType": "ai",
"deleteReason": [],
"postId": "6553ce608b3f645e79d95034",
"postSlug": "how-to-get-started",
"postTitle": "How to get started",
"boardId": "6553ce608b3f645e79d95001",
"board": "General Discussion",
"commenter": {
"email": "[email protected]",
"firstName": "John",
"lastName": "Smith",
"pictureUrl": "https://example.com/avatar.jpg",
"headline": "Product Manager"
}
},
{
"id": "6553ce608b3f645e79d95041",
"content": "Thanks for sharing!",
"createdAt": "2024-11-14T16:30:00.000Z",
"updatedAt": "2024-11-14T16:30:00.000Z",
"lastEditAt": "2024-11-14T16:30:00.000Z",
"acceptedAsAnswer": false,
"status": "published",
"reviewType": "ai",
"deleteReason": [],
"postId": "6553ce608b3f645e79d95034",
"postSlug": "how-to-get-started",
"postTitle": "How to get started",
"boardId": "6553ce608b3f645e79d95001",
"board": "General Discussion",
"commenter": {
"email": "[email protected]",
"firstName": "Jane",
"lastName": "Doe",
"pictureUrl": "",
"headline": "Software Engineer at Test Company"
}
}
]
}

Notes:

  • The response fields are the same as Get All Forum Comments, but scoped to a single post.
  • Returns 400 if the post is not found.

Moderation

These endpoints mirror the moderation actions available to admins and moderators in the Gradual dashboard, so a high-volume community can work its queues programmatically.

There are two separate queues. Which endpoint you use depends on which queue an item is in — mixing them up is the most common integration mistake.

QueueWhat's in itList it withKeep itRemove it
Pending reviewContent held before publishing, on boards that require moderator reviewGET /forum/posts?status=initialCheck&reviewType=moderatorPOST …/approvePOST …/delete
ReportedContent already published that members have reportedGET /forum/reported-posts · GET /forum/reported-commentsPOST …/ignore-reportsPOST …/delete

A reported item is already published, so POST …/approve does not apply to it — use POST …/ignore-reports to dismiss the reports and keep the content.

Keep reviewType=moderator on the pending-review query. Content in initialCheck with reviewType: "ai" is waiting on the automated check, not on you: approve returns 409 and delete returns 403 for it. Only moderator-review items are actionable.

Operator attribution

Every action endpoint (POST) requires operatorEmail in the request body — the email of the community member the action is attributed to. It is recorded in the moderation audit log and shown as "Reviewed by" in the Gradual dashboard.

That member must be an admin or a moderator of the board the content belongs to. This is a real permission check, not just a label:

  • missing or unresolvable operatorEmail400
  • the member exists but may not moderate that content → 403

Moderation categories

The values accepted by deleteReason on the delete endpoints. Any other value returns 400. Values are case-sensitive.

  • Forum posts and comments: Spam, Profane, BlockedUrl, Discrimination, Sexual, Violent, PII, AntiSpam, Offensive, Gibberish

Passing "Spam" is what marks content as spam, and is the same signal the dashboard's "mark as spam" produces. There is no separate "delete and mark spam" endpoint.

Note: deleting content always records a spam-rule violation and runs your community's auto-ban check, whether or not you include "Spam". What "Spam" adds is the explicit spam marking on the record itself.

Content already removed can carry a Moderator reason, which the dashboard sets when a moderator supplies only a custom message. Moderator is not accepted as input — do not echo a deleteReason array read from a deleted item straight back into a delete call.

Get Moderation Counts

URL: https://api.gradual-api.com/public-api/v1/forum/moderation/counts

HTTP Method: GET

Content type: application/json

Tier: Light

Returns the size of each moderation queue. Useful for deciding whether to run a sync at all.

Query Parameters:

  • boardIds, string, optional, comma-separated forum board identifiers to restrict the counts to

Response Example:

{
"pendingPosts": 8,
"pendingComments": 3,
"reportedPosts": 34,
"reportedComments": 12
}

Notes:

  • These counts are community-wide. The dashboard's equivalent badges are scoped to the boards the signed-in moderator may moderate, so these numbers will not match what any individual dashboard user sees.

List Reported Posts

URL: https://api.gradual-api.com/public-api/v1/forum/reported-posts

HTTP Method: GET

Content type: application/json

Tier: Medium

Returns posts that members have reported, one entry per post with its reports aggregated. Defaults to posts with reports still awaiting review — which in practice means published posts, since deleting a post accepts its reports. Widen reviewed or reportStatus and you will also see posts that have since been deleted; read each entry's post.status rather than assuming.

Query Parameters:

  • pageNum, integer, optional, page number (minimum 1, defaults to 1)
  • pageSize, integer, optional, number of results per page (1–200, defaults to 50)
  • reviewed, boolean, optional, defaults to false. false returns items with pending reports; true returns items whose reports have all been actioned
  • reportStatus, string, optional, one of pending, accepted, rejected, authorDeleted. When supplied, takes precedence over reviewed
  • boardIds, string, optional, comma-separated forum board identifiers
  • authorEmail, string, optional, restrict to posts written by one member
  • sortBy, string, optional, one of latestReported (most recently reported first) or topReported (most reported first), defaults to latestReported

Response Example:

{
"size": 1,
"pageNumber": 1,
"pageSize": 50,
"results": [
{
"sourceType": "ForumPost",
"sourceId": "665f1c2a9b3e4a0012ab34cd",
"reportsCount": 3,
"pendingReportsCount": 3,
"lastReportedAt": "2026-07-27T14:22:09.000Z",
"reviewedAt": null,
"reviewedBy": null,
"post": {
"id": "665f1c2a9b3e4a0012ab34cd",
"title": "Cheap watches for sale",
"status": "published",
"reviewType": "ai",
"deleteReason": [],
"boardId": "665f1c2a9b3e4a0012ab1000",
"board": "General"
}
}
]
}

Notes:

  • Items are grouped by reported content, not by report. A post reported by five members appears once with reportsCount: 5.
  • The post object has the same fields as Get All Forum Posts (abbreviated above).
  • Use GET /forum/reports?sourceId={sourceId} to see who reported an item and why.

List Reported Comments

URL: https://api.gradual-api.com/public-api/v1/forum/reported-comments

HTTP Method: GET

Content type: application/json

Tier: Medium

Identical to List Reported Posts, but returns reported forum comments. Each result carries a comment object instead of a post object, and sourceType is ForumComment.

Query Parameters: same as List Reported Posts.

List Reports

URL: https://api.gradual-api.com/public-api/v1/forum/reports

HTTP Method: GET

Content type: application/json

Tier: Medium

Returns individual reports — who reported an item, why, and whether that report has been actioned — one row per report, newest first.

Query Parameters:

  • pageNum, integer, optional, page number (minimum 1, defaults to 1)
  • pageSize, integer, optional, number of results per page (1–200, defaults to 50)
  • sortOrder, string, optional, sort direction: asc or desc (defaults to desc)
  • sourceType, string, optional, one of ForumPost, ForumComment
  • sourceId, string, optional, restrict to reports on one specific post or comment
  • reportStatus, string, optional, one of pending, accepted, rejected, authorDeleted. Defaults to pending
  • reporterEmail, string, optional, restrict to reports filed by one member

Response Example:

{
"size": 1,
"pageNumber": 1,
"pageSize": 50,
"results": [
{
"reportId": "665f1c2a9b3e4a0012abcc01",
"reportReason": "Advertising a product, not related to the board",
"reportStatus": "pending",
"reportedAt": "2026-07-27T14:22:09.000Z",
"reportFrom": "https://community.example.com/forum/posts/cheap-watches-for-sale-a1b2c3",
"reporter": {
"email": "[email protected]",
"firstName": "Jordan",
"lastName": "Kim"
}
}
]
}

Notes:

  • One row per report — an item reported by five members returns five rows here. Use the reported-list endpoints for the aggregated, one-row-per-item view.
  • Filters that match nothing — including a sourceId for an item that does not exist — return an empty results array, not 404.

Approve a Post

URL: https://api.gradual-api.com/public-api/v1/forum/posts/{postId}/approve

HTTP Method: POST

Content type: application/json

Tier: Medium

Approves a post that is pending review and publishes it. Notifies the author.

Path Parameters:

  • postId, string, required, the unique identifier of the post

Request Body Parameters:

  • operatorEmail, string, required, the email of the member to attribute this action to
  • reason, string, optional, a note recorded in the moderation audit log

Request Body Example:

{
"operatorEmail": "[email protected]",
"reason": "Looks fine, on topic"
}

Response Example (200 OK): the updated Forum Post object, with status now published.

Notes:

  • Only applies to the pending review queue. A post that is already published — including one sitting in the reported queue — is not "approved"; see the queue table above.
  • Returns 200 and the current post if the post was already approved, so retries are safe.
  • Returns 409 if the post is in any other state (for example already deleted). The response body names the current status.
  • Returns 404 if no post with the given postId exists in your community.

Delete a Post

URL: https://api.gradual-api.com/public-api/v1/forum/posts/{postId}/delete

HTTP Method: POST

Content type: application/json

Tier: Medium

Removes a post from the community. Works on both published posts and posts pending review.

Path Parameters:

  • postId, string, required, the unique identifier of the post

Request Body Parameters:

  • operatorEmail, string, required, the email of the member to attribute this action to
  • deleteReason, array of strings, optional, one or more moderation categories (see Moderation categories). Include "Spam" to mark the post as spam
  • customMessage, string, optional, a free-text note shown to the author explaining the removal

Request Body Example — remove and mark as spam:

{
"operatorEmail": "[email protected]",
"deleteReason": ["Spam"]
}

Response Example (200 OK): the updated Forum Post object, with status now deleted.

Notes:

  • Deleting a post also accepts its pending reports. Every pending report on the post moves to accepted, so the post drops out of GET /forum/reported-posts on its own — you do not need a follow-up ignore-reports call.
  • Deleting a post hides its comments in the community UI, but not from this API. Members no longer see them under the removed post; the comments keep their own status and are still returned by GET /forum/comments (including GET /forum/comments?postId={postId}). If you are mirroring forum content into another system, hide a post's comments yourself when the post's status is deleted or selfDeleted — filtering on the comment's own status is not enough.
  • Depending on your community's auto-ban rules, repeatedly deleting a member's content may automatically ban that member.
  • Returns 409 if the post is already deleted, with currentStatus naming its state.
  • Returns 400 if deleteReason contains a value outside the supported moderation categories.

Ignore the Reports on a Post

URL: https://api.gradual-api.com/public-api/v1/forum/posts/{postId}/ignore-reports

HTTP Method: POST

Content type: application/json

Tier: Medium

Dismisses every pending report on a post and keeps the post published. This is the "this content is fine" action for the reported queue.

Path Parameters:

  • postId, string, required, the unique identifier of the post

Request Body Parameters:

  • operatorEmail, string, required, the email of the member to attribute this action to

Response Example (200 OK): the Forum Post object, unchanged apart from its reports now being dismissed.

Notes:

  • The post itself is not modified — only the reports against it move from pending to rejected.
  • Safe to call when there are no pending reports: returns 200 and does nothing.
  • Only needed when you are keeping the post. Deleting a post already moves its pending reports to accepted, so it clears the reported queue by itself.

Restore a Deleted Post

URL: https://api.gradual-api.com/public-api/v1/forum/posts/{postId}/recover

HTTP Method: POST

Content type: application/json

Tier: Medium

Republishes a post that was previously removed. This is the undo for an accidental delete.

Path Parameters:

  • postId, string, required, the unique identifier of the post

Request Body Parameters:

  • operatorEmail, string, required, the email of the member to attribute this action to

Response Example (200 OK): the updated Forum Post object, with status now published and deleteReason cleared.

Notes:

  • Returns 404 if the post does not exist or is not currently deleted.
  • Only moderator-deleted content can be restored. A post the author removed themselves has status: "selfDeleted" and returns 404 — it is not recoverable through this API.
  • Returns 409 if the post's board has since been archived — restore the board first.

Mark a Deleted Post as Spam

URL: https://api.gradual-api.com/public-api/v1/forum/posts/{postId}/mark-spam

HTTP Method: POST

Content type: application/json

Tier: Medium

Adds the Spam category to a post that has already been deleted, without deleting it again. Use this when you removed something first and only later determined it was spam.

Path Parameters:

  • postId, string, required, the unique identifier of the post

Request Body Parameters:

  • operatorEmail, string, required, the email of the member to attribute this action to

Response Example (200 OK): the updated Forum Post object, with "Spam" appended to deleteReason.

Notes:

  • To delete and mark as spam in a single call, use POST /forum/posts/{postId}/delete with deleteReason: ["Spam"] instead.
  • Returns 409 if the post is not currently deleted.

Comment actions

The forum comment actions mirror the post actions exactly. Replace postId with commentId in the path; request bodies are identical, and responses return the Forum Comment object instead of the Forum Post object.

EndpointMethodTierRequest body
/forum/comments/{commentId}/approvePOSTMediumoperatorEmail (required), reason
/forum/comments/{commentId}/deletePOSTMediumoperatorEmail (required), deleteReason, customMessage
/forum/comments/{commentId}/ignore-reportsPOSTMediumoperatorEmail (required)
/forum/comments/{commentId}/recoverPOSTMediumoperatorEmail (required)
/forum/comments/{commentId}/mark-spamPOSTMediumoperatorEmail (required)

Notes:

  • Deleting a comment also accepts its pending reports, exactly as for posts — no follow-up ignore-reports call is needed.
  • Deleting a comment does not delete its replies. They are unreachable in the community UI, but keep their own status and are still returned by GET /forum/comments.
  • 🚨 delete requires the parent post to be published. If the post has itself been deleted, or is still pending review, the call returns 404 with "message": "Comment is locked" — so delete the comments you want removed before you delete the post, not after. Once the post is gone its comments cannot be actioned through the API at all.

Moderation errors

StatusMeaning
400Invalid request — a missing or unresolvable operatorEmail, a malformed id, an unsupported deleteReason value, or a bad pagination/filter parameter
401Missing or invalid Authorization / x-client-id headers
403The operatorEmail member is not an admin or moderator for this content
404The post or comment does not exist in your community
409The item is not in a state that allows this action. currentStatus tells you what state it is in
429Rate limit exceeded

Error body — message is a human-readable English sentence, not a machine-readable code. Do not match on its text; branch on the HTTP status and, for 409, on currentStatus.

{
"message": "Cannot delete a post that has already been deleted",
"currentStatus": "deleted"
}

currentStatus is present whenever the rejection was caused by the item's state — always on 409, and on the 404 returned when an item you tried to recover is not currently deleted. It carries the item's status at the moment the action was rejected.

Notes on usage at volume

  • Page until short. size is the number of items in the current page. Continue paging until results contains fewer items than pageSize.
  • Act on a page, then re-read page 1. Because these lists shrink as you act on them, walking pages 1→N while deleting items will skip entries. The reliable pattern is: read page 1, action every item on it, read page 1 again, repeat until empty.
  • Retries are safe. Approve and ignore-reports are idempotent — repeating a completed action returns 200 with the current state. Delete returns 409 on a second call.
  • updatedAt does not move on moderation actions. Approving or deleting content deliberately preserves the original timestamp, so you cannot use updatedAt to detect that an item was moderated. It is returned on every post and comment for reference, but it is not offered as a sortBy value for exactly this reason — sorting a review queue by it would be misleading.