/*
* Zernio API
*
* API reference for Zernio. Authenticate with a Bearer API key. Base URL: https://zernio.com/api Versioning and deprecation: all endpoints are versioned in the URL path (current version: /v1). Breaking changes only ship in a new path version; existing versions keep working. Deprecated operations are marked 'deprecated: true' in this spec and announced in the changelog (https://zernio.com/changelog) before removal. Errors: every 4xx/5xx response is application/json with a machine-readable 'code' and a human-readable 'error' message (see the ErrorResponse schema). Request ids: responses carry an X-Request-Id header with the id we log the request under. Quote it when reporting a problem. A valid x-request-id you send is reused as that id.
*
* The version of the OpenAPI document: 1.99.0
* Contact: support@zernio.com
* Generated by: https://openapi-generator.tech
*/
use super::{configuration, ContentType, Error};
use crate::{apis::ResponseContent, models};
use reqwest;
use serde::{de::Error as _, Deserialize, Serialize};
/// struct for typed errors of method [`delete_inbox_comment`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum DeleteInboxCommentError {
Status400(models::GetYouTubeDailyViews400Response),
Status401(models::InlineObject1),
Status403(),
Status429(models::ErrorResponse),
Status502(),
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`edit_inbox_comment`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum EditInboxCommentError {
Status400(),
Status401(models::InlineObject1),
Status403(),
Status404(),
Status502(),
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`get_inbox_post_comments`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum GetInboxPostCommentsError {
Status400(),
Status401(models::InlineObject1),
Status403(),
Status429(models::ErrorResponse),
Status502(),
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`hide_inbox_comment`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum HideInboxCommentError {
Status400(),
Status401(models::InlineObject1),
Status403(),
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`like_inbox_comment`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum LikeInboxCommentError {
Status400(),
Status401(models::InlineObject1),
Status403(),
Status409(),
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`like_post`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum LikePostError {
Status400(models::ErrorResponse),
Status401(models::InlineObject1),
Status403(),
Status404(),
Status409(),
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`list_inbox_comments`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum ListInboxCommentsError {
Status401(models::InlineObject1),
Status403(),
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`pin_inbox_comment`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum PinInboxCommentError {
Status400(models::ErrorResponse),
Status401(models::InlineObject1),
Status403(),
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`reply_to_inbox_post`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum ReplyToInboxPostError {
Status400(),
Status401(models::InlineObject1),
Status403(),
Status409(),
Status422(),
Status429(models::ErrorResponse),
Status502(),
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`send_private_reply_to_comment`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum SendPrivateReplyToCommentError {
Status400(models::ErrorResponse),
Status401(models::InlineObject1),
Status403(),
Status404(),
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`set_comment_moderation`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum SetCommentModerationError {
Status400(),
Status401(models::InlineObject1),
Status403(),
Status404(),
Status502(),
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`unhide_inbox_comment`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum UnhideInboxCommentError {
Status400(),
Status401(models::InlineObject1),
Status403(),
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`unlike_inbox_comment`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum UnlikeInboxCommentError {
Status400(),
Status401(models::InlineObject1),
Status403(),
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`unlike_post`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum UnlikePostError {
Status400(models::ErrorResponse),
Status401(models::InlineObject1),
Status403(),
Status404(),
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`unpin_inbox_comment`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum UnpinInboxCommentError {
Status400(models::ErrorResponse),
Status401(models::InlineObject1),
Status403(),
UnknownValue(serde_json::Value),
}
/// Delete a comment on a post. Supported by Facebook, Instagram, Threads, LinkedIn, Reddit, Bluesky, X (Twitter), YouTube, and TikTok (accounts connected through the TikTok for Business app). Not supported on Google Business (reviews only). Requires accountId and commentId query parameters.
pub async fn delete_inbox_comment(
configuration: &configuration::Configuration,
post_id: &str,
account_id: &str,
comment_id: &str,
) -> Result<models::DeleteInboxComment200Response, Error<DeleteInboxCommentError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_path_post_id = post_id;
let p_query_account_id = account_id;
let p_query_comment_id = comment_id;
let uri_str = format!(
"{}/v1/inbox/comments/{postId}",
configuration.base_path,
postId = crate::apis::urlencode(p_path_post_id)
);
let mut req_builder = configuration
.client
.request(reqwest::Method::DELETE, &uri_str);
req_builder = req_builder.query(&[("accountId", &p_query_account_id.to_string())]);
req_builder = req_builder.query(&[("commentId", &p_query_comment_id.to_string())]);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
let content_type = resp
.headers()
.get("content-type")
.and_then(|v| v.to_str().ok())
.unwrap_or("application/octet-stream");
let content_type = super::ContentType::from(content_type);
if !status.is_client_error() && !status.is_server_error() {
let content = resp.text().await?;
match content_type {
ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::DeleteInboxComment200Response`"))),
ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::DeleteInboxComment200Response`")))),
}
} else {
let content = resp.text().await?;
let entity: Option<DeleteInboxCommentError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent {
status,
content,
entity,
}))
}
}
/// Edit the body of a comment the connected account posted. Supported on Reddit only. Reddit keeps the same comment id after an edit. Reddit exposes no API to edit a post title, and a link post has no editable body. To edit a published post's body, use `POST /v1/posts/{postId}/edit`.
pub async fn edit_inbox_comment(
configuration: &configuration::Configuration,
post_id: &str,
comment_id: &str,
edit_inbox_comment_request: models::EditInboxCommentRequest,
) -> Result<models::EditInboxComment200Response, Error<EditInboxCommentError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_path_post_id = post_id;
let p_path_comment_id = comment_id;
let p_body_edit_inbox_comment_request = edit_inbox_comment_request;
let uri_str = format!(
"{}/v1/inbox/comments/{postId}/{commentId}",
configuration.base_path,
postId = crate::apis::urlencode(p_path_post_id),
commentId = crate::apis::urlencode(p_path_comment_id)
);
let mut req_builder = configuration
.client
.request(reqwest::Method::PATCH, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_edit_inbox_comment_request);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
let content_type = resp
.headers()
.get("content-type")
.and_then(|v| v.to_str().ok())
.unwrap_or("application/octet-stream");
let content_type = super::ContentType::from(content_type);
if !status.is_client_error() && !status.is_server_error() {
let content = resp.text().await?;
match content_type {
ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::EditInboxComment200Response`"))),
ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::EditInboxComment200Response`")))),
}
} else {
let content = resp.text().await?;
let entity: Option<EditInboxCommentError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent {
status,
content,
entity,
}))
}
}
/// Fetch comments for a specific post. Requires accountId query parameter. Pass `commentId` (Facebook, Instagram, Reddit, TikTok) to fetch replies to a specific comment instead of the post's top-level comments. Facebook, Instagram and TikTok return the comment's replies, paged by `limit`/`cursor`; Reddit returns the focused comment thread instead. On Facebook and Instagram the requested comment itself comes back in the top-level `comment` field. On Facebook, passing a COMMENT id as `postId` (instead of using `commentId`) is also supported for backwards compatibility and returns that comment's replies the same way. Prefer `commentId` for new integrations; it also works on Instagram, which rejects a comment id passed as `postId`. YouTube does not support either form, `postId` must be a video id. Responses are cached for up to 10 minutes, so a page may lag new comments by that window. Do not poll this endpoint for real-time updates: subscribe to the `comment.received` webhook, which delivers new comments as they arrive. Your own writes (creating, replying to, or deleting a comment) refresh the cache immediately. TikTok is served for accounts connected through the TikTok for Business app: `postId` is the TikTok video id, each top-level comment carries up to three inline replies, and `commentId` pages the full reply list of one comment. Developer-app TikTok accounts return 400 with code `PLATFORM_LIMITATION`. Hidden comments: Facebook Pages and Instagram accounts connected through Instagram Login return them with `isHidden: true`. Instagram accounts connected through Facebook Login do not return them at all (Meta omits them, together with their replies), so a hidden comment and a deleted one look the same on this read.
pub async fn get_inbox_post_comments(
configuration: &configuration::Configuration,
post_id: &str,
account_id: &str,
subreddit: Option<&str>,
limit: Option<i32>,
cursor: Option<&str>,
comment_id: Option<&str>,
) -> Result<models::GetInboxPostComments200Response, Error<GetInboxPostCommentsError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_path_post_id = post_id;
let p_query_account_id = account_id;
let p_query_subreddit = subreddit;
let p_query_limit = limit;
let p_query_cursor = cursor;
let p_query_comment_id = comment_id;
let uri_str = format!(
"{}/v1/inbox/comments/{postId}",
configuration.base_path,
postId = crate::apis::urlencode(p_path_post_id)
);
let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
req_builder = req_builder.query(&[("accountId", &p_query_account_id.to_string())]);
if let Some(ref param_value) = p_query_subreddit {
req_builder = req_builder.query(&[("subreddit", ¶m_value.to_string())]);
}
if let Some(ref param_value) = p_query_limit {
req_builder = req_builder.query(&[("limit", ¶m_value.to_string())]);
}
if let Some(ref param_value) = p_query_cursor {
req_builder = req_builder.query(&[("cursor", ¶m_value.to_string())]);
}
if let Some(ref param_value) = p_query_comment_id {
req_builder = req_builder.query(&[("commentId", ¶m_value.to_string())]);
}
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
let content_type = resp
.headers()
.get("content-type")
.and_then(|v| v.to_str().ok())
.unwrap_or("application/octet-stream");
let content_type = super::ContentType::from(content_type);
if !status.is_client_error() && !status.is_server_error() {
let content = resp.text().await?;
match content_type {
ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::GetInboxPostComments200Response`"))),
ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::GetInboxPostComments200Response`")))),
}
} else {
let content = resp.text().await?;
let entity: Option<GetInboxPostCommentsError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent {
status,
content,
entity,
}))
}
}
/// Hide a comment on a post. Supported by Facebook, Instagram, Threads, X, and TikTok (accounts connected through the TikTok for Business app). Hidden comments are only visible to the commenter and page admin. For X, the reply must belong to a conversation started by the authenticated user.
pub async fn hide_inbox_comment(
configuration: &configuration::Configuration,
post_id: &str,
comment_id: &str,
hide_inbox_comment_request: models::HideInboxCommentRequest,
) -> Result<models::HideInboxComment200Response, Error<HideInboxCommentError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_path_post_id = post_id;
let p_path_comment_id = comment_id;
let p_body_hide_inbox_comment_request = hide_inbox_comment_request;
let uri_str = format!(
"{}/v1/inbox/comments/{postId}/{commentId}/hide",
configuration.base_path,
postId = crate::apis::urlencode(p_path_post_id),
commentId = crate::apis::urlencode(p_path_comment_id)
);
let mut req_builder = configuration
.client
.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_hide_inbox_comment_request);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
let content_type = resp
.headers()
.get("content-type")
.and_then(|v| v.to_str().ok())
.unwrap_or("application/octet-stream");
let content_type = super::ContentType::from(content_type);
if !status.is_client_error() && !status.is_server_error() {
let content = resp.text().await?;
match content_type {
ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::HideInboxComment200Response`"))),
ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::HideInboxComment200Response`")))),
}
} else {
let content = resp.text().await?;
let entity: Option<HideInboxCommentError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent {
status,
content,
entity,
}))
}
}
/// Like or upvote a comment on a post. Supported platforms: Facebook, X, Bluesky, Reddit, LinkedIn, and Instagram in limited release (see below). For Bluesky, the cid (content identifier) is required in the request body. For LinkedIn, pass the composite comment URN returned by the comments endpoints as commentId; an optional reactionType picks the reaction (defaults to LIKE), and accounts connected before the social-feed scopes were requested get a 403 with code `linkedin_reconnect_required`. Instagram is in LIMITED RELEASE and not generally available: the call needs `instagram_manage_engagement`, which Meta has so far granted this app only under Standard Access, so it works for app admins, developers and testers of our Meta app and returns a 403 with code `PLATFORM_BETA_RESTRICTED` for every other account. That restriction lifts when Meta App Review grants Advanced Access; the constraints below apply once it does. Instagram covers comments and replies on feed posts, reels and carousels. Only an account connected through Facebook Login can be granted `instagram_manage_engagement`: an Instagram Login connection returns a 400 with code `instagram_likes_require_facebook_login`, and an account whose token predates the permission returns a 403 with code `reconnect_required`. Content from private accounts cannot be liked. Instagram also enforces a burst limit of 50 like or unlike calls per 5 seconds per Instagram account, and exceeding it locks that account out of the like API for an hour, so pace bulk loops.
pub async fn like_inbox_comment(
configuration: &configuration::Configuration,
post_id: &str,
comment_id: &str,
like_inbox_comment_request: models::LikeInboxCommentRequest,
) -> Result<models::LikeInboxComment200Response, Error<LikeInboxCommentError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_path_post_id = post_id;
let p_path_comment_id = comment_id;
let p_body_like_inbox_comment_request = like_inbox_comment_request;
let uri_str = format!(
"{}/v1/inbox/comments/{postId}/{commentId}/like",
configuration.base_path,
postId = crate::apis::urlencode(p_path_post_id),
commentId = crate::apis::urlencode(p_path_comment_id)
);
let mut req_builder = configuration
.client
.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_like_inbox_comment_request);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
let content_type = resp
.headers()
.get("content-type")
.and_then(|v| v.to_str().ok())
.unwrap_or("application/octet-stream");
let content_type = super::ContentType::from(content_type);
if !status.is_client_error() && !status.is_server_error() {
let content = resp.text().await?;
match content_type {
ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::LikeInboxComment200Response`"))),
ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::LikeInboxComment200Response`")))),
}
} else {
let content = resp.text().await?;
let entity: Option<LikeInboxCommentError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent {
status,
content,
entity,
}))
}
}
/// Like (or react to) a post as a connected account. Supported platforms: LinkedIn, X, Facebook, YouTube, Bluesky, and Instagram in limited release (see below). Threads, TikTok and Pinterest expose no like endpoint in their APIs and return 400. Reddit returns 400 too, pointing at `POST /v1/accounts/{accountId}/reddit-vote`, which covers upvote, downvote and clear on both posts and comments. The account does not have to be the one that published the post, which is what makes executive engagement possible: pass an exec's `accountId` and the brand post's ID. `postId` accepts either a Zernio post ID or the platform's native post ID. A Zernio post ID resolves to the entry for `accountId`, falling back to the post's single entry on the same platform (two entries on that platform is a 400, so pass the native ID). LinkedIn requires the `w_member_social_feed` / `w_organization_social_feed` scopes, which are not retroactive: accounts connected before those were requested get a 403 with code `linkedin_reconnect_required` until the user reconnects the account. YouTube spends 50 quota units per call. Instagram is in LIMITED RELEASE and not generally available: the call needs `instagram_manage_engagement`, which Meta has so far granted this app only under Standard Access, so it works for app admins, developers and testers of our Meta app and returns a 403 with code `PLATFORM_BETA_RESTRICTED` for every other account. That restriction lifts when Meta App Review grants Advanced Access; the constraints below apply once it does. Instagram covers feed images, reels and carousels (stories and private-account media are not likeable). Only an account connected through Facebook Login can be granted `instagram_manage_engagement`: an Instagram Login connection returns a 400 with code `instagram_likes_require_facebook_login`, and an account whose token predates the permission returns a 403 with code `reconnect_required`. Instagram also enforces a burst limit of 50 like or unlike calls per 5 seconds per Instagram account, and exceeding it locks that account out of the like API for an hour, so pace bulk loops.
pub async fn like_post(
configuration: &configuration::Configuration,
post_id: &str,
like_post_request: models::LikePostRequest,
) -> Result<models::LikePost200Response, Error<LikePostError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_path_post_id = post_id;
let p_body_like_post_request = like_post_request;
let uri_str = format!(
"{}/v1/inbox/posts/{postId}/like",
configuration.base_path,
postId = crate::apis::urlencode(p_path_post_id)
);
let mut req_builder = configuration
.client
.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_like_post_request);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
let content_type = resp
.headers()
.get("content-type")
.and_then(|v| v.to_str().ok())
.unwrap_or("application/octet-stream");
let content_type = super::ContentType::from(content_type);
if !status.is_client_error() && !status.is_server_error() {
let content = resp.text().await?;
match content_type {
ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::LikePost200Response`"))),
ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::LikePost200Response`")))),
}
} else {
let content = resp.text().await?;
let entity: Option<LikePostError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent {
status,
content,
entity,
}))
}
}
/// Returns posts with comment counts from all connected accounts. Aggregates data across multiple accounts. Responses are cached for up to 10 minutes, so the feed may lag new comments by that window. Do not poll this endpoint for real-time updates: subscribe to the `comment.received` webhook, which fires for every new comment across your posts and carries the post reference needed to keep this list current. For users with the Ads add-on (accounts on usage-based billing always qualify), the user's Meta ads (boosted/dark posts) are included too. There's one row per (ad, placement-with-comments): an ad that runs on both Facebook feed and Instagram feed produces up to two rows (the Page dark post and the IG media have separate comment threads), each flagged `isAd: true` with `adId` and `placement` (`id` is `{adId}:{placement}`). Use `?platform=metaads` to return *only* ad rows; passing `facebook`/`instagram` returns *organic* posts only (no ads); omitting `platform` returns both. Fetch a row's thread from GET /v1/ads/{adId}/comments?placement={placement}. Ad comment counts are read with the Marketing API token (Facebook side) or the connected Instagram account's token (Instagram side); a row whose count can't be read is omitted. Pagination walks each account's platform listing. Following `nextCursor` reaches past the first page on Facebook, Instagram, Threads, LinkedIn and YouTube, since they are the platforms that support a server-side date window; on the others the listing stops at its first page. Cursor pagination is only coherent for the default sort (`sortBy=date`, `sortOrder=desc`): with `sortOrder=asc`, or with `sortBy=comments`, the cursor filter does not match the sort order and the second page is unreliable. `minComments` is applied to each page after pagination: a page can hold fewer than `limit` posts, even none, while `hasMore` is true; keep following `nextCursor`. `nextCursor` is opaque: pass it back verbatim, never construct or parse it, its composition may change without notice. Because each page re-queries a live window, results can still shift between requests, so dedupe by `id` on the client. `commentCount` semantics differ by platform: YouTube's includes replies, Facebook's counts top-level comments only.
pub async fn list_inbox_comments(
configuration: &configuration::Configuration,
profile_id: Option<&str>,
platform: Option<&str>,
min_comments: Option<i32>,
since: Option<String>,
sort_by: Option<&str>,
sort_order: Option<&str>,
limit: Option<i32>,
cursor: Option<&str>,
account_id: Option<&str>,
) -> Result<models::ListInboxComments200Response, Error<ListInboxCommentsError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_query_profile_id = profile_id;
let p_query_platform = platform;
let p_query_min_comments = min_comments;
let p_query_since = since;
let p_query_sort_by = sort_by;
let p_query_sort_order = sort_order;
let p_query_limit = limit;
let p_query_cursor = cursor;
let p_query_account_id = account_id;
let uri_str = format!("{}/v1/inbox/comments", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
if let Some(ref param_value) = p_query_profile_id {
req_builder = req_builder.query(&[("profileId", ¶m_value.to_string())]);
}
if let Some(ref param_value) = p_query_platform {
req_builder = req_builder.query(&[("platform", ¶m_value.to_string())]);
}
if let Some(ref param_value) = p_query_min_comments {
req_builder = req_builder.query(&[("minComments", ¶m_value.to_string())]);
}
if let Some(ref param_value) = p_query_since {
req_builder = req_builder.query(&[("since", ¶m_value.to_string())]);
}
if let Some(ref param_value) = p_query_sort_by {
req_builder = req_builder.query(&[("sortBy", ¶m_value.to_string())]);
}
if let Some(ref param_value) = p_query_sort_order {
req_builder = req_builder.query(&[("sortOrder", ¶m_value.to_string())]);
}
if let Some(ref param_value) = p_query_limit {
req_builder = req_builder.query(&[("limit", ¶m_value.to_string())]);
}
if let Some(ref param_value) = p_query_cursor {
req_builder = req_builder.query(&[("cursor", ¶m_value.to_string())]);
}
if let Some(ref param_value) = p_query_account_id {
req_builder = req_builder.query(&[("accountId", ¶m_value.to_string())]);
}
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
let content_type = resp
.headers()
.get("content-type")
.and_then(|v| v.to_str().ok())
.unwrap_or("application/octet-stream");
let content_type = super::ContentType::from(content_type);
if !status.is_client_error() && !status.is_server_error() {
let content = resp.text().await?;
match content_type {
ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::ListInboxComments200Response`"))),
ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::ListInboxComments200Response`")))),
}
} else {
let content = resp.text().await?;
let entity: Option<ListInboxCommentsError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent {
status,
content,
entity,
}))
}
}
/// Pin a top-level comment to the top of a post's comment section. TikTok accounts connected through the TikTok for Business app only; every other platform returns 400.
pub async fn pin_inbox_comment(
configuration: &configuration::Configuration,
post_id: &str,
comment_id: &str,
pin_inbox_comment_request: models::PinInboxCommentRequest,
) -> Result<models::PinInboxComment200Response, Error<PinInboxCommentError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_path_post_id = post_id;
let p_path_comment_id = comment_id;
let p_body_pin_inbox_comment_request = pin_inbox_comment_request;
let uri_str = format!(
"{}/v1/inbox/comments/{postId}/{commentId}/pin",
configuration.base_path,
postId = crate::apis::urlencode(p_path_post_id),
commentId = crate::apis::urlencode(p_path_comment_id)
);
let mut req_builder = configuration
.client
.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_pin_inbox_comment_request);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
let content_type = resp
.headers()
.get("content-type")
.and_then(|v| v.to_str().ok())
.unwrap_or("application/octet-stream");
let content_type = super::ContentType::from(content_type);
if !status.is_client_error() && !status.is_server_error() {
let content = resp.text().await?;
match content_type {
ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::PinInboxComment200Response`"))),
ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::PinInboxComment200Response`")))),
}
} else {
let content = resp.text().await?;
let entity: Option<PinInboxCommentError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent {
status,
content,
entity,
}))
}
}
/// Post a reply to a post or specific comment. Requires accountId in request body. **Idempotency:** send an `Idempotency-Key` header to make retries safe (e.g. after a client-side timeout where delivery is unknown): same key + same body replays the original response (with `Idempotent-Replayed: true`) instead of posting the comment a second time; same key + different body returns 422; a key still in flight returns 409. Keys are retained for 24 hours and are scoped to the credential and to this exact path, so reusing a key against a different postId returns 422 rather than replaying the other post's response. Only successful (2xx) responses are stored for replay. If the request throws or returns a non-2xx status the key is released, so the header protects the \"request succeeded but the response was lost\" case. After an ambiguous failure (a 5xx or a network timeout) list the post's comments before retrying with the same key, and treat an empty result as inconclusive rather than as proof nothing was posted.
pub async fn reply_to_inbox_post(
configuration: &configuration::Configuration,
post_id: &str,
reply_to_inbox_post_request: models::ReplyToInboxPostRequest,
idempotency_key: Option<&str>,
) -> Result<models::ReplyToInboxPost200Response, Error<ReplyToInboxPostError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_path_post_id = post_id;
let p_body_reply_to_inbox_post_request = reply_to_inbox_post_request;
let p_header_idempotency_key = idempotency_key;
let uri_str = format!(
"{}/v1/inbox/comments/{postId}",
configuration.base_path,
postId = crate::apis::urlencode(p_path_post_id)
);
let mut req_builder = configuration
.client
.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(param_value) = p_header_idempotency_key {
req_builder = req_builder.header("Idempotency-Key", param_value.to_string());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_reply_to_inbox_post_request);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
let content_type = resp
.headers()
.get("content-type")
.and_then(|v| v.to_str().ok())
.unwrap_or("application/octet-stream");
let content_type = super::ContentType::from(content_type);
if !status.is_client_error() && !status.is_server_error() {
let content = resp.text().await?;
match content_type {
ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::ReplyToInboxPost200Response`"))),
ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::ReplyToInboxPost200Response`")))),
}
} else {
let content = resp.text().await?;
let entity: Option<ReplyToInboxPostError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent {
status,
content,
entity,
}))
}
}
/// Send a direct message to the author of a comment. Supported on Instagram and Facebook only. One reply per comment, must be sent within 7 days. Optionally attach interactive elements: `quickReplies` (chips above the keyboard, max 13) or `buttons` (1-3 inline postback/url buttons rendered in the same bubble via Meta's button_template). Chips do not render in the Instagram Message Requests folder. Since late August 2026 Instagram refuses buttons, cards and attachments to commenters who do not follow the account (Meta code 2, subcode 1545133, returned here as a non-retryable 400 that says so), and the failed call still consumes the comment's single private reply. To reach non-followers send plain text and add buttons once they reply. `quickReplies` and `buttons` are mutually exclusive. When the comment's single private reply is spent (by this call or an earlier one) the 400 carries `details.privateReplyConsumed: true`; never retry it.
pub async fn send_private_reply_to_comment(
configuration: &configuration::Configuration,
post_id: &str,
comment_id: &str,
send_private_reply_to_comment_request: models::SendPrivateReplyToCommentRequest,
) -> Result<models::SendPrivateReplyToComment200Response, Error<SendPrivateReplyToCommentError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_path_post_id = post_id;
let p_path_comment_id = comment_id;
let p_body_send_private_reply_to_comment_request = send_private_reply_to_comment_request;
let uri_str = format!(
"{}/v1/inbox/comments/{postId}/{commentId}/private-reply",
configuration.base_path,
postId = crate::apis::urlencode(p_path_post_id),
commentId = crate::apis::urlencode(p_path_comment_id)
);
let mut req_builder = configuration
.client
.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_send_private_reply_to_comment_request);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
let content_type = resp
.headers()
.get("content-type")
.and_then(|v| v.to_str().ok())
.unwrap_or("application/octet-stream");
let content_type = super::ContentType::from(content_type);
if !status.is_client_error() && !status.is_server_error() {
let content = resp.text().await?;
match content_type {
ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::SendPrivateReplyToComment200Response`"))),
ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::SendPrivateReplyToComment200Response`")))),
}
} else {
let content = resp.text().await?;
let entity: Option<SendPrivateReplyToCommentError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent {
status,
content,
entity,
}))
}
}
/// Set a comment's moderation status. Supported on YouTube only. Use this to work a moderation queue: approve a held comment (`published`), reject it (`rejected`), or send it back for review (`heldForReview`). The request must be authorized by the owner of the channel or video the comment belongs to. You cannot moderate comments on videos you do not own. This is distinct from `POST /v1/inbox/comments/{postId}/{commentId}/hide`, which covers Facebook, Instagram, Threads, and X and does not apply to YouTube.
pub async fn set_comment_moderation(
configuration: &configuration::Configuration,
post_id: &str,
comment_id: &str,
set_comment_moderation_request: models::SetCommentModerationRequest,
) -> Result<models::UpdateYoutubeDefaultPlaylist200Response, Error<SetCommentModerationError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_path_post_id = post_id;
let p_path_comment_id = comment_id;
let p_body_set_comment_moderation_request = set_comment_moderation_request;
let uri_str = format!(
"{}/v1/inbox/comments/{postId}/{commentId}/moderation",
configuration.base_path,
postId = crate::apis::urlencode(p_path_post_id),
commentId = crate::apis::urlencode(p_path_comment_id)
);
let mut req_builder = configuration
.client
.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_set_comment_moderation_request);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
let content_type = resp
.headers()
.get("content-type")
.and_then(|v| v.to_str().ok())
.unwrap_or("application/octet-stream");
let content_type = super::ContentType::from(content_type);
if !status.is_client_error() && !status.is_server_error() {
let content = resp.text().await?;
match content_type {
ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::UpdateYoutubeDefaultPlaylist200Response`"))),
ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::UpdateYoutubeDefaultPlaylist200Response`")))),
}
} else {
let content = resp.text().await?;
let entity: Option<SetCommentModerationError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent {
status,
content,
entity,
}))
}
}
/// Unhide a previously hidden comment. Supported by Facebook, Instagram, Threads, X, and TikTok (accounts connected through the TikTok for Business app).
pub async fn unhide_inbox_comment(
configuration: &configuration::Configuration,
post_id: &str,
comment_id: &str,
account_id: &str,
) -> Result<models::HideInboxComment200Response, Error<UnhideInboxCommentError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_path_post_id = post_id;
let p_path_comment_id = comment_id;
let p_query_account_id = account_id;
let uri_str = format!(
"{}/v1/inbox/comments/{postId}/{commentId}/hide",
configuration.base_path,
postId = crate::apis::urlencode(p_path_post_id),
commentId = crate::apis::urlencode(p_path_comment_id)
);
let mut req_builder = configuration
.client
.request(reqwest::Method::DELETE, &uri_str);
req_builder = req_builder.query(&[("accountId", &p_query_account_id.to_string())]);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
let content_type = resp
.headers()
.get("content-type")
.and_then(|v| v.to_str().ok())
.unwrap_or("application/octet-stream");
let content_type = super::ContentType::from(content_type);
if !status.is_client_error() && !status.is_server_error() {
let content = resp.text().await?;
match content_type {
ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::HideInboxComment200Response`"))),
ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::HideInboxComment200Response`")))),
}
} else {
let content = resp.text().await?;
let entity: Option<UnhideInboxCommentError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent {
status,
content,
entity,
}))
}
}
/// Remove a like from a comment. Supported platforms: Facebook, X, Bluesky, Reddit, LinkedIn, and Instagram in limited release. For Bluesky, the likeUri query parameter is required. Instagram has the same limited release, Facebook Login, `instagram_manage_engagement` and burst-limit constraints as liking.
pub async fn unlike_inbox_comment(
configuration: &configuration::Configuration,
post_id: &str,
comment_id: &str,
account_id: &str,
like_uri: Option<&str>,
) -> Result<models::UnlikeInboxComment200Response, Error<UnlikeInboxCommentError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_path_post_id = post_id;
let p_path_comment_id = comment_id;
let p_query_account_id = account_id;
let p_query_like_uri = like_uri;
let uri_str = format!(
"{}/v1/inbox/comments/{postId}/{commentId}/like",
configuration.base_path,
postId = crate::apis::urlencode(p_path_post_id),
commentId = crate::apis::urlencode(p_path_comment_id)
);
let mut req_builder = configuration
.client
.request(reqwest::Method::DELETE, &uri_str);
req_builder = req_builder.query(&[("accountId", &p_query_account_id.to_string())]);
if let Some(ref param_value) = p_query_like_uri {
req_builder = req_builder.query(&[("likeUri", ¶m_value.to_string())]);
}
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
let content_type = resp
.headers()
.get("content-type")
.and_then(|v| v.to_str().ok())
.unwrap_or("application/octet-stream");
let content_type = super::ContentType::from(content_type);
if !status.is_client_error() && !status.is_server_error() {
let content = resp.text().await?;
match content_type {
ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::UnlikeInboxComment200Response`"))),
ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::UnlikeInboxComment200Response`")))),
}
} else {
let content = resp.text().await?;
let entity: Option<UnlikeInboxCommentError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent {
status,
content,
entity,
}))
}
}
/// Remove this account's like from a post. Supported platforms: LinkedIn, X, Facebook, YouTube, Bluesky, and Instagram in limited release. On YouTube this clears the rating. Instagram has the same limited release, Facebook Login, `instagram_manage_engagement` and burst-limit constraints as liking. For Bluesky, `likeUri` (returned when the post was liked) is required. Reddit uses `POST /v1/accounts/{accountId}/reddit-vote` with `direction: 0`.
pub async fn unlike_post(
configuration: &configuration::Configuration,
post_id: &str,
account_id: &str,
like_uri: Option<&str>,
) -> Result<models::UnlikePost200Response, Error<UnlikePostError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_path_post_id = post_id;
let p_query_account_id = account_id;
let p_query_like_uri = like_uri;
let uri_str = format!(
"{}/v1/inbox/posts/{postId}/like",
configuration.base_path,
postId = crate::apis::urlencode(p_path_post_id)
);
let mut req_builder = configuration
.client
.request(reqwest::Method::DELETE, &uri_str);
req_builder = req_builder.query(&[("accountId", &p_query_account_id.to_string())]);
if let Some(ref param_value) = p_query_like_uri {
req_builder = req_builder.query(&[("likeUri", ¶m_value.to_string())]);
}
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
let content_type = resp
.headers()
.get("content-type")
.and_then(|v| v.to_str().ok())
.unwrap_or("application/octet-stream");
let content_type = super::ContentType::from(content_type);
if !status.is_client_error() && !status.is_server_error() {
let content = resp.text().await?;
match content_type {
ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::UnlikePost200Response`"))),
ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::UnlikePost200Response`")))),
}
} else {
let content = resp.text().await?;
let entity: Option<UnlikePostError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent {
status,
content,
entity,
}))
}
}
/// Unpin a previously pinned comment. TikTok accounts connected through the TikTok for Business app only.
pub async fn unpin_inbox_comment(
configuration: &configuration::Configuration,
post_id: &str,
comment_id: &str,
account_id: &str,
) -> Result<models::PinInboxComment200Response, Error<UnpinInboxCommentError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_path_post_id = post_id;
let p_path_comment_id = comment_id;
let p_query_account_id = account_id;
let uri_str = format!(
"{}/v1/inbox/comments/{postId}/{commentId}/pin",
configuration.base_path,
postId = crate::apis::urlencode(p_path_post_id),
commentId = crate::apis::urlencode(p_path_comment_id)
);
let mut req_builder = configuration
.client
.request(reqwest::Method::DELETE, &uri_str);
req_builder = req_builder.query(&[("accountId", &p_query_account_id.to_string())]);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
let content_type = resp
.headers()
.get("content-type")
.and_then(|v| v.to_str().ok())
.unwrap_or("application/octet-stream");
let content_type = super::ContentType::from(content_type);
if !status.is_client_error() && !status.is_server_error() {
let content = resp.text().await?;
match content_type {
ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::PinInboxComment200Response`"))),
ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::PinInboxComment200Response`")))),
}
} else {
let content = resp.text().await?;
let entity: Option<UnpinInboxCommentError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent {
status,
content,
entity,
}))
}
}