Skip to content
Dashboard

Create a new post

POST/v2/posts

Creates a new post (feedback submission) in the specified board.

Required Fields

  • title - Post title (minimum 2 characters). Required unless intakeMode is feedback; see “Intake mode” below.

Optional Fields

  • boardId - Board ID to create the post in. Omit to use the organization’s default board.
  • intakeMode - request (default) or feedback; see “Intake mode”.
  • source - { channel, externalId, url?, conversationId?, label? }; see “Provenance and idempotency”.
  • attachTo - An open request this post belongs with; see “attachTo, or link-insight?”.
  • internal - Store on the hidden internal board (never portal-visible); not with boardId.
  • content - Post content in HTML format
  • tags - Array of tag names to attach
  • statusId - Status ID to set (defaults to board’s default status)
  • commentsEnabled - Whether comments are allowed (default: true)
  • inReview - Whether post is pending moderation (default: false)
  • customFields - Custom field values as key-value pairs
  • eta - Estimated completion date (Unix timestamp or ISO date)
  • assigneeId - Admin ID to assign this post to
  • visibility - Post-level restriction: ‘public’, ‘authorOnly’ (author and admins) or ‘companyOnly’ (the author’s company). Board and organization access controls still apply.

Author Attribution

For posts created on behalf of users, use the author object:

  • id - Featurebase user ID
  • userId - External SSO user ID
  • email - User’s email address
  • name - Display name
  • profilePicture - Profile picture URL

Resolution priority: id > userId > email > authenticated user

Intake mode

intakeMode is the caller’s declared intent and the ONE field that selects how the post is processed; author and source only describe where the text came from.

  • request (default): a finished request, stored exactly as supplied — no AI extraction, no rewrite. Featurebase may still link existing customer evidence TO it in the background.
  • feedback: raw customer feedback (a Slack message, a call note, a survey answer). Processed like a portal post: organized into requests when the workspace’s “Organize submissions” lane is on, otherwise its claims are extracted and matched against existing requests. The workspace’s Autopilot dial, plan, AI budget, moderation and spam settings apply, also when the post is filed under the API key’s own user. statusId and eta are rejected (400). Feedback creates are rate-limited per workspace more strictly than requests (429 with Retry-After).

In feedback mode title is optional: omit it and the first line of content becomes the title, cut to 120 characters; content is then required (400 on content when both are empty). In request mode title stays required, minimum 2 characters.

At most 5 requests organized from one submission notify the team (admin notifications, mentions, Slack, Discord, tracker pushes); the rest are created silently, still returned in processing.results and still fire post.created.

Length limits for feedback

Text is read whole or rejected (400 on content; the message states the limit and the length sent). The count is plain text: title plus content without HTML. The limit follows source.channel: call 120,000 (a two-hour transcript), email and api 60,000, slack and discord 30,000; no channel means api. Workspaces with the AI switched off have no limit. To send more, split the text and give each part its own source.externalId.

Long text is read in parts, then each ask is matched and filed: seconds for a message, tens of minutes for a two-hour transcript. A repeated ask is reported once. One submission yields at most 30 requests: the 29 strongest, plus one held request listing the rest. Without the organize lane, at most 50 asks are captured. At most 20 submissions per workspace per hour may exceed one reading pass (about 16,000 characters with the organize lane, otherwise 6,000, or 24,000 for a call); past that, 429 with Retry-After.

The response reports intakeMode and processing: status is queued (an AI run was enqueued; its result lands on the post later), skipped with a reason (request_mode, autopilot_off, pipeline_paused, support_board, spam_held, staff_authored, …), or existing on an idempotent replay. Fetch GET /v2/posts/{id} to read where the feedback ended up.

Provenance and idempotency

source records where a request came from and makes the create idempotent: sending the same (channel, externalId) twice returns the first post unchanged, with deduped: true. Ids are stored as api:<externalId>, so they never collide with Featurebase’s own. The channels feedback, widget and support are reserved for the portal, the widget and the inbox (400). With source and no author, the post is attributed to a guest named after source.label (or the channel): a relayed request belongs to the customer who said it, not to the API key.

attachTo records that the NEW post belongs with an existing request. The post stays a post: it keeps kind: 'issue', stays in GET /v2/posts, keeps its own votes, its author does not become a supporter of the target, and it is not listed by GET /v2/posts/{targetId}/insights. The link is silent: no notification, no ack.

POST /v2/posts/{id}/link-insight files the post as a quote under the request instead: it becomes an insight, leaves the posts resource (GET /v2/posts/{id} answers 404), appears in GET /v2/posts/{targetId}/insights, and its author counts as a supporter.

Two customers asking for the same thing who each keep their own request → attachTo. A sentence that is evidence for a request you already track → create the post, then link-insight. Both take an open request in this workspace as target.

attachTo cannot be combined with intakeMode: 'feedback' (400 invalid_parameter on attachTo): one says where the text belongs, the other asks Featurebase to decide. The link is made AFTER the post is written, so an unusable target is a 422 that says the post was created — not rolled back. The target is refused when it is missing in this workspace, not a request, merged, a processed submission, awaiting moderation, held as spam, or the new post itself.

Backdating (Imports)

  • createdAt - Override creation date for importing historical data

Response

  • 201 - created. The post object, plus intakeMode and processing.
  • 200 - a post already existed for this (source.channel, source.externalId): that post, unchanged, with deduped: true and processing.status: 'existing'; a replay never links anything a second time.
  • 422 - attachTo named a request that cannot carry evidence. The post was still created; the error message says so.
Header ParametersExpand Collapse
"Featurebase-Version": optional "2026-08-19.orbit" or "2026-01-01.nova" or "2025-12-12.clover"
One of the following:
"2026-08-19.orbit"
"2026-01-01.nova"
"2025-12-12.clover"
Body ParametersJSONExpand Collapse
assigneeId: optional string

Admin ID to assign this post to

attachTo: optional string

Id of an existing open request this post is evidence for. The post is created, then linked.

author: optional AuthorInput { id, email, name, 2 more }

Author to attribute the post to. If not provided, uses the authenticated user — unless source is given, in which case a guest author is synthesised from source.label (or the channel name), because a relayed request belongs to the customer who said it. Supports multiple identification methods: id (Featurebase ID), userId (external SSO ID), or email.

id: optional string

Featurebase user ID to attribute content to

email: optional string

Author email (used to find or create user)

formatemail
name: optional string

Author display name

maxLength255
profilePicture: optional string

Author profile picture URL

userId: optional string

External user ID from your system (matched via SSO)

maxLength255
boardId: optional string

Board ID to create the post in. Omit to use the default board of the organization.

commentsEnabled: optional boolean

Whether comments are enabled on this post

content: optional string

Post content (HTML). Required when intakeMode is ‘feedback’ and no title is given. In ‘feedback’ mode its plain text is limited by source.channel (see intakeMode); longer content is rejected with a 400.

createdAt: optional string

Creation date (for backdating imports)

customFields: optional map[array of string or boolean or number or 2 more]

Custom field values. Keys must be valid ObjectIds. Values can be: string, boolean, number, ISO date string, array of strings, ObjectId string, or null.

One of the following:
array of string
boolean
number
string
string
eta: optional string

Estimated completion date

inReview: optional boolean

Whether post is pending moderation

intakeMode: optional "request" or "feedback"

What the text is. ‘request’ (default): a finished request — stored exactly as supplied, no AI claim extraction, regardless of author. ‘feedback’: raw customer feedback — processed like a portal post (organized into a request, or its claims extracted and matched against existing requests) under the workspace’s Autopilot dial, plan, AI budget and moderation settings. In ‘feedback’ mode title is optional (the first line of content becomes it), statusId and eta are rejected (400) because raw feedback has no decision yet, and text is read in full up to the limit of its source.channel — 120,000 characters of plain text for ‘call’ (a two-hour transcript), 60,000 for ‘email’ and ‘api’, 30,000 for ‘slack’ and ‘discord’; without a source.channel the ‘api’ limit applies — while anything longer is rejected (400) rather than trimmed. Long text takes tens of minutes rather than seconds to process, and one submission yields at most 30 requests.

One of the following:
"request"
"feedback"
integrations: optional object { clickup, discord, github, 3 more }

Push the created post to third-party integrations configured on your organization. Each integration must be explicitly set to true to trigger; omitted integrations will not be pushed to.

clickup: optional boolean

Push to ClickUp

discord: optional boolean

Push to Discord

github: optional boolean

Push to GitHub

jira: optional boolean

Push to Jira

linear: optional boolean

Push to Linear

slack: optional boolean

Push to Slack

internal: optional boolean

Create this request on the internal board. Never visible on the portal.

notifyAdmins: optional boolean

Whether to send email notifications to admins when this post is created. When true, admins will receive the same email notifications as when a post is created from the dashboard. Defaults to false (no emails sent).

portalHidden: optional boolean

When true, hides the issue from portal/public surfaces. Omitted or false is visible.

source: optional object { channel, externalId, conversationId, 2 more }

Provenance of this request, and the idempotency key for the create. With source and no author, the post is attributed to a guest named after label (or the channel) so it belongs to the customer who said it, not to the API key.

channel: "slack" or "discord" or "email" or 5 more

Channel the request arrived on. ‘feedback’, ‘widget’ and ‘support’ are reserved for posts authored on the portal, the widget and the inbox, and are rejected with a 400. With intakeMode: 'feedback' the channel also sets how much text is read: ‘call’ 120,000 characters, ‘email’ and ‘api’ 60,000, ‘slack’ and ‘discord’ 30,000.

One of the following:
"slack"
"discord"
"email"
"support"
"widget"
"call"
"api"
"feedback"
externalId: string

Stable id of the message/record in the source system. Sending the same (channel, externalId) twice returns the post created the first time instead of a duplicate (HTTP 200 with deduped: true). Stored namespaced as api:<externalId>.

minLength1
maxLength255
conversationId: optional string

Id of the support conversation this request came from

minLength1
maxLength64
label: optional string

Display name of the specific source. Also names the guest author when no author is given.

maxLength255
url: optional string

Deep link back to the original message/record

statusId: optional string

Status ID to set

tags: optional string or array of string

Tag names to attach

One of the following:
string
array of string
title: optional string

Post title. Required unless intakeMode is ‘feedback’, where raw customer text rarely has one: omit it (or send it blank) and the first line of content becomes the title, cut to 120 characters.

minLength2
maxLength512
upvotes: optional number

Initial upvotes count. Defaults to 1 (post author is automatically added as voter). Use 0 to create a post without any votes.

minimum0
visibility: optional "public" or "authorOnly" or "companyOnly"

Post visibility. ‘public’ = visible to all users, ‘authorOnly’ = only visible to the author and admins, ‘companyOnly’ = only visible to users in the same company as the author

One of the following:
"public"
"authorOnly"
"companyOnly"
ReturnsExpand Collapse
Post object { id, access, anchor, 30 more }
id: string

Unique identifier

access: PostAccess { companyExternalIds, userIds }
companyExternalIds: array of string

External company IDs explicitly granted access to this post. Empty array means no company-level restrictions. Non-empty means only users belonging to these companies can see the post.

userIds: array of string

User IDs explicitly granted access to this post. Empty array means no user-level restrictions (post uses board/org visibility). Non-empty means only these users (plus admins) can see the post.

anchor: object { commentId, conversationId, messageId, 3 more }

When kind is ‘insight’, where exactly the insight points back into its origin: an insight source record with character ranges into its fullText, or the native conversation/message/comment/post ids.

commentId: optional string
conversationId: optional string
messageId: optional string
ranges: optional array of object { end, start }
end: number
start: number
sourceRecordId: optional string
submissionId: optional string
assigneeId: string

ID of the admin assigned to this post, null if unassigned

author: PostAuthor { id, email, name, 2 more }
id: string

Author unique identifier

email: string

Author email (if available)

name: string

Author display name

profilePicture: string

Author profile picture URL

type: "admin" or "customer" or "guest" or 3 more

Type of user who authored the post

One of the following:
"admin"
"customer"
"guest"
"integration"
"bot"
"lead"
boardId: string

Board (category) ID this post belongs to

commentCount: number

Total number of comments

content: string

Post content in HTML format

createdAt: string

ISO 8601 timestamp when created

customFields: map[unknown]

Custom field values keyed by field ID

eta: string

Estimated completion time as ISO 8601 timestamp, null if not set

features: PostFeatures { commentsEnabled }
commentsEnabled: boolean

Whether comments are allowed on this post

groupKey: string

When kind is ‘insight’, the triage grouping key (source record id, conversation id, origin post id, or the insight’s own id for singletons). Legacy insights may be null and group as singletons.

inReview: boolean

Whether the post is pending moderation review

insightSource: object { channel, capturedBy, conversationId, 3 more }

Provenance of an insight: which channel it came from and how it was captured.

channel: "slack" or "discord" or "email" or 5 more
One of the following:
"slack"
"discord"
"email"
"support"
"widget"
"call"
"api"
"feedback"
capturedBy: optional "manual" or "auto" or "ai" or "api"
One of the following:
"manual"
"auto"
"ai"
"api"
conversationId: optional string
externalId: optional string
sourceLabel: optional string
url: optional string
integrations: object { clickup, devops, github, 4 more }

Third-party integration links associated with this post

clickup: array of object { id, title, url }
id: string

ClickUp task ID

title: string

ClickUp task title

url: string

URL to the ClickUp task

devops: array of object { id, projectId, projectName, 2 more }
id: number

Azure DevOps work item ID

projectId: string

Azure DevOps project ID

projectName: string

Azure DevOps project name

title: string

Work item title

url: string

URL to the work item

github: array of object { id, number, repositoryFullName, 3 more }
id: string

GitHub issue ID

number: string

GitHub issue number

repositoryFullName: string

Full repository name (owner/repo)

repositoryName: string

Repository name

title: string

GitHub issue title

url: string

URL to the GitHub issue

hubspot: array of object { dealAmount, dealClosed, objectId, type }
dealAmount: number

Deal amount (for DEAL type)

dealClosed: boolean

Whether the deal is closed (for DEAL type)

objectId: number

HubSpot object ID

type: "TICKET" or "DEAL" or "CONTACT"

HubSpot object type

One of the following:
"TICKET"
"DEAL"
"CONTACT"
jira: array of object { issueId, issueUrl }
issueId: string

Jira issue ID

issueUrl: string

URL to the Jira issue

linear: array of object { issueId, issueUrl }
issueId: string

Linear issue ID

issueUrl: string

URL to the Linear issue

salesforce: array of object { amount, isClosed, objectId, objectType }
amount: number

Opportunity amount (for Opportunity type)

isClosed: boolean

Whether the opportunity is closed (for Opportunity type)

objectId: string

Salesforce record ID

objectType: "Opportunity" or "Case"

Salesforce object type

One of the following:
"Opportunity"
"Case"
isPinned: boolean

Whether the post is pinned to the top

kind: "issue" or "insight" or "record"

Discriminates an actionable work item (‘issue’) from a customer submission whose claims were extracted into insights (‘record’ — not a work item). Defaults to ‘issue’ for all pre-existing posts. Default list responses return issues only; pass kind=‘record’ to opt in. Raw signal (‘insight’) is never returned by the posts resource — insights are served by /v2/insights.

One of the following:
"issue"
"insight"
"record"
linkedInsightCount: number

Number of insights linked to this issue as supporting evidence. Only meaningful when kind is ‘issue’.

linkedIssueId: string

When kind is ‘insight’, the ID of the issue this insight supports. Null when the insight is unlinked or when kind is ‘issue’.

object: "post"

Object type identifier

opportunityAmount: number

Total opportunity amount from linked HubSpot deals and Salesforce opportunities

portalHidden: boolean

True when the issue is hidden from portal/public surfaces. Missing stored values are returned as false.

postUrl: string

Full URL to view the post

slug: string

URL-friendly slug

status: PostStatus { id, color, isDefault, 3 more }
id: string

Unique identifier

color: string

Color for UI display

isDefault: boolean

Whether this is the default status for new posts

name: string

Display name

object: "post_status"

Object type identifier

type: "reviewing" or "unstarted" or "active" or 2 more

The workflow stage this status represents

One of the following:
"reviewing"
"unstarted"
"active"
"completed"
"canceled"
tags: array of PostTag { id, color, name }

Tags attached to this post

id: string

Tag unique identifier

color: string

Tag color hex code

name: string

Tag name

title: string

Post title

updatedAt: string

ISO 8601 timestamp when last modified

upvotes: number

Total number of upvotes

deduped: optional true

Present and true only on POST /v2/posts, when the request carried a source.externalId that already had a post. The existing post is returned unchanged with HTTP 200; a newly created post returns HTTP 201 without this field.

intakeMode: optional "request" or "feedback"

Present only on POST /v2/posts: the intakeMode the post was processed under (‘request’ when the request named none). On an idempotent replay (deduped: true) this is the mode the post was ORIGINALLY created with.

One of the following:
"request"
"feedback"
processing: optional PostProcessing { status, reason, results }

On POST /v2/posts — queued: a processing run (claim extraction or the Organize rewrite) was enqueued and its result lands asynchronously on the post. skipped: nothing was enqueued; reason says which gate decided (‘request_mode’ for every intakeMode: ‘request’ create). existing: the create was an idempotent replay and the post was not processed again. On GET /v2/posts/{id} this field is present only for posts created with intakeMode: 'feedback' and reports how far that processing has got (‘queued’, ‘processing’, ‘complete’, ‘needs_review’, or ‘skipped’ with the same reason the create returned), with results listing what was made of the submission once the run has finished.

status: "queued" or "processing" or "complete" or 3 more

‘queued’ = an AI run was enqueued and has not landed yet; ‘processing’ = the run is working on the submission; ‘complete’ = it finished and results lists what it produced; ‘needs_review’ = it finished and a teammate still has to decide something; ‘skipped’ = nothing was enqueued (see reason); ‘existing’ = idempotent replay, not processed again.

One of the following:
"queued"
"processing"
"complete"
"needs_review"
"skipped"
"existing"
reason: optional "request_mode" or "autopilot_off" or "insights_disabled" or 11 more

Why processing was skipped. ‘request_mode’ = intakeMode was ‘request’ (the default); ‘autopilot_off’ = the workspace’s Autopilot dial is off or its plan does not include it; ‘pipeline_paused’ = the platform paused AI processing (it resumes automatically); ‘support_board’ / ‘spam_held’ / ‘staff_authored’ / ‘no_content’ = the post did not qualify; ‘source_too_long’ = the text was over the length limit when the run read it (a create that long is normally refused with a 400 first); ‘extraction_failed’ = the AI could not read the text after repeated attempts; nothing was written, and opening the post in Triage runs the analysis again.

One of the following:
"request_mode"
"autopilot_off"
"insights_disabled"
"pipeline_paused"
"support_board"
"spam_held"
"staff_authored"
"not_a_post"
"no_board"
"no_id"
"no_content"
"source_too_long"
"extraction_failed"
"hook_error"
results: optional array of object { outcome, title, postId, 2 more }

What the workspace’s “Organize submissions” lane made of this submission, one entry per ask it found, in the order they appear in the text. Present on GET /v2/posts/{id} for posts created with intakeMode: 'feedback' once the run has finished. Absent while the run is still working, and absent for workspaces that do not organize submissions — there the post itself is the request.

outcome: "attached" or "request" or "question" or "held"

‘request’ = the ask became a request of its own; ‘attached’ = it was added as evidence to a request that already existed; ‘held’ = it became a request that is waiting for a teammate to publish it; ‘question’ = it asked something and no request was created, so a teammate answers it.

One of the following:
"attached"
"request"
"question"
"held"
title: string

The ask, as it was written up.

postId: optional string

The request this ask became, or was attached to. Absent for a question, and absent when the request is not readable through this API (for example a ticket board).

postTitle: optional string

Title of postId.

reason: optional "too_many_topics" or "uncertain" or "custom_fields" or "processing_failed"

Why a ‘held’ result is waiting for a teammate. Only on a ‘held’ result, and only one of these codes: ‘too_many_topics’ = the submission held more separate asks than one submission can become requests, so this one request lists the asks that did not fit, one line each in the customer’s words; ‘uncertain’ = the ask was too vague to file without a person; ‘custom_fields’ = the board requires custom fields this submission did not carry; ‘processing_failed’ = the AI could not rewrite the text (the request then holds the original words) or could not check this ask against existing requests, so a teammate confirms it is not a duplicate.

One of the following:
"too_many_topics"
"uncertain"
"custom_fields"
"processing_failed"

Create a new post

curl https://do.featurebase.app/v2/posts \
    -H 'Content-Type: application/json' \
    -H "Authorization: Bearer $FEATUREBASE_API_KEY" \
    -d '{
          "assigneeId": "507f1f77bcf86cd799439013",
          "attachTo": "507f1f77bcf86cd799439014",
          "boardId": "507f1f77bcf86cd799439011",
          "commentsEnabled": true,
          "content": "<p>It would be great to have dark mode.</p>",
          "createdAt": "2025-01-15T10:30:00.000Z",
          "customFields": {
            "507f1f77bcf86cd799439011": "high"
          },
          "eta": "2025-12-31T23:59:59.000Z",
          "intakeMode": "feedback",
          "internal": true,
          "notifyAdmins": true,
          "portalHidden": true,
          "statusId": "507f1f77bcf86cd799439012",
          "tags": [
            "feature",
            "ui"
          ],
          "title": "Add dark mode support",
          "upvotes": 5,
          "visibility": "public"
        }'
{
  "id": "507f1f77bcf86cd799439011",
  "access": {
    "companyExternalIds": [
      "string"
    ],
    "userIds": [
      "string"
    ]
  },
  "anchor": {
    "commentId": "commentId",
    "conversationId": "conversationId",
    "messageId": "messageId",
    "ranges": [
      {
        "end": 0,
        "start": 0
      }
    ],
    "sourceRecordId": "sourceRecordId",
    "submissionId": "submissionId"
  },
  "assigneeId": "507f1f77bcf86cd799439013",
  "author": {
    "id": "507f1f77bcf86cd799439011",
    "email": "john@example.com",
    "name": "John Doe",
    "profilePicture": "https://cdn.example.com/avatars/john.png",
    "type": "customer"
  },
  "boardId": "507f1f77bcf86cd799439011",
  "commentCount": 5,
  "content": "<p>It would be great to have a dark mode option for the dashboard.</p>",
  "createdAt": "2023-12-12T00:00:00.000Z",
  "customFields": {
    "cf_priority": "bar",
    "cf_effort": "bar"
  },
  "eta": "2025-01-01T00:00:00.000Z",
  "features": {
    "commentsEnabled": true
  },
  "groupKey": null,
  "inReview": false,
  "insightSource": {
    "channel": "slack",
    "capturedBy": "manual",
    "conversationId": "conversationId",
    "externalId": "externalId",
    "sourceLabel": "sourceLabel",
    "url": "url"
  },
  "integrations": {
    "clickup": [
      {
        "id": "86a1b2c3d",
        "title": "Add dark mode support",
        "url": "https://app.clickup.com/t/86a1b2c3d"
      }
    ],
    "devops": [
      {
        "id": 1234,
        "projectId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "projectName": "My Project",
        "title": "Add dark mode support",
        "url": "https://dev.azure.com/org/project/_workitems/edit/1234"
      }
    ],
    "github": [
      {
        "id": "1234567890",
        "number": "42",
        "repositoryFullName": "acme/backend",
        "repositoryName": "backend",
        "title": "Add dark mode support",
        "url": "https://github.com/acme/backend/issues/42"
      }
    ],
    "hubspot": [
      {
        "dealAmount": 5000,
        "dealClosed": false,
        "objectId": 123456789,
        "type": "TICKET"
      }
    ],
    "jira": [
      {
        "issueId": "10042",
        "issueUrl": "https://myteam.atlassian.net/browse/PROJ-123"
      }
    ],
    "linear": [
      {
        "issueId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "issueUrl": "https://linear.app/team/issue/ENG-123"
      }
    ],
    "salesforce": [
      {
        "amount": 25000,
        "isClosed": false,
        "objectId": "006Dn00000Abcdef",
        "objectType": "Opportunity"
      }
    ]
  },
  "isPinned": false,
  "kind": "issue",
  "linkedInsightCount": 0,
  "linkedIssueId": null,
  "object": "post",
  "opportunityAmount": 30000,
  "portalHidden": false,
  "postUrl": "https://feedback.example.com/p/add-dark-mode-support",
  "slug": "add-dark-mode-support",
  "status": {
    "id": "507f1f77bcf86cd799439011",
    "color": "Blue",
    "isDefault": false,
    "name": "In Progress",
    "object": "post_status",
    "type": "active"
  },
  "tags": [
    {
      "id": "507f1f77bcf86cd799439011",
      "color": "#FF5722",
      "name": "bug"
    }
  ],
  "title": "Add dark mode support",
  "updatedAt": "2023-12-13T00:00:00.000Z",
  "upvotes": 42,
  "deduped": true,
  "intakeMode": "request",
  "processing": {
    "status": "queued",
    "reason": "request_mode",
    "results": [
      {
        "outcome": "request",
        "title": "Export the board to CSV",
        "postId": "507f1f77bcf86cd799439011",
        "postTitle": "CSV export",
        "reason": "too_many_topics"
      }
    ]
  }
}
Returns Examples
{
  "id": "507f1f77bcf86cd799439011",
  "access": {
    "companyExternalIds": [
      "string"
    ],
    "userIds": [
      "string"
    ]
  },
  "anchor": {
    "commentId": "commentId",
    "conversationId": "conversationId",
    "messageId": "messageId",
    "ranges": [
      {
        "end": 0,
        "start": 0
      }
    ],
    "sourceRecordId": "sourceRecordId",
    "submissionId": "submissionId"
  },
  "assigneeId": "507f1f77bcf86cd799439013",
  "author": {
    "id": "507f1f77bcf86cd799439011",
    "email": "john@example.com",
    "name": "John Doe",
    "profilePicture": "https://cdn.example.com/avatars/john.png",
    "type": "customer"
  },
  "boardId": "507f1f77bcf86cd799439011",
  "commentCount": 5,
  "content": "<p>It would be great to have a dark mode option for the dashboard.</p>",
  "createdAt": "2023-12-12T00:00:00.000Z",
  "customFields": {
    "cf_priority": "bar",
    "cf_effort": "bar"
  },
  "eta": "2025-01-01T00:00:00.000Z",
  "features": {
    "commentsEnabled": true
  },
  "groupKey": null,
  "inReview": false,
  "insightSource": {
    "channel": "slack",
    "capturedBy": "manual",
    "conversationId": "conversationId",
    "externalId": "externalId",
    "sourceLabel": "sourceLabel",
    "url": "url"
  },
  "integrations": {
    "clickup": [
      {
        "id": "86a1b2c3d",
        "title": "Add dark mode support",
        "url": "https://app.clickup.com/t/86a1b2c3d"
      }
    ],
    "devops": [
      {
        "id": 1234,
        "projectId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "projectName": "My Project",
        "title": "Add dark mode support",
        "url": "https://dev.azure.com/org/project/_workitems/edit/1234"
      }
    ],
    "github": [
      {
        "id": "1234567890",
        "number": "42",
        "repositoryFullName": "acme/backend",
        "repositoryName": "backend",
        "title": "Add dark mode support",
        "url": "https://github.com/acme/backend/issues/42"
      }
    ],
    "hubspot": [
      {
        "dealAmount": 5000,
        "dealClosed": false,
        "objectId": 123456789,
        "type": "TICKET"
      }
    ],
    "jira": [
      {
        "issueId": "10042",
        "issueUrl": "https://myteam.atlassian.net/browse/PROJ-123"
      }
    ],
    "linear": [
      {
        "issueId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "issueUrl": "https://linear.app/team/issue/ENG-123"
      }
    ],
    "salesforce": [
      {
        "amount": 25000,
        "isClosed": false,
        "objectId": "006Dn00000Abcdef",
        "objectType": "Opportunity"
      }
    ]
  },
  "isPinned": false,
  "kind": "issue",
  "linkedInsightCount": 0,
  "linkedIssueId": null,
  "object": "post",
  "opportunityAmount": 30000,
  "portalHidden": false,
  "postUrl": "https://feedback.example.com/p/add-dark-mode-support",
  "slug": "add-dark-mode-support",
  "status": {
    "id": "507f1f77bcf86cd799439011",
    "color": "Blue",
    "isDefault": false,
    "name": "In Progress",
    "object": "post_status",
    "type": "active"
  },
  "tags": [
    {
      "id": "507f1f77bcf86cd799439011",
      "color": "#FF5722",
      "name": "bug"
    }
  ],
  "title": "Add dark mode support",
  "updatedAt": "2023-12-13T00:00:00.000Z",
  "upvotes": 42,
  "deduped": true,
  "intakeMode": "request",
  "processing": {
    "status": "queued",
    "reason": "request_mode",
    "results": [
      {
        "outcome": "request",
        "title": "Export the board to CSV",
        "postId": "507f1f77bcf86cd799439011",
        "postTitle": "CSV export",
        "reason": "too_many_topics"
      }
    ]
  }
}