# Table of Contents
- [Featurebase API Reference](#featurebase-api-reference)
- [Authentication - Featurebase API Reference](#authentication-featurebase-api-reference)
- [Pagination - Featurebase API Reference](#pagination-featurebase-api-reference)
- [Quickstart - Featurebase API Reference](#quickstart-featurebase-api-reference)
- [Errors - Featurebase API Reference](#errors-featurebase-api-reference)
- [Webhooks - Featurebase API Reference](#webhooks-featurebase-api-reference)
- [Posts - Featurebase API Reference](#posts-featurebase-api-reference)
- [Comments - Featurebase API Reference](#comments-featurebase-api-reference)
- [Changelogs - Featurebase API Reference](#changelogs-featurebase-api-reference)
- [Roles - Featurebase API Reference](#roles-featurebase-api-reference)
- [Identify Users - Featurebase API Reference](#identify-users-featurebase-api-reference)
- [Help Centers - Featurebase API Reference](#help-centers-featurebase-api-reference)
- [404: This page could not be found](#404-this-page-could-not-be-found)
---
# Featurebase API Reference
API Documentation
=================
Use the Featurebase API to access posts, changelogs, comments, and more and seamlessly integrate Featurebase into your product.
[Quickstart](/quickstart)
[Guides](/#guides)
-------------------
### Authentication
Learn how to authenticate your API requests.
[Read more](/authentication)
### Pagination
Understand how to work with paginated responses.
[Read more](/pagination)
### Errors
Read about the different types of errors returned by the API.
[Read more](/errors)
[Resources](/#resources)
-------------------------
### [Posts](/posts)
Learn about the posts model and how to create, retrieve, update, delete, and list posts.
### [Changelogs](/changelogs)
Learn about the changelog model and how to create, retrieve, update, delete, and list changelogs.
### [Roles](/roles)
Learn about the roles model and how to create, retrieve, update, delete, and list roles.
### [Comments](/comments)
Learn about the comments model and how to create, retrieve, update, delete, and list comments.
---
# Authentication - Featurebase API Reference
Authentication
==============
In this guide, we’ll look at how authentication works. Featurebase let's you authenticate using a special header containing the API Key.
[API Key authentication](/authentication#api-key-authentication)
-----------------------------------------------------------------
With API Key authentication, you send along an "X-API-Key" header with every request you make.
### Example request with api key
curl https://do.featurebase.app/v2/posts \
-H "X-API-Key: {api_key}"
CopyCopied!
Please don't commit your Featurebase API Key to GitHub!
---
# Pagination - Featurebase API Reference
Pagination
==========
In this guide, we will look at how to work with paginated responses when querying the Featurebase API. By default, all responses limit results to ten. However, you can go as high as 100 by adding a `limit` parameter to your requests.
When an API response returns a list of objects, no matter the amount, pagination is supported. In paginated responses, objects are nested in a `results` attribute. You can use the `page` query parameters to browse pages. You will also get access to `totalPages` and `totalResults`, which you can use to build pagination controls in your application.
[Example using pages](/pagination#example-using-pages)
-------------------------------------------------------
In this example, we request the second page of posts.
* Name
`page`
Type
string
Description
The page to return.
* Name
`limit`
Type
integer
Description
Limit the number of items returned.
### Manual pagination using cURL
curl -G https://do.featurebase.app/v2/posts \
-H "X-API-Key: {token}" \
-d page=2 \
-d limit=10
CopyCopied!
### Paginated response
{
"results": [\
{\
"title": "Weekly email to users.",\
...\
{\
...\
},\
...\
],
"page": 2,
"limit": 10,
"totalPages": 18,
"totalResults": 179
}
CopyCopied!
---
# Quickstart - Featurebase API Reference
Quickstart
==========
This guide will get you all set up and ready to use the Featurebase API. We’ll cover how to find your API key and how to make your first API request. We'll also look at where to go next to find all the information you need to take full advantage of our powerful REST API.
Before you can make requests to the Featurebase API, you will need to grab your API key from your dashboard. You find it under [Settings » Integrations » API](https://auth.featurebase.app/choose-org?redirect=/settings/integrations)
.
[Making your first API request](/quickstart#making-your-first-api-request)
---------------------------------------------------------------------------
After picking your preferred client, you are ready to make your first call to the Featurebase API. Below, you can see how to send a GET request to the Posts endpoint to get a list of all your posts. In the cURL example, results are limited to ten conversations, the default page length for each client.
cURLNode.jsPython
GET
/v2/posts
curl -G https://do.featurebase.app/v2/posts \
-H "X-API-Key: {token}"
CopyCopied!
[Read the docs for the Posts endpoint](/posts)
[What's next?](/quickstart#whats-next)
---------------------------------------
Great, you're now set up with an API client and have made your first request to the API. Here are a few links that might be handy as you venture further into the Featurebase API:
* [Grab your API key from the Featurebase dashboard](/quickstart#)
* [Check out the Posts endpoint](/posts)
* [Learn about the different error messages in Featurebase](/errors)
---
# Errors - Featurebase API Reference
Errors
======
In this guide, we will talk about what happens when something goes wrong while you work with the API. Mistakes happen, and mostly they will be yours, not ours. Let's look at some status codes and error types you might encounter.
You can tell if your request was successful by checking the status code when receiving an API response. If a response comes back unsuccessful, you can use the error type and error message to figure out what has gone wrong and do some rudimentary debugging (before contacting support).
Before reaching out to support with an error, please be aware that 99% of all reported errors are, in fact, user errors. Therefore, please carefully check your code before contacting Featurebase support.
* * *
[Status codes](/errors#status-codes)
-------------------------------------
Here is a list of the different categories of status codes returned by the Featurebase API. Use these to understand if a request was successful.
* Name
`2xx`
Type
Description
A 2xx status code indicates a successful response.
* Name
`4xx`
Type
Description
A 4xx status code indicates a client error — this means it's a _you_ problem.
* Name
`5xx`
Type
Description
A 5xx status code indicates a server error — you won't be seeing these.
* * *
### Error response
{
"success": false,
"error": "Something went wrong with X!?",
}
CopyCopied!
---
# Webhooks - Featurebase API Reference
Webhooks
========
When using Featurebase, you might want your applications to react instantly as users interact with your portal. With webhooks, your backend systems can receive and act on real-time updates such as new feedback posts.
Featurebase sends event data to your application's webhook endpoint as a JSON payload, using secure HTTPS. This data contains all the essential event details so you can act on it instantly.
[Registering webhooks](/webhooks#registering-webhooks)
-------------------------------------------------------
To register a new webhook, you need to have a URL in your app that Featurebase can call. You can configure a new webhook from the Featurebase Dashboard -> Settings -> [Webhooks](https://auth.featurebase.app/choose-org?redirect=/settings/webhooks)
. Give your webhook a name, pick the [topics](/webhooks#topic-types)
you want to listen for, and add your URL.
Your webhook endpoint must be a publicly accessible HTTPS URL in this format:
https://{your-website}/{your-webhook-endpoint}
CopyCopied!
For example, if your domain is `https://yourawesomesite.com` and your webhook endpoint route is `/featurebase_webhooks`, you would register:
https://yourawesomesite.com/featurebase_webhooks
CopyCopied!
You can register up to 10 webhook endpoints per organization. All endpoints must use HTTPS for security.
Now, whenever something of interest happens, a webhook is fired off by Featurebase. In the next section, we'll look at how to consume webhooks.
[Consuming webhooks](/webhooks#consuming-webhooks)
---------------------------------------------------
When your app receives a webhook request from Featurebase, check the `topic` attribute to see what event caused it. The first part of the event type will tell you the payload type, e.g., a post, comment, etc.
### Example webhook payload
{
"id": "notif_0193a6e6-fb6b-78ef-b71f-15008d9f9cde",
"topic": "post.updated",
"data": {
"type": "notification_event_data",
"item": {
"id": "6755c4afb12a37dffa6319b0",
"title": "My new title",
// ...
},
"changes": [\
{\
"field": "title",\
"oldValue": "My old title",\
"newValue": "My new title"\
}\
]
}
// ...
}
CopyCopied!
In the example above, a post was `updated`, and the payload type is a `notification_event_data`. Notice how the `changes` array contains the old and new values for the changed fields.
[See all topic types](/webhooks#topic-types)
* * *
[Topic types](/webhooks#topic-types)
-------------------------------------
* Name
`post.created`
Type
Description
A new post was created.
* Name
`post.updated`
Type
Description
An existing post was updated.
* Name
`post.deleted`
Type
Description
A post was successfully deleted.
* Name
`post.voted`
Type
Description
A post received a vote.
* Name
`changelog.published`
Type
Description
A new changelog entry was published.
* Name
`comment.created`
Type
Description
A new comment was created.
* Name
`comment.updated`
Type
Description
An existing comment was updated.
* Name
`comment.deleted`
Type
Description
A comment was successfully deleted.
### Example payload
{
"type": "notification_event",
"topic": "post.updated",
"organizationId": "6595518396205e06b897ad65",
"data": {
"type": "notification_event_data",
"item": {
"id": "67546dfb6e1363426b90707f",
"type": "post",
"title": "New title",
"content": "
New content
",
// ...
},
"changes": [\
{\
"field": "title",\
"oldValue": "Old title",\
"newValue": "New title"\
},\
{\
"field": "content", \
"oldValue": "Old content
",\
"newValue": "New content
"\
}\
]
},
"id": "notif_0193a70c-3015-757c-a260-22ae37c86608",
"webhookId": "675346db13af7340748ce850",
"createdAt": "2024-12-08T16:13:34.102Z",
"deliveryStatus": "pending"
}
CopyCopied!
[Topic Examples](/webhooks#topic-examples)
-------------------------------------------
Here's a detailed look at the payload structure for each webhook topic.
### Post Events
### post.created
{
"type": "notification_event",
"topic": "post.created",
"organizationId": "6595518396205e06b897ad65",
"data": {
"type": "notification_event_data",
"item": {
"id": "6755d2162acedc23e26dd3d1",
"type": "post",
"title": "Hello, world!",
"content": "This is a test post.
",
"user": {
"id": "5fef50c5e9458a0012f82456",
"email": "admin@example.com",
"name": "Admin",
"profilePicture": "https://example.com/profile.jpg",
"verified": true,
"type": "admin",
"description": ""
},
"postStatus": {
"name": "In Review",
"color": "Sky",
"type": "reviewing",
"isDefault": true,
"id": "6595518396205e06b897ad6a"
},
"postCategory": {
"category": "Feature Request",
"private": false,
"segmentIds": [],
"roles": [],
"customInputFields": [],
"icon": {
"type": "predefined",
"value": "LightBulbIcon"
},
"id": "6755d0970b5d5b1fefdf54f4"
}
"date": "2024-12-08T17:06:30.577Z",
"slug": "hello-world-29",
"upvotes": 1,
"inReview": false,
"accessUsers": [],
"accessCompanies": [],
"clickupTasks": [],
"githubIssues": [],
"commentsAllowed": true,
"categoryId": "6755d0970b5d5b1fefdf54f4",
"lastModified": "2024-12-08T17:06:30.577Z",
"lastUpvoted": "2024-12-08T17:06:30.574Z",
"commentCount": 0,
"postTags": [],
"pinned": false,
"devopsWorkItems": []
}
},
"id": "notif_0193a73c-a97f-76b8-b855-2b85c7cec70a",
"webhookId": "675346db13af7340748ce850",
"createdAt": "2024-12-08T17:06:30.911Z",
"deliveryStatus": "failure",
"firstSentAt": "2024-12-08T17:06:31.162Z",
"deliveryAttempts": 1
}
CopyCopied!
### post.updated
{
"type": "notification_event",
"topic": "post.updated",
"organizationId": "6595518396205e06b897ad65",
"data": {
"type": "notification_event_data",
"item": {
"id": "6755d2162acedc23e26dd3d1",
"type": "post",
"title": "New title",
"content": "New content
",
"user": {
"id": "5fef50c5e9458a0012f82456",
"email": "admin@example.com",
"name": "Admin",
"profilePicture": "https://example.com/profile.jpg",
"verified": true,
"type": "admin",
"description": ""
},
"postStatus": {
"name": "Completed",
"color": "Green",
"type": "completed",
"isDefault": false,
"id": "6595518396205e06b897ad6d"
},
"postCategory": {
"category": "Feature Request",
"private": false,
"segmentIds": [],
"roles": [],
"customInputFields": [],
"icon": {
"type": "predefined",
"value": "LightBulbIcon"
},
"id": "6755d0970b5d5b1fefdf54f4"
}
"date": "2024-12-08T17:06:30.577Z",
"slug": "hello-world-29",
"upvotes": 1,
"inReview": false,
"accessUsers": [],
"accessCompanies": [],
"clickupTasks": [],
"githubIssues": [],
"commentsAllowed": true,
"categoryId": "6755d0970b5d5b1fefdf54f4",
"lastModified": "2024-12-08T17:06:30.577Z",
"lastUpvoted": "2024-12-08T17:06:30.574Z",
"commentCount": 0,
"postTags": [],
"pinned": false,
"devopsWorkItems": []
},
"changes": [\
{\
"field": "postStatus.name",\
"oldValue": "In Review",\
"newValue": "Completed"\
},\
{\
"field": "postStatus.color",\
"oldValue": "Sky",\
"newValue": "Green"\
},\
{\
"field": "postStatus.type",\
"oldValue": "reviewing",\
"newValue": "completed"\
},\
{\
"field": "postStatus.isDefault",\
"oldValue": true,\
"newValue": false\
},\
{\
"field": "postStatus.id",\
"oldValue": "6595518396205e06b897ad6a",\
"newValue": "6595518396205e06b897ad6d"\
},\
{\
"field": "content",\
"oldValue": "Old content
",\
"newValue": "New content
"\
},\
{\
"field": "title",\
"oldValue": "Old title",\
"newValue": "New title"\
}\
]
},
"id": "notif_0193a73c-a97f-76b8-b855-2b85c7cec70a",
"webhookId": "675346db13af7340748ce850",
"createdAt": "2024-12-08T17:06:30.911Z",
"deliveryStatus": "pending",
"firstSentAt": "2024-12-08T17:06:31.162Z",
"deliveryAttempts": 1
}
CopyCopied!
### post.deleted
{
"type": "notification_event",
"topic": "post.deleted",
"organizationId": "6595518396205e06b897ad65",
"data": {
"type": "notification_event_data",
"item": {
"id": "6755d2162acedc23e26dd3d1",
"type": "post",
"title": "Hello, world!",
"content": "This is a test post.
",
"user": {
"id": "5fef50c5e9458a0012f82456",
"email": "admin@example.com",
"name": "Admin",
"profilePicture": "https://example.com/profile.jpg",
"verified": true,
"type": "admin",
"description": ""
},
"postStatus": {
"name": "In Review",
"color": "Sky",
"type": "reviewing",
"isDefault": true,
"id": "6595518396205e06b897ad6a"
},
"postCategory": {
"category": "Feature Request",
"private": false,
"segmentIds": [],
"roles": [],
"customInputFields": [],
"icon": {
"type": "predefined",
"value": "LightBulbIcon"
},
"id": "6755d0970b5d5b1fefdf54f4"
}
"date": "2024-12-08T17:06:30.577Z",
"slug": "hello-world-29",
"upvotes": 1,
"inReview": false,
"accessUsers": [],
"accessCompanies": [],
"clickupTasks": [],
"githubIssues": [],
"commentsAllowed": true,
"categoryId": "6755d0970b5d5b1fefdf54f4",
"lastModified": "2024-12-08T17:06:30.577Z",
"lastUpvoted": "2024-12-08T17:06:30.574Z",
"commentCount": 0,
"postTags": [],
"pinned": false,
"devopsWorkItems": []
}
},
"id": "notif_0193a73c-a97f-76b8-b855-2b85c7cec70a",
"webhookId": "675346db13af7340748ce850",
"createdAt": "2024-12-08T17:06:30.911Z",
"deliveryStatus": "failure",
"firstSentAt": "2024-12-08T17:06:31.162Z",
"deliveryAttempts": 1
}
CopyCopied!
### post.voted
{
"type": "notification_event",
"topic": "post.voted",
"organizationId": "6595518396205e06b897ad65",
"data": {
"type": "notification_event_data",
"item": {
"type": "post_vote",
"action": "add", // or "remove"
"submissionId": "6755d2162acedc23e26dd3d1",
"user": {
"id": "5fef50c5e9458a0012f82456",
"email": "admin@example.com",
"name": "Admin",
"profilePicture": "https://example.com/profile.jpg",
"verified": true,
"type": "admin",
"description": ""
}
}
},
"id": "notif_0193a741-a81a-7716-80e3-3236608244ec",
"webhookId": "675346db13af7340748ce850",
"createdAt": "2024-12-08T17:11:58.234Z",
"deliveryStatus": "pending"
}
CopyCopied!
### Changelog Events
### changelog.published
{
"type": "notification_event",
"topic": "changelog.published",
"organizationId": "6595518396205e06b897ad65",
"data": {
"type": "notification_event_data",
"item": {
"id": "6755d4e73ba80aa1cd90bae8",
"type": "changelog",
"title": "[EN] Hello World!",
"content": "This is a test changelog.
",
"markdownContent": "This is a test changelog.",
"featuredImage": "https://fb-usercontent.fra1.cdn.digitaloceanspaces.com/0193a748-9c36-7976-a414-672869c3e160.png",
"date": "2024-12-08T17:18:31.396Z",
"state": "live",
"locale": "en",
"slug": "en-hello-world-2",
"firstPublishInLocale": true, // If this is the first publish in this locale
"changelogCategories": [\
{\
"name": "New",\
"color": "Green",\
"segmentIds": [],\
"roles": [],\
"id": "6595518396205e06b897ad6f"\
},\
{\
"name": "Improved",\
"color": "Sky",\
"segmentIds": [],\
"roles": [],\
"id": "6595518396205e06b897ad70"\
}\
],
"commentCount": 0,
"notifications": {
"en": {
"sendEmailNotification": false,
"hideFromBoardAndWidgets": false,
"scheduledDate": null
},
"de": {
"hideFromBoardAndWidgets": false,
"sendEmailNotification": true,
"scheduledDate": null
}
},
"allowedSegmentIds": [],
"isDraftDiffersFromLive": false,
"isPublished": true,
"availableLocales": [\
"en",\
"de"\
],
"publishedLocales": [\
"en",\
"de"\
],
"slugs": {
"en": "en-hello-world-2",
"de": "de-hallo-welt-2"
},
"organization": "robiorg4"
},
"changes": []
},
"id": "notif_0193a764-e5be-7f0a-90dd-a9cdffc79c43",
"webhookId": "675346db13af7340748ce850",
"createdAt": "2024-12-08T17:50:27.774Z",
"deliveryStatus": "failure",
"firstSentAt": "2024-12-08T17:50:28.023Z",
"deliveryAttempts": 1
}
CopyCopied!
### Comment Events
### comment.created
{
"type": "notification_event",
"topic": "comment.created",
"organizationId": "6595518396205e06b897ad65",
"data": {
"type": "notification_event_data",
"item": {
"type": "comment",
"id": "6755d722fcb2ad2f2e2b16a1",
"content": "Hey! This is a great idea!
",
"user": {
"id": "5fef50c5e9458a0012f82456",
"email": "admin@example.com",
"name": "Admin",
"profilePicture": "https://example.com/profile.jpg",
"verified": true,
"type": "admin",
"description": ""
},
"isPrivate": false,
"score": 1,
"upvotes": 1,
"downvotes": 0,
"inReview": false,
"pinned": false,
"emailSent": false,
"sendNotification": true,
"createdAt": "2024-12-08T17:28:02.468Z",
"updatedAt": "2024-12-08T17:28:02.468Z",
"organization": "6595518396205e06b897ad65",
"submission": "67530bae0c2341f39d2c5847",
"path": "67530bae0c2341f39d2c5847"
}
},
"id": "notif_0193a750-5fc9-7739-8714-758bff6e62c6",
"webhookId": "675346db13af7340748ce850",
"createdAt": "2024-12-08T17:28:02.761Z",
"deliveryStatus": "pending"
}
CopyCopied!
### comment.updated
{
"type": "notification_event",
"topic": "comment.updated",
"organizationId": "6595518396205e06b897ad65",
"data": {
"type": "notification_event_data",
"item": {
"type": "comment",
"id": "6755d722fcb2ad2f2e2b16a1",
"content": "New content
",
"user": {
"id": "5fef50c5e9458a0012f82456",
"email": "admin@example.com",
"name": "Admin",
"profilePicture": "https://example.com/profile.jpg",
"verified": true,
"type": "admin",
"description": ""
},
"isPrivate": false,
"score": 1,
"upvotes": 1,
"downvotes": 0,
"inReview": false,
"pinned": false,
"emailSent": false,
"sendNotification": true,
"createdAt": "2024-12-08T17:28:02.468Z",
"updatedAt": "2024-12-08T17:28:02.468Z",
"organization": "6595518396205e06b897ad65",
"submission": "67530bae0c2341f39d2c5847",
"path": "67530bae0c2341f39d2c5847"
},
"changes": [\
{\
"field": "content",\
"oldValue": "Old content
",\
"newValue": "New content
"\
}\
]
},
"id": "notif_0193a750-5fc9-7739-8714-758bff6e62c6",
"webhookId": "675346db13af7340748ce850",
"createdAt": "2024-12-08T17:28:02.761Z",
"deliveryStatus": "pending"
}
CopyCopied!
### comment.deleted
{
"type": "notification_event",
"topic": "comment.deleted",
"organizationId": "6595518396205e06b897ad65",
"data": {
"type": "notification_event_data",
"item": {
"type": "comment",
"id": "6755d722fcb2ad2f2e2b16a1",
"content": "Hey! This is a great idea!
",
"user": {
"id": "5fef50c5e9458a0012f82456",
"email": "admin@example.com",
"name": "Admin",
"profilePicture": "https://example.com/profile.jpg",
"verified": true,
"type": "admin",
"description": ""
},
"isPrivate": false,
"score": 1,
"upvotes": 1,
"downvotes": 0,
"inReview": false,
"pinned": false,
"emailSent": false,
"sendNotification": true,
"createdAt": "2024-12-08T17:28:02.468Z",
"updatedAt": "2024-12-08T17:28:02.468Z",
"organization": "6595518396205e06b897ad65",
"submission": "67530bae0c2341f39d2c5847",
"path": "67530bae0c2341f39d2c5847"
}
},
"id": "notif_0193a750-5fc9-7739-8714-758bff6e62c6",
"webhookId": "675346db13af7340748ce850",
"createdAt": "2024-12-08T17:28:02.761Z",
"deliveryStatus": "pending"
}
CopyCopied!
Each webhook event includes:
* `type`: Always "notification\_event"
* `topic`: The specific event type
* `organizationId`: Your organization's unique identifier
* `data`: Contains the event details
* `type`: Always "notification\_event\_data"
* `item`: The resource that triggered the event
* `changes`: For update events, shows what changed
* `id`: Unique identifier for the webhook event
* `webhookId`: ID of the webhook configuration
* `createdAt`: Timestamp when the event occurred
* `deliveryStatus`: Current delivery status of the webhook
The `item` object structure varies based on the event type, but always includes the resource's essential data and any relevant timestamps.
* * *
[Example webhook handlers](/webhooks#example-webhook-handlers)
---------------------------------------------------------------
Here are examples of webhook handlers for different languages.
### Webhook Handler Examples
PythonJavaScriptPHPRubyJavaGoC#
from fastapi import FastAPI, Request, HTTPException
import logging
app = FastAPI()
logger = logging.getLogger(__name__)
async def process_webhook_event(event_data: dict) -> None:
"""Process the webhook event asynchronously."""
try:
topic = event_data.get('topic')
match topic:
case 'post.created':
await handle_post_created(event_data)
case 'post.updated':
await handle_post_updated(event_data)
case _:
logger.warning(f"Unhandled webhook topic: {topic}")
except Exception as e:
logger.error(f"Error processing webhook: {str(e)}", exc_info=True)
@app.post("/webhooks/featurebase")
async def handle_webhook(request: Request):
try:
# Return 200 immediately to acknowledge receipt
background_tasks = request.background
# Get the raw payload
payload = await request.json()
# Verify webhook signature (implemented in security section)
# verify_webhook_signature(request)
# Process webhook asynchronously
background_tasks.add_task(process_webhook_event, payload)
return {"status": "accepted"}
except Exception as e:
logger.error(f"Webhook handler error: {str(e)}", exc_info=True)
raise HTTPException(status_code=500, detail="Internal server error")
CopyCopied!
When implementing webhook handlers, you'll want to:
1. Validate the webhook signature immediately (see security section below)
2. Return a quick 200 OK response to acknowledge receipt
3. Move the actual processing to a background task/job
4. Handle different event types based on the webhook topic
5. Add error handling and logging for debugging issues
Choose the example that matches your tech stack and adapt it to your needs. Remember to implement the webhook signature verification as shown in the [Security](/webhooks#security)
section.
* * *
[Security](/webhooks#security)
-------------------------------
To verify webhook authenticity, each request includes these security headers:
* `X-Webhook-Signature`: HMAC-SHA256 signature of the request
* `X-Webhook-Timestamp`: Unix timestamp when the request was sent
The signature is generated by combining the timestamp and raw request body with a dot (`.`) separator, then creating an HMAC-SHA256 hash using your webhook secret. Here's how to implement secure verification:
### Verifying webhook signatures
PythonJavaScriptPHPRubyJavaGoC#
import hmac
import hashlib
import time
from fastapi import Request, HTTPException
WEBHOOK_SECRET = "whsec_..." # Load from environment variables
MAX_TIMESTAMP_DIFF = 300 # 5 minutes
async def verify_webhook_signature(request: Request) -> None:
"""Verify the webhook signature or raise HTTPException."""
try:
# Get signature and timestamp
signature = request.headers.get("X-Webhook-Signature")
timestamp = request.headers.get("X-Webhook-Timestamp")
if not signature or not timestamp:
raise HTTPException(401, "Missing signature headers")
# Verify timestamp freshness
timestamp_diff = abs(int(time.time()) - int(timestamp))
if timestamp_diff > MAX_TIMESTAMP_DIFF:
raise HTTPException(401, "Webhook timestamp too old")
# Get raw body
body = await request.body()
# Create signed payload
signed_payload = f"{timestamp}.{body.decode('utf-8')}"
# Calculate expected signature
expected = hmac.new(
WEBHOOK_SECRET.encode('utf-8'),
signed_payload.encode('utf-8'),
hashlib.sha256
).hexdigest()
# Secure comparison
if not hmac.compare_digest(expected, signature):
raise HTTPException(401, "Invalid signature")
except ValueError:
raise HTTPException(401, "Invalid signature format")
# Usage in webhook handler:
@app.post("/webhooks/featurebase")
async def handle_webhook(request: Request):
await verify_webhook_signature(request)
# ... rest of handler code
CopyCopied!
For maximum security:
1. Verify the webhook signature as soon as possible using HMAC-SHA256
2. Ensure the timestamp is within a 5-minute window to prevent replay attacks
3. Use constant-time comparison when checking signatures
4. Return 200 OK immediately after verification
5. Process the webhook payload asynchronously after responding
6. Keep your webhook secret key safe and never commit it to source control
* * *
[Event Delivery Behaviors](/webhooks#event-delivery-behaviors)
---------------------------------------------------------------
This section helps you understand different behaviors to expect regarding how Featurebase sends events to your webhook endpoint.
### Retry behavior
If a webhook delivery fails, Featurebase will automatically retry up to 3 times:
1. 1 minute after the first attempt
2. 1 hour after the second attempt
3. 6 hours after the third attempt
### Event ordering
Featurebase doesn't guarantee that webhook events arrive in the order they were generated. For example, updating a post might generate the following sequence of events:
1. `post.created`
2. `post.updated`
However, these events may not be delivered to your endpoint in that exact order. Your integration should not rely on receiving events sequentially, and it must be able to handle them regardless of arrival sequence.
### Handle duplicate events
Webhook endpoints might occasionally receive the same event more than once. To prevent double-processing, log the unique event IDs that your endpoint has already handled. If a new incoming event's ID matches a previously processed event, skip it.
### Example webhook event with ID
{
"type": "notification_event",
"topic": "post.updated",
"id": "notif_0193a6e6-fb6b-78ef-b71f-15008d9f9cde",
// ... rest of the event data
}
CopyCopied!
### Quick response time
Your endpoint should return a successful (2xx) status code promptly—before performing any lengthy operations that might lead to timeouts. For example:
// Good: Return 200 immediately, then process
app.post('/webhook', async (req, res) => {
// 1. Return 200 OK right away
res.status(200).send('OK');
// 2. Process the webhook asynchronously
processWebhookEvent(req.body).catch(err => {
console.error('Webhook processing error:', err);
});
});
// Bad: Wait for processing before responding
app.post('/webhook', async (req, res) => {
// Don't do this - it could timeout
await processWebhookEvent(req.body);
res.status(200).send('OK');
});
CopyCopied!
This approach prevents timeouts and ensures Featurebase knows your endpoint received the event, even if processing takes longer.
---
# Posts - Featurebase API Reference
Posts
=====
Posts are at the core of Featurebase — they are the basic building blocks of your feedback board. On this page, we'll dive into the different post endpoints you can use to manage them programmatically. We'll look at how to query, create, update, and delete posts.
[The post model](/posts#the-post-model)
----------------------------------------
The Post model contains all the information about the posts and additional metadata created under different boards, including the feedback, reactions, and discussions they generate. This encompasses the title and description of the post, the board it belongs to, any estimated release time for features discussed, and various tags indicating the importance or status of the post. This model allows for a comprehensive overview of user-generated ideas, requests, or issues, and the response they receive from the community.
### Properties
* Name
`id`
Type
string
Description
The id of the post. Example: "6409cde5f3c4e8d9a7977d89"
* Name
`slug`
Type
string
Description
The slug of the post. Example: "my-post-slug".
Can be used to create a URL for the post: `https://{yourorg}.featurebase.app/p/ {slug}`
* Name
`title`
Type
string
Description
The title of the post.
* Name
`content`
Type
string
Description
The content of the post.
* Name
`author`
Type
string
Description
The name of the author of the post.
* Name
`authorId`
Type
string
Description
The id for the author of the post.
* Name
`authorEmail`
Type
string
Description
The email of the author of the post.
* Name
`commentsAllowed`
Type
boolean
Description
Flag indicating whether comments are allowed on the post.
* Name
`organization`
Type
string
Description
The organization that the author of the post belongs to.
* Name
`upvotes`
Type
number
Description
The number of upvotes the post has received.
* Name
`postCategory`
Type
object
Description
The category of the post.
* Name
`authorPicture`
Type
string
Description
The URL to the picture of the author of the post.
* Name
`postStatus`
Type
object
Description
The status of the post.
* Name
`date`
Type
Date
Description
The date when the post was made.
* Name
`comments`
Type
Array
Description
An array of comments ids made on the post.
* Name
`postTags`
Type
Array
Description
An array of tag objects associated with the post.
* Name
`inReview`
Type
boolean
Description
Flag indicating whether the post is currently under review.
* Name
`lastUpvoted`
Type
Date
Description
The date when the post last received an upvote.
* Name
`ratingCount`
Type
number
Description
The total count of 1-10 scale importance ratings the post has received.
* Name
`averageRating`
Type
number
Description
The average rating of the post.
* Name
`eta`
Type
Date
Description
The estimated time of arrival or completion of the post.
* Name
`linearIssueId`
Type
string
Description
The ID of the related Linear issue.
* Name
`linearIssueUrl`
Type
string
Description
The URL of the related Linear issue.
* Name
`jiraIssueId`
Type
string
Description
The ID of the related Jira issue.
* Name
`jiraIssueUrl`
Type
string
Description
The URL of the related Jira issue.
* Name
`linearProjectId`
Type
string
Description
The ID of the related Linear project.
* Name
`metadata`
Type
object
Description
An object containing additional metadata related to the post.
* * *
GET/v2/posts
[List posts](/posts#list-posts)
--------------------------------
This endpoint allows you to retrieve a paginated list of all your posts. By default, a maximum of ten posts are shown per page.
### Optional filtering attributes
* Name
`id`
Type
string
Description
Find submission by it's id.
* Name
`q`
Type
string
Description
Search for posts by title or content.
* Name
`category`
Type
string\[\]
Description
Filter posts by providing an array of category(board) names.
* Name
`status`
Type
string\[\]
Description
Filter posts by status ids.
* Name
`sortBy`
Type
string
Description
Sort posts by a specific attribute. Example values: "date:desc" or "upvotes:desc"
* Name
`startDate`
Type
date
Description
Get posts created after a specific date.
* Name
`endDate`
Type
date
Description
Get posts created before a specific date.
### Pagination attributes
* Name
`limit`
Type
integer
Description
Number of results per page
* Name
`page`
Type
integer
Description
Page number
### Request
cURLNode.jsPython
GET
/v2/posts
curl -G https://do.featurebase.app/v2/posts \
-H "X-API-Key: {token}"
CopyCopied!
### Response
{
"results": [\
{\
"title": "My Cool Post",\
"content": "This is my cool post. It's really cool.",\
"author": "Admin",\
"authorId": "5fef50c5e9458a0012f82456",\
"authorPicture": "https://fb-usercontent.fra1.cdn.digitaloceanspaces.com/1681500636768.jpg",\
"commentsAllowed": true,\
"organization": "robiorg",\
"upvotes": 1,\
"upvoted": false,\
"downvoted": false,\
"postCategory": {\
"category": "💡 Feature Request",\
"private": false,\
"prefill": "
",\
"roles": [],\
"hiddenFromRoles": [],\
"id": "6418a4ec12471f16fa1dbeb4"\
},\
"postTags": [\
{\
"name": "Low Priority",\
"color": "",\
"private": false,\
"id": "6462be53f4f8de0c9b908f19"\
}\
],\
"postStatus": {\
"name": "In Review",\
"color": "Sky",\
"type": "reviewing",\
"isDefault": true,\
"id": "6431b593c8ea5e5b4dbbc047"\
},\
"date": "2023-05-15T22:22:48.405Z",\
"lastModified": "2023-05-15T22:22:48.405Z",\
"comments": [],\
"isSubscribed": false,\
"inReview": false,\
"lastDraggedTimestamps": [],\
"id": "6462b0b8df91a5dd5a727d96"\
}\
],
"page": 1,
"limit": 10,
"totalPages": 1,
"totalResults": 1
}
CopyCopied!
* * *
POST/v2/posts
[Create a new post](/posts#create-a-new-post)
----------------------------------------------
This endpoint allows you to create a new post to one of your boards.
### Required attributes
* Name
`title`
Type
string
Description
The title of the submission. It must be at least 2 characters long.
* Name
`category`
Type
string
Description
The board (a.k.a category) of the submission.
### Optional attributes
* Name
`content`
Type
string
Description
The content of the submission. Can be an empty string.
* Name
`email`
Type
string
Description
The email of the user submitting the post. Will create a new user if the email is not associated with an existing user.
* Name
`authorName`
Type
string
Description
Used when you provide an email. If the email is not associated with an existing user, a new user will be created with this name.
* Name
`tags`
Type
string\[\]
Description
The tags associated with the submission. Needs to be an array of tag names.
* Name
`commentsAllowed`
Type
boolean
Description
Flag indicating whether comments are allowed on the submission.
* Name
`status`
Type
string
Description
The status of the submission.
* Name
`date`
Type
Date
Description
Set the post creation date.
* Name
`customInputValues`
Type
object
Description
The custom input values for the post. The key should be the custom input field ID, and the value can be a string, boolean, number, array of strings, or null depending on the field type. You can copy the custom input field ID from the dashboard [custom fields page](https://auth.featurebase.app/choose-org?redirect=/settings/custom-fields)
.
Example: `{...,"customInputValues": {"65d2634a6c467fbea2a72734": ["iOS"]}}`
### Request
cURLNode.jsPython
POST
/v2/posts
curl https://do.featurebase.app/v2/posts \
-H "X-API-Key: {token}" \
-d title="My Cool Post" \
-d content="This is my cool post. It's really cool." \
-d category="💡 Feature Requests"
CopyCopied!
### Response
{
"success": true,
"submission": {
"title": "My Cool Post",
"content": "This is my cool post. It's really cool.",
"author": "Admin",
"authorId": "5fef50c5e9458a0012f82456",
"authorPicture": "https://fb-usercontent.fra1.cdn.digitaloceanspaces.com/1681500636768.jpg",
"commentsAllowed": true,
"organization": "robiorg",
"upvotes": 1,
"upvoted": true,
"downvoted": false,
"postCategory": {
"category": "💡 Feature Request",
"private": false,
"prefill": "
",
"roles": [],
"hiddenFromRoles": [],
"id": "6418a4ec12471f16fa1dbeb4"
},
"postStatus": {
"name": "In Review",
"color": "Sky",
"type": "reviewing",
"isDefault": true,
"id": "6431b593c8ea5e5b4dbbc047"
},
"comments": [],
"isSubscribed": false,
"inReview": false,
"lastDraggedTimestamps": [],
"postTags": [],
"date": "2023-05-15T22:22:48.405Z",
"lastModified": "2023-05-15T22:22:48.405Z",
"id": "6462b0b8df91a5dd5a727d96"
}
}
CopyCopied!
* * *
PATCH/v2/posts
[Update a post](/posts#update-a-post)
--------------------------------------
This endpoint allows you to update a post by providing the post id. Refer to [the list](/posts#the-post-model)
at the top of this page to see which properties are included with post objects.
### Required attributes
* Name
`id`
Type
string
Description
The id of the submission.
### Properties you can update
* Name
`title`
Type
string
Description
The title of the post. Example: "Add dark mode support"
* Name
`content`
Type
string
Description
The HTML content of the post. Example: "It would be great to have dark mode support for better viewing at night.
"
* Name
`status`
Type
string
Description
The status of the submission. Example: "In Progress"
* Name
`commentsAllowed`
Type
boolean
Description
Flag indicating whether comments are allowed on the submission. Example: true
* Name
`category`
Type
string
Description
The category of the submission. Example: "💡 Feature Request"
* Name
`status`
Type
string
Description
The status of the submission.
* Name
`sendStatusUpdateEmail`
Type
boolean
Description
Flag indicating whether to send a status update email to the upvoters. Default: false
* Name
`tags`
Type
string\[\]
Description
The tags of the submission. Example: \["tag1", "tag2"\]
* Name
`inReview`
Type
boolean
Description
Flag indicating whether the submission is in review. In review posts are not visible to users.
* Name
`date`
Type
Date
Description
The post creation date.
* Name
`customInputValues`
Type
object
Description
The custom input values for the post. The key should be the custom input field ID, and the value can be a string, boolean, number, array of strings, or null depending on the field type. You can copy the custom input field ID from the dashboard [custom fields page](https://auth.featurebase.app/choose-org?redirect=/settings/custom-fields)
.
Example: `{...,"customInputValues": {"65d2634a6c467fbea2a72734": ["iOS"]}}`
### Request
cURLNode.jsPython
PATCH
/v2/posts
curl -X PATCH "https://do.featurebase.app/v2/posts" \
-H "X-API-Key: {token}" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "id=6462c35485d966548318efbd" \
-d "tags=Low Priority" \
-d "status=In Progress"
CopyCopied!
### Response
{
"success": true
}
CopyCopied!
* * *
DELETE/v2/posts
[Delete a post](/posts#delete-a-post)
--------------------------------------
This endpoint allows you to delete posts from your boards. Note: This will permanently delete the post.
### Required attributes
* Name
`id`
Type
string
Description
The id of the submission.
### Request
cURLNode.jsPython
DELETE
/v2/posts
curl -X DELETE https://do.featurebase.app/v2/posts \
-H "X-API-Key: {token}" \
-d "id=6462c35485d966548318efbd"
CopyCopied!
### Response
{
"success": true
}
CopyCopied!
* * *
GET/v2/posts/upvoters
[Get post upvoters](/posts#get-post-upvoters)
----------------------------------------------
This endpoint allows you to retrieve a paginated list of users who have upvoted a specific post.
### Required attributes
* Name
`submissionId`
Type
string
Description
The ID of the post to get upvoters for.
### Pagination attributes
* Name
`page`
Type
integer
Description
Page number (default: 1)
* Name
`limit`
Type
integer
Description
Number of results per page (default: 10, max: 100)
### Request
cURLNode.jsPython
GET
/v2/posts/upvoters
curl -G https://do.featurebase.app/v2/posts/upvoters \
-H "X-API-Key: {token}" \
-d "submissionId=676f0f6765bdaa7d7d760f88" \
-d "page=1" \
-d "limit=10"
CopyCopied!
### Response
{
"success": true,
"results": [\
{\
"id": "676f0f6765bdaa7d7d760f88",\
"userId": "676f0f673dbb299c8a4f3057",\
"organizationId": "5febde12dc56d60012d47db6",\
"companies": [\
{\
"id": "676f0f67169ca7f8674a1f9a",\
"name": "Awesome Company",\
"monthlySpend": 500,\
"createdAt": "2025-01-21T02:02:11.687Z",\
"customFields": {\
"subscriptionStatus": "paid",\
"plan": "pro",\
"location": "Europe"\
},\
"_id": "677314a47d6c448912fae542"\
}\
],\
"email": "john@example.com",\
"name": "John Steezy",\
"profilePicture": "https://fb-usercontent.fra1.cdn.digitaloceanspaces.com/anon_23.png",\
"commentsCreated": 0,\
"postsCreated": 0,\
"lastActivity": "2025-01-03T21:42:30.181Z",\
"subscribedToChangelog": true,\
"manuallyOptedOutFromChangelog": false,\
"roles": [],\
"locale": "en",\
"verified": true,\
"type": "customer",\
"description": ""\
},\
...\
],
"page": 1,
"limit": 10,
"totalPages": 7,
"totalResults": 63
}
CopyCopied!
* * *
POST/v2/posts/upvoters
[Add upvoters to a post](/posts#add-upvoters-to-a-post)
--------------------------------------------------------
This endpoint allows you to perform an update on a message. Examples of updates are adding a reaction, editing the message, or adding an attachment.
### Required attributes
* Name
`id`
Type
string
Description
ID of the post.
* Name
`email`
Type
string
Description
Email of the upvoter.
* Name
`name`
Type
string
Description
Name of the upvoter
### Request
cURLJavaScriptPython
POST
/v2/posts/upvoters
curl -X POST https://do.featurebase.app/v2/posts/upvoters \
-H "X-API-Key: {token}" \
-H "Content-Type: application/json" \
-d '{
"id": "6462b0b8df91a5dd5a727d96",
"email": "random@email.com",
"name": "Random Name"
}'
CopyCopied!
### Response
{
"success": true
}
CopyCopied!
---
# Comments - Featurebase API Reference
Comments
========
On this page, we'll dive into the different comment endpoints you can use to manage them programmatically. We'll look at how to query, send, update, and delete comments.
[The comment model](/comment#the-comment-model)
------------------------------------------------
The comment model contains information about a comment made on a post or changelog.
### Properties
* Name
`id`
Type
string
Description
The id of the comment. Example: "6409cde5f3c4e8d9a7977d89"
* Name
`content`
Type
string
Description
The content of the comment. In HTML format.
* Name
`author`
Type
string
Description
The name of the author of the comment.
* Name
`authorId`
Type
string
Description
The id for the author of the comment.
* Name
`authorPicture`
Type
string
Description
The profile picture of the author of the comment.
* Name
`isPrivate`
Type
boolean
Description
Flag indicating whether the comment is private. Private comments are visible only to admins of the organization.
* Name
`isDeleted`
Type
boolean
Description
Flag indicating whether the comment has been deleted.
* Name
`upvotes`
Type
number
Description
The number of upvotes the comment has received.
* Name
`downvotes`
Type
number
Description
The number of downvotes the comment has received.
* Name
`score`
Type
number
Description
The score of the comment. Calculated by subtracting the number of downvotes from the number of upvotes.
* Name
`submission`
Type
string
Description
The id of the Featurebase submission if this comment is associated with a submission.
* Name
`changelog`
Type
string
Description
The id of the Featurebase changelog if this comment is associated with a changelog.
* Name
`parentComment`
Type
string
Description
The id of the parent comment if this comment is a reply to another comment.
* Name
`path`
Type
string
Description
The "path" is a string made up of IDs separated by slashes ('/'). It shows the series of steps to reach a specific comment. The first ID in the string refers to either a submission or changelog. Following IDs represent each parent comment, leading up to the top-level comment. The ID of the comment this path relates to is not included in this string.
Example: 64a5376aca108a14db4a61f1/64bac622fd8b1ea910527b3c
* Name
`replies`
Type
Comment
Description
An array of comment objects that are replies to this comment. Replies to comments can contain their own replies.
* Name
`organization`
Type
string
Description
The id of the organization the comment belongs to.
* Name
`createdAt`
Type
Date
Description
The date when the comment was created.
* Name
`originalSubmission`
Type
string
Description
The id of the original submission if this comment was merged from another submission.
* Name
`postStatus`
Type
string
Description
Status change comments have a post status associated with them. This is the status the post was changed to by the status name.
* Name
`inReview`
Type
boolean
Description
Flag indicating whether the comment is currently under review.
* Name
`pinned`
Type
boolean
Description
Flag indicating whether the comment is pinned.
* * *
GET/v2/comment
[Get comments](/comment#get-comments)
--------------------------------------
This endpoint allows you to retrieve a paginated list of all comments for a post/changelog. By default, a maximum of ten comments are shown per page.
### Required attributes. One of the following is required.
* Name
`submissionId`
Type
string
Description
The id of the submission to get comments for.
Accepts both ObjectId and slug.
Example: "65f5f3c037fc63b7d43d0f16" or "my-post-slug"
* Name
`changelogId`
Type
string
Description
The id of the changelog to get comments for.
Accepts both ObjectId and slug.
Example: "65f5f3c037fc63b7d43d0f16" or "my-changelog-slug"
### Optional filtering attributes
* Name
`privacy`
Type
enum
Description
Filter comments by privacy setting. Allowed values: "public", "private", "all"
* Name
`inReview`
Type
boolean
Description
Filter comments by whether they are in review. Set to true to get only comments that are in review.
* Name
`commentThreadId`
Type
string
Description
Given a specific comment id, this will return all comments in the thread with the root comment being the comment with the given id.
### Pagination attributes
* Name
`limit`
Type
integer
Description
Number of results per page. Default is 10.
* Name
`page`
Type
integer
Description
Page number. Default is 1.
* Name
`sortBy`
Type
enum
Description
Sort order of the results.
Allowed values: "best", "top", "new", "old"
Default: "best"
### Request
cURLNode.jsPython
GET
/v2/comment
curl -G https://do.featurebase.app/v2/comment?submissionId=63ed5a57cd650fc9c9032925 \
-H "X-API-Key: {token}"
CopyCopied!
### Response
{
"results": [\
{\
"upvoted": false,\
"downvoted": false,\
"inReview": false,\
"isSpam": false,\
"pinned": false,\
"emailSent": false,\
"sendNotification": true,\
"organization": "5febde12dc56d60012d47db6",\
"submission": "63ed5a57cd650fc9c9032925",\
"author": "John Steezy",\
"authorId": "63a050296e448a0434d72c9b",\
"authorPicture": "https://fb-usercontent.fra1.cdn.digitaloceanspaces.com/20231002205914057346.png",\
"isPrivate": false,\
"isDeleted": false,\
"confidenceScore": 0,\
"content": "This is an example comment.
",\
"upvotes": 1,\
"downvotes": 0,\
"score": 1,\
"parentComment": null,\
"path": "63ed5a57cd650fc9c9032925",\
"replies": [\
{\
"inReview": false,\
"pinned": false,\
"emailSent": false,\
"sendNotification": true,\
"organization": "5febde12dc56d60012d47db6",\
"submission": "63ed5a57cd650fc9c9032925",\
"author": "Admin",\
"authorId": "5febde0bdc56d60012d47db5",\
"authorPicture": "https://fb-usercontent.fra1.cdn.digitaloceanspaces.com/878ab937-3862-4491-ba5c-4a65113a3765.png",\
"isPrivate": false,\
"isDeleted": false,\
"confidenceScore": 0.20654329147389295,\
"content": "This is an example reply.
",\
"upvotes": 1,\
"downvotes": 0,\
"score": 1,\
"parentComment": "6409cde5f3c4e8d9a7977d89",\
"path": "63ed5a57cd650fc9c9032925/6409cde5f3c4e8d9a7977d89",\
"replies": [],\
"createdAt": "2023-03-09T12:17:33.599Z",\
"updatedAt": "2023-10-27T19:27:52.338Z",\
"downvoted": false,\
"isSpam": false,\
"upvoted": false,\
"id": "6409ce5df3c4e8d9a7978ce1"\
}\
],\
"createdAt": "2023-03-09T12:15:33.672Z",\
"updatedAt": "2023-08-10T07:30:39.451Z",\
"id": "6409cde5f3c4e8d9a7977d89"\
},\
{\
"upvoted": false,\
"downvoted": false,\
"inReview": false,\
"isSpam": false,\
"pinned": false,\
"emailSent": false,\
"sendNotification": true,\
"organization": "5febde12dc56d60012d47db6",\
"submission": "63ed5a57cd650fc9c9032925",\
"author": "Admin",\
"authorId": "5febde0bdc56d60012d47db5",\
"authorPicture": "https://fb-usercontent.fra1.cdn.digitaloceanspaces.com/878ab937-3862-4491-ba5c-4a65113a3765.png",\
"isPrivate": false,\
"isDeleted": false,\
"confidenceScore": 0,\
"content": "Thanks a lot for the suggestion!
",\
"upvotes": 1,\
"downvotes": 0,\
"score": 1,\
"parentComment": null,\
"path": "63ed5a57cd650fc9c9032925",\
"replies": [\
{\
"upvoted": false,\
"downvoted": false,\
"inReview": false,\
"isSpam": false,\
"pinned": false,\
"emailSent": false,\
"sendNotification": true,\
"organization": "5febde12dc56d60012d47db6",\
"submission": "63ed5a57cd650fc9c9032925",\
"author": "User Two",\
"authorId": "63ed595bcd650fc9c9031a07",\
"authorPicture": "https://fb-usercontent.fra1.cdn.digitaloceanspaces.com/20231002205911291646.jpg",\
"isPrivate": false,\
"isDeleted": false,\
"confidenceScore": 0,\
"content": "No worries, happy to help
",\
"upvotes": 1,\
"downvotes": 0,\
"score": 1,\
"parentComment": "63ed5bdacd650fc9c9034208",\
"path": "63ed5a57cd650fc9c9032925/63ed5bdacd650fc9c9034208",\
"replies": [],\
"createdAt": "2023-02-16T02:46:29.013Z",\
"updatedAt": "2023-02-16T02:46:29.013Z",\
"id": "63ed9905cd650fc9c9053aca"\
}\
],\
"createdAt": "2023-02-15T22:25:30.094Z",\
"updatedAt": "2023-02-15T22:25:30.094Z",\
"id": "63ed5bdacd650fc9c9034208"\
}\
],
"page": 1,
"limit": 10,
"totalPages": 1,
"totalResults": 2
}
CopyCopied!
* * *
POST/v2/comment
[Create a new comment](/comment#create-a-new-comment)
------------------------------------------------------
This endpoint allows you to create a new comment or reply to an existing comment. You can create a comment for a submission or changelog.
### Required attributes.
* Name
`submissionId`
Type
string
Description
The id of the submission to get comments for.
Accepts both ObjectId and slug.
Example: "65f5f3c037fc63b7d43d0f16" or "my-post-slug"
* Name
`changelogId`
Type
string
Description
The id of the changelog to get comments for. Accepts both ObjectId and slug. Example: "65f5f3c037fc63b7d43d0f16" or "my-changelog-slug"
* Name
`content`
Type
string
Description
The content of the comment.
### Optional attributes
* Name
`parentCommentId`
Type
string
Description
The id of the parent comment if this comment is a reply to another comment.
* Name
`isPrivate`
Type
boolean
Description
Flag indicating whether the comment is private. Private comments are visible only to admins of the organization.
* Name
`sendNotification`
Type
boolean
Description
Flag indicating whether to notify voters of the submission about the comment. Defaults to true.
* Name
`createdAt`
Type
Date
Description
Set the date when the comment was created. Useful for importing comments from other platforms.
* Name
`author`
Type
Object
Description
Post the comment under a specific user. If not provided, the comment will be posted under the owner user of the Featurebase account.
Example Object:
{
"name": "John Doe",
"email": "email@example.com",
"profilePicture": "https://example.com/profile.jpg"
}
CopyCopied!
### Request
cURLNode.jsPython
POST
/v2/comment
curl https://do.featurebase.app/v2/comment \
-H "X-API-Key: {token}" \
-d content="This is my cool comment. It's really cool." \
-d submissionId="65f5f3c037fc63b7d43d0f16"
CopyCopied!
### Response
{
"success": true,
"comment": {
"author": "Admin",
"authorId": "5fef50c5e9458a0012f82456",
"authorPicture": "https://fb-usercontent.fra1.cdn.digitaloceanspaces.com/1693132126228.jpg",
"isPrivate": false,
"content": "This is my cool comment. It's really cool.",
"upvotes": 1,
"downvotes": 0,
"score": 1,
"confidenceScore": 0.20654329147389295,
"submission": "65f5f3c037fc63b7d43d0f16",
"replies": [],
"organization": "6595518396205e06b897ad65",
"upvoted": true,
"downvoted": false,
"inReview": false,
"isSpam": false,
"pinned": false,
"emailSent": false,
"sendNotification": true,
"path": "65f5f3c037fc63b7d43d0f16",
"createdAt": "2024-04-19T13:09:03.405Z",
"updatedAt": "2024-04-19T13:09:03.405Z",
"id": "66226cefcb28bdf767296403"
}
}
CopyCopied!
* * *
PATCH/v2/comment
[Update a comment](/comment#update-a-comment)
----------------------------------------------
This endpoint allows you to update a comment by providing the comment id.
### Required attributes
* Name
`id`
Type
string
Description
The id of the comment.
### Properties you can update
* Name
`content`
Type
string
Description
The content of the comment. Example: "This is my updated comment."
* Name
`isPrivate`
Type
boolean
Description
Flag indicating whether the comment is private. Private comments are visible only to admins of the organization.
* Name
`pinned`
Type
boolean
Description
Flag indicating whether the comment is pinned. Pinned comments are displayed at the top of the comments section.
* Name
`inReview`
Type
boolean
Description
Flag indicating whether the comment is in review. In review comments are not visible to other users.
* Name
`createdAt`
Type
Date
Description
Update the date when the comment was created. Useful for importing comments from other platforms.
### Request
cURLNode.jsPython
PATCH
/v2/comment
curl -X PATCH "https://do.featurebase.app/v2/comment" \
-H "X-API-Key: {token}" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "id=6462c35485d966548318efbd" \
-d "inReview=false" \
CopyCopied!
### Response
{
"success": true
}
CopyCopied!
* * *
DELETE/v2/comment
[Delete a comment](/comment#delete-a-comment)
----------------------------------------------
This endpoint allows you to delete comments from your posts. Note: If you are deleting a comment that has replies, we will soft delete the comment. The content/author will be replaced with "\[Deleted\]". This helps maintain the context of the conversation.
### Required attributes
* Name
`id`
Type
string
Description
The id of the comment.
### Request
cURLNode.jsPython
DELETE
/v2/comment
curl -X DELETE https://do.featurebase.app/v2/comment \
-H "X-API-Key: {token}" \
-d "id=6462c35485d966548318efbd"
CopyCopied!
### Response
{
"success": true
}
CopyCopied!
---
# Changelogs - Featurebase API Reference
Changelogs
==========
Changelogs are one of the core features in Featurebase. On this page, we'll dive into the different changelog endpoints you can use to manage them programmatically. We'll look into subscribing your users to your changelog so that they always receive updates when you post changes.
[The Changelog model](/changelogs#the-changelog-model)
-------------------------------------------------------
The Changelog model contains all the information about a changelog, such as its title, content, date of creation, and much more. It has the following properties:
### Properties
* Name
`id`
Type
string
Description
The id of the changelog.
* Name
`slug`
Type
string
Description
The slug of the changelog. Example: "my-changelog-slug".
Can be used to create a URL for the changelog: `https://{yourorg}.featurebase.app/changelog/{slug}`
* Name
`featuredImage`
Type
string
Description
The URL of the featured image of the changelog.
* Name
`title`
Type
string
Description
The title of the changelog.
* Name
`content`
Type
string
Description
The HTML content of the changelog.
* Name
`markdownContent`
Type
string
Description
The markdown content of the changelog.
* Name
`date`
Type
Date
Description
The date when the changelog was made.
* Name
`state`
Type
string
Description
State can either be "draft" or "live".
* Name
`changelogCategories`
Type
object\[\]
Description
An array of category objects associated with the changelog.
* Name
`organization`
Type
string
Description
The organization that this changelog belongs to.
* Name
`emailSentToSubscribers`
Type
boolean
Description
Flag indicating whether the email has been sent to subscribers for this changelog.
* Name
`commentCount`
Type
number
Description
The number of comments on the changelog.
* Name
`allowedSegmentIds`
Type
string\[\]
Description
An array of segment ids that are allowed to view the changelog. If empty, everyone can view the changelog.
* Name
`locale`
Type
string
Description
The locale of the changelog, defaulting to "en".
* * *
GET/v2/changelog
[Get changelogs](/changelogs#get-changelogs)
---------------------------------------------
This endpoint allows you to retrieve a paginated list of all your changelogs. By default, a maximum of ten changelogs are shown per page.
### Query Parameters
* Name
`id`
Type
string
Description
Find changelog by its id.
* Name
`q`
Type
string
Description
Search for changelogs by title or content.
* Name
`categories`
Type
string\[\]
Description
Filter changelogs by category, by providing an array of category names.
* Name
`limit`
Type
integer
Description
Number of results per page. Maximum: 100.
* Name
`page`
Type
integer
Description
Page number.
* Name
`locale`
Type
string
Description
The locale of the changelogs. Defaults to 'en'.
* Name
`state`
Type
string
Description
The state of the changelog, either 'draft' or 'live'.
### Request
cURLNode.jsPython
GET
/v2/changelog
curl -G https://do.featurebase.app/v2/changelog \
-H "X-API-Key: {token}"
CopyCopied!
### Response
{
"results": [\
{\
"title": "Your awesome changelog!",\
"slug": "your-awesome-changelog",\
"content": "Your changelog content in HTML format.
",\
"markdownContent": "Your changelog content in markdown format.",\
"date": "2023-05-07T17:46:39.168Z",\
"state": "live",\
"sendNotification": true,\
"emailSentToSubscribers": true,\
"commentCount": 2,\
"changelogCategories": [\
{\
"name": "Test2",\
"roles": [],\
"id": "6438a1efda3640f8feb72121"\
}\
],\
"organization": "robiorg",\
"id": "6457e3ff70afca5d8c27dccc",\
},\
{\
...\
},\
...\
],
"page": 1,
"limit": 10,
"totalPages": 30,
"totalResults": 292
}
CopyCopied!
* * *
POST/v2/changelog
[Create changelog](/changelogs#create-changelog)
-------------------------------------------------
This endpoint allows you to create a new changelog.
### Required Attributes
* Name
`title`
Type
string
Description
The title of the changelog.
* Name
`htmlContent`
Type
string
Description
The HTML content of the changelog. Provide either `htmlContent` or `markdownContent` depending on the format your data is in.
* Name
`markdownContent`
Type
string
Description
The markdown content of the changelog.
### Optional Attributes
* Name
`changelogCategories`
Type
string\[\]
Description
An array of category identifiers to which the changelog belongs.
Example: `["New", "Fixed", "Improved"]`
* Name
`featuredImage`
Type
string
Description
The URL of the featured image for the changelog.
* Name
`allowedSegmentIds`
Type
string\[\]
Description
An array of segment ids that are allowed to view the changelog.
* Name
`locale`
Type
string
Description
The locale of the changelog, defaulting to "en".
* Name
`date`
Type
Date
Description
The date of the changelog.
### Request
cURLNode.jsPython
POST
/v2/changelog
curl -X 'POST' 'https://do.featurebase.app/v2/changelog' \
-H 'X-API-Key: {token}' \
-H 'Content-Type: application/json' \
-d '{
"title": "New Features Update",
"markdownContent": "Exciting new features to explore.",
"changelogCategories": ["New", "Fixed", "Improved"],
"state": "draft",
"featuredImage": "http://example.com/image.png",
}'
CopyCopied!
### Response
{
"results": {
"title": "Your awesome changelog!",
"slug": "your-awesome-changelog",
"content": "Your changelog content in HTML format.
",
"markdownContent": "Your changelog content in markdown format.",
"date": "2023-05-07T17:46:39.168Z",
"state": "live",
"sendNotification": true,
"emailSentToSubscribers": true,
"commentCount": 2,
"changelogCategories": [\
{\
"name": "Test2",\
"roles": [],\
"id": "6438a1efda3640f8feb72121"\
}\
],
"organization": "robiorg",
"id": "6457e3ff70afca5d8c27dccc",
},
"success": true
}
CopyCopied!
* * *
PATCH/v2/changelog
[Update changelog](/changelogs#update-changelog)
-------------------------------------------------
This endpoint allows you to update an existing changelog. Only send the fields you want to update.
### Required Attributes
* Name
`id`
Type
string
Description
The id of the changelog to update.
### Fields to Update
* Name
`title`
Type
string
Description
The title of the changelog.
* Name
`htmlContent`
Type
string
Description
The HTML content of the changelog. Provide either `htmlContent` or `markdownContent` depending on the format your data is in.
* Name
`markdownContent`
Type
string
Description
The markdown content of the changelog.
* Name
`changelogCategories`
Type
string\[\]
Description
An array of category identifiers to which the changelog belongs.
Example: `["New", "Fixed", "Improved"]`
* Name
`date`
Type
Date
Description
The date of the changelog.
* Name
`featuredImage`
Type
string
Description
The URL of the featured image for the changelog.
* Name
`allowedSegmentIds`
Type
string\[\]
Description
An array of segment ids that are allowed to view the changelog.
### Request
cURLNode.jsPython
PATCH
/v2/changelog
curl -X 'PATCH' 'https://do.featurebase.app/v2/changelog' \
-H 'X-API-Key: {token}' \
-H 'Content-Type: application/json' \
-d '{
"id": "6457e3ff70afca5d8c27dccc",
"title": "New Features Update",
"markdownContent": "Exciting new features to explore.",
"changelogCategories": ["New", "Fixed", "Improved"],
"state": "draft",
"featuredImage": "http://example.com/image.png",
"sendNotification": true,
}'
CopyCopied!
### Response
{
"changelog": {
"title": "Your awesome changelog!",
"slug": "your-awesome-changelog",
"content": "Your changelog content in HTML format.
",
"markdownContent": "Your changelog content in markdown format.",
"date": "2023-05-07T17:46:39.168Z",
"state": "draft",
"sendNotification": true,
"emailSentToSubscribers": true,
"commentCount": 2,
"changelogCategories": [\
{\
"name": "Test2",\
"roles": [],\
"id": "6438a1efda3640f8feb72121"\
}\
],
"organization": "robiorg",
"id": "6457e3ff70afca5d8c27dccc",
},
"success": true
}
CopyCopied!
* * *
DELETE/v2/changelog
[Delete changelog](/changelogs#delete-changelog)
-------------------------------------------------
This endpoint allows you to delete a changelog.
### Required Attributes
* Name
`id`
Type
string
Description
The id of the changelog to delete.
### Request
cURLNode.jsPython
DELETE
/v2/changelog
curl -X 'DELETE' 'https://do.featurebase.app/v2/changelog' \
-H 'X-API-Key: {token}' \
-H 'Content-Type: application/json' \
-d '{
"id": "6457e3ff70afca5d8c27dccc"
}'
CopyCopied!
### Response
{
"success": true
}
CopyCopied!
* * *
GET/v2/changelog/subscribers
[Get changelog subscribers](/changelogs#get-changelog-subscribers)
-------------------------------------------------------------------
This endpoint allows you to retrieve a list of all your changelog subscribers.
### Request
cURLNode.jsPython
GET
/v2/changelog/subscribers
curl -G https://do.featurebase.app/v2/changelog/subscribers \
-H "X-API-Key: {token}"
CopyCopied!
### Response
{
"success": true,
"emails": [\
"yourcustomer@gmail.com"\
]
}
CopyCopied!
* * *
POST/v2/changelog/subscribers
[Add new changelog subscribers](/changelogs#add-new-changelog-subscribers)
---------------------------------------------------------------------------
This endpoint allows you to add changelog subscribers. They will then receive emails when you post changelogs.
### Required Attributes
* Name
`emails`
Type
string\[\]
Description
An array of emails to add as subscribers.
* Name
`locale`
Type
string
Description
The locale for the subscribers, defaulting to "en".
### Request
cURLNode.jsPython
POST
/v2/changelog/subscribers
curl -X 'POST' 'https://do.featurebase.app/v2/changelog/subscribe' \
-H 'X-API-Key: {token}' \
-H 'Content-Type: application/json' \
-d '{
"emails": [\
"yourcustomer@gmail.com",\
"yoursecondcustomer@gmail.com"\
],
}'
CopyCopied!
### Response
{
"success": true
}
CopyCopied!
* * *
DELETE/v2/changelog/subscribers
[Remove changelog subscribers by email](/changelogs#remove-changelog-subscribers-by-email)
-------------------------------------------------------------------------------------------
This endpoint allows you to remove changelog subscribers.
### Required Attributes
* Name
`emails`
Type
string\[\]
Description
An array of emails to remove from subscribers.
* Name
`locale`
Type
string
Description
The locale for the subscribers, defaulting to "en".
### Request
cURLNode.jsPython
DELETE
/v2/changelog/subscribers
curl -X 'DELETE' 'https://do.featurebase.app/v2/changelog/subscribe' \
-H 'X-API-Key: {token}' \
-H 'Content-Type: application/json' \
-d '{
"emails": [\
"yourcustomer@gmail.com"\
],
}'
CopyCopied!
### Response
{
"success": true
}
CopyCopied!
* * *
POST/v2/changelog/publish
[Publish changelog](/changelogs#publish-changelog)
---------------------------------------------------
This endpoint allows you to publish a changelog and optionally send an email notification.
### Required Attributes
* Name
`id`
Type
string
Description
The id of the changelog to publish.
* Name
`sendEmail`
Type
boolean
Description
A flag indicating whether to send an email notification to subscribers.
* Name
`locales`
Type
string\[\]
Description
An array of locales to publish the changelog to. An empty array publishes to all locales.
* Name
`scheduledDate`
Type
Date
Description
The date when the changelog should be published. Must be a future date.
### Request
cURLNode.jsPython
POST
/v2/changelog/publish
curl -X 'POST' 'https://do.featurebase.app/v2/changelog/publish' \
-H 'X-API-Key: {token}' \
-H 'Content-Type: application/json' \
-d '{
"id": "6457e3ff70afca5d8c27dccc",
"sendEmail": true,
"scheduledDate": "2023-12-01T00:00:00Z"
}'
CopyCopied!
### Response
{
"success": true
}
CopyCopied!
* * *
POST/v2/changelog/unpublish
[Unpublish changelog](/changelogs#unpublish-changelog)
-------------------------------------------------------
This endpoint allows you to unpublish a changelog.
### Required Attributes
* Name
`id`
Type
string
Description
The id of the changelog to unpublish.
* Name
`locales`
Type
string\[\]
Description
An array of locales to unpublish the changelog from. An empty array unpublishes from all locales.
### Request
cURLNode.jsPython
POST
/v2/changelog/unpublish
curl -X 'POST' 'https://do.featurebase.app/v2/changelog/unpublish' \
-H 'X-API-Key: {token}' \
-H 'Content-Type: application/json' \
-d '{
"id": "6457e3ff70afca5d8c27dccc",
}'
CopyCopied!
### Response
{
"success": true
}
CopyCopied!
---
# Roles - Featurebase API Reference
Roles
=====
Roles are a core part of the User Segmentation feature. On this page, we'll dive into the different role endpoints you can use to manage them programmatically. We'll look into giving your users specific roles and thereby allowing them to view specific boards.
* * *
POST/v2/organization/roles
[Add users to roles](/roles#add-users-to-roles)
------------------------------------------------
This endpoint allows you to add users to roles. Those roles can then be used to control access to boards & changelogs.
### Required attributes
* Name
`emails`
Type
string\[\]
Description
An array of emails to add to the role.
* Name
`roles`
Type
string\[\]
Description
The roles to give these users.
### Request
cURLNode.jsPython
POST
/v2/organization/roles
curl -X 'POST' 'https://do.featurebase.app/v2/organization/roles' \
-H 'X-API-Key: {token}' \
-H 'Content-Type: application/json' \
-d '{
"emails": [\
"yourcustomer@gmail.com",\
"yoursecondcustomer@gmail.com\
],
"roles": ["Employee", "Customer"]
}'
CopyCopied!
### Response
{
"success": true
}
CopyCopied!
* * *
DELETE/v2/organization/roles
[Remove users from roles by email](/roles#remove-users-from-roles-by-email)
----------------------------------------------------------------------------
This endpoint allows you to remove roles from users.
### Required attributes
* Name
`emails`
Type
string\[\]
Description
An array of emails to remove roles from.
### Optional attributes
* Name
`roles`
Type
string\[\]
Description
An array of roles to remove from the users. If not provided, all roles will be removed.
### Request
cURLNode.jsPython
DELETE
/v2/organization/roles
curl -X 'DELETE' 'https://do.featurebase.app/v2/organization/roles' \
-H 'X-API-Key: {token}' \
-H 'Content-Type: application/json' \
-d '{
"emails": [\
"yourcustomer@gmail.com",\
],
"roles": ["Employee"]
}'
CopyCopied!
### Response
{
"success": true
}
CopyCopied!
---
# Identify Users - Featurebase API Reference
Identify Users
==============
Sync your customer data with Featurebase to view and sort ideas by customers monthly spend and other parameters.
The Company model
=================
### Required attributes
* Name
`id`
Type
string
Description
Company ID
* Name
`name`
Type
string
Description
Company name
### Optional attributes
* Name
`monthlySpend`
Type
number
Description
Monthly recurring revenue from this company.
* Name
`createdAt`
Type
Date
Description
Date when the company was created.
* Name
`customFields`
Type
object
Description
Object containing key-value pairs of custom fields.
* * *
GET/v2/organization/identifyUser
[Get single identified user](/identify#get-single-identified-user)
-------------------------------------------------------------------
This endpoint allows you to get an identified user's information.
### Required attributes (one of the following is required)
* Name
`email`
Type
string
Description
Email of the user.
* Name
`id`
Type
string
Description
Your own ID of the user.
### Request
cURLNode.jsPython
GET
/v2/organization/identifyUser
curl -G https://do.featurebase.app/v2/organization/identifyUser?email=youruser@example.com \
-H "X-API-Key: {token}"
CopyCopied!
### Response
{
"success": true,
"user": {
"fbUserId": "5febdbb7b36fdd00129617c4",
"organization": "demonstration",
"customFields": {
"Based In": "Manchester",
},
"companies": [\
{\
"id": "23",\
"name": "Business Inc.",\
"monthlySpend": 1000,\
"customFields": {\
"Location": "Canada"\
},\
"createdAt": "2023-05-18T16:15:05.574Z"\
},\
{\
"id": "43",\
"name": "Second company",\
"monthlySpend": 1900,\
"customFields": {\
"Location": "Tallinn"\
},\
"createdAt": "2023-05-18T16:15:05.574Z"\
}\
],
"externalUserId": "3216544",
"id": "6465431c1f9677b6de697168",
"name": "John Steezy",
"email": "youruser@gmail.com",
"profilePicture": "https://fb-usercontent.fra1.cdn.digitaloceanspaces.com/3110ce26-faa9-46d4-b39a-8a2d99f7fd00.png",
"roleDetails": {"name": "Paid User", "id": "6465431c1f9677b6de697168"} // Only sent along for enterprise users with roles set up.
}
}
CopyCopied!
* * *
GET/v2/organization/identifyUser/query
[Query identified users](/identify#query-identified-users)
-----------------------------------------------------------
This endpoint allows you to paginate through all identified users in your organization.
### Optional attributes
* Name
`page`
Type
string
Description
Page number to fetch. (Default: 1)
* Name
`limit`
Type
string
Description
Number of users to fetch per page. (Default: 10)
* Name
`sortBy`
Type
string
Description
Field to sort by. (Allowed values: "topPosters", "topCommenters", "lastActivity". Default: "lastActivity")
* Name
`q`
Type
string
Description
Query string to search for users by name or email.
* Name
`segment`
Type
string
Description
Segment to filter users by. Example: "Paid Users". Learn more here: [https://help.featurebase.app/en/articles/8031451-user-segmentation](https://help.featurebase.app/en/articles/8031451-user-segmentation)
### Request
cURLNode.jsPython
GET
/v2/organization/identifyUser/query
curl -G https://do.featurebase.app/v2/organization/identifyUser/query?page=1&limit=2&sortBy=lastActivity \
-H "X-API-Key: {token}"
CopyCopied!
### Response
{
"success": true,
"results": [\
{\
"_id": "65f8827aeed085186898aa11",\
"organization": "yourorganizationsubdomain",\
"userId": "123456789",\
"companies": [\
{\
"id": "23",\
"name": "Business Inc.",\
"monthlySpend": 1000,\
"customFields": {\
"Location": "Canada"\
},\
"createdAt": "2023-05-18T16:15:05.574Z"\
},\
{\
"id": "43",\
"name": "Second company",\
"monthlySpend": 1900,\
"customFields": {\
"Location": "Tallinn"\
},\
"createdAt": "2023-05-18T16:15:05.574Z"\
}\
],\
"email": "user_one@example.com",\
"name": "User One",\
"profilePicture": "https://fb-usercontent.fra1.cdn.digitaloceanspaces.com/fallback-8d359061-f581-4a88-8d04-afeed7a92b8d.png",\
"commentsCreated": 3,\
"postsCreated": 0,\
"lastActivity": "2024-03-21T13:59:47.595Z",\
"createdAt": "2024-03-18T18:05:46.977Z",\
"updatedAt": "2024-03-21T13:59:47.673Z",\
"__v": 0\
},\
{\
"_id": "65955983372a181bcfae1941",\
"organization": "yourorganizationsubdomain",\
"__v": 0,\
"companies": [\
{\
"id": "23",\
"name": "Business Inc.",\
"monthlySpend": 1000,\
"customFields": {\
"Location": "Canada"\
},\
"createdAt": "2023-05-18T16:15:05.574Z"\
},\
{\
"id": "43",\
"name": "Second company",\
"monthlySpend": 1900,\
"customFields": {\
"Location": "Tallinn"\
},\
"createdAt": "2023-05-18T16:15:05.574Z"\
}\
],\
"createdAt": "2024-01-03T12:56:35.559Z",\
"email": "user_two@example.com",\
"lastActivity": "2024-03-21T12:53:56.512Z",\
"name": "User Two",\
"postsCreated": 19,\
"commentsCreated": 54,\
"profilePicture": "https://fb-usercontent.fra1.cdn.digitaloceanspaces.com/1693132126228.jpg",\
"updatedAt": "2024-03-21T12:53:56.631Z"\
}\
],
"page": 1,
"limit": 2,
"totalResults": 37
}
CopyCopied!
* * *
POST/v2/organization/identifyUser
[Identify user](/identify#identify-user)
-----------------------------------------
This endpoint allows you to add additional data to your users in Featurebase. Add your own customer id, custom fields, companies, MRR they provide to get the best overview.
When your users data changes, you can update it using the same endpoint. We will automatically update the data in Featurebase.
### Required attributes
* Name
`email`
Type
string
Description
Email of the user to be identified. Either email or userId is required.
* Name
`userId`
Type
string
Description
ID of the user to be identifed. Either email or userId is required.
* Name
`name`
Type
string
Description
Name of the user to be identified.
### Optional attributes
* Name
`profilePicture`
Type
string
Description
URL of the users profile picture.
* Name
`subscribedToChangelog`
Type
boolean
Description
Whether the user is subscribed to receive emails when you publish a changelog.
* Name
`companies`
Type
Company\[\]
Description
Array of companies this user is associated with. Refer to [the company model](/identify#the-company-model)
for more information here.
* Name
`customFields`
Type
object
Description
Object containing key-value pairs of custom fields.
* Name
`createdAt`
Type
date
Description
Date when the user was created.
* Name
`roles`
Type
string\[\]
Description
Assign this user to roles. Refer to [the role model](/roles)
for more information here.
* Name
`locale`
Type
string
Description
The user's preferred language code (e.g., "en" for English). This ensures the user receives changelog emails in the correct language.
### Request
cURLNode.jsPython
POST
/v2/organization/identifyUser
curl -X 'POST' 'https://do.featurebase.app/v2/organization/identifyUser' \
-H 'X-API-Key: {token}' \
-H 'Content-Type: application/json' \
-d '{
"email": "youruser@example.com",
"name": "John Steezy",
"userId": "123456789",
"subscribedToChangelog": true,
"profilePicture": "https://example.com/profile.jpg",
"createdAt": "2023-05-19T15:35:49.915Z",
"roles": ["Paid Member"],
"customFields": {
"title": "Product Manager",
"plan": "Premium"
},
"locale": "en",
"companies": [\
{\
"id": "987654321",\
"name": "Business Inc.",\
"monthlySpend": 500,\
"createdAt": "2023-05-19T15:35:49.915Z",\
"customFields": {\
"location": "Canada",\
"language": "French"\
}\
}\
]
}'
CopyCopied!
### Response
{
"success": true
}
CopyCopied!
* * *
DELETE/v2/organization/deleteUser
[Delete user](/identify#delete-user)
-------------------------------------
This endpoint allows you to delete a user from your organization. This will remove all data associated with this user from your Featurebase account.
### Required attributes
* Name
`email`
Type
string
Description
Email of the user. Required if userId is not provided.
* Name
`userId`
Type
string
Description
ID of the user in your own system. Required if email is not provided.
### Request
cURLNode.jsPython
DELETE
/v2/organization/deleteUser
# Delete by email
curl -X 'DELETE' 'https://do.featurebase.app/v2/organization/deleteUser' \
-H 'X-API-Key: {token}' \
-H 'Content-Type: application/json' \
-d '{
"email": "youruser@example.com"
}'
# Or delete by userId
curl -X 'DELETE' 'https://do.featurebase.app/v2/organization/deleteUser' \
-H 'X-API-Key: {token}' \
-H 'Content-Type: 'application/json' \
-d '{
"userId": "123456789"
}'
CopyCopied!
### Response
{
"success": true,
}
CopyCopied!
---
# Help Centers - Featurebase API Reference
Help Centers
============
Help centers are essential for providing users with accessible support and documentation. On this page, we'll explore the various help center endpoints you can use to manage them programmatically. We'll cover creating, updating, and retrieving help center collections and articles.
[The Help Center Model](/help-center#the-help-center-model)
------------------------------------------------------------
The Help Center model contains all the information about a help center, such as its title, description, navigation items, and more. It has the following properties:
### Properties
* Name
`helpCenterId`
Type
string
Description
The help center's unique ID.
* Name
`displayName`
Type
string
Description
The display name of the help center. Usually your company name like "Featurebase".
* Name
`title`
Type
string
Description
The title of the help center. Something like "How can we help you?" or "YourCompany Help Center".
* Name
`description`
Type
string
Description
The description of the help center.
* Name
`navItems`
Type
object\[\]
Description
An array of navigation items for the help center.
* Name
`isPublic`
Type
boolean
Description
Indicates whether the help center is public.
* Name
`organizationId`
Type
string
Description
The ID of the organization that the help center belongs to.
* Name
`defaultLocale`
Type
string
Description
The default locale of the help center.
* Name
`locale`
Type
string
Description
The locale of the help center.
* Name
`availableLocales`
Type
string\[\]
Description
An array of available locales for the help center.
* Name
`createdAt`
Type
Date
Description
The date when the help center was created.
* Name
`updatedAt`
Type
Date
Description
The date when the help center was last updated.
* * *
GET/v2/help\_center/help\_centers
[Get Help Centers](/help-center#get-help-centers)
--------------------------------------------------
This endpoint allows you to retrieve a list of all your help centers. Currently, Featurebase only supports one help center per organization, but we plan on supporting multiple help centers in the future.
### Request
cURLNode.jsPython
GET
/v2/help\_center/help\_centers
curl -G https://do.featurebase.app/v2/help_center/help_centers \
-H "X-API-Key: {token}"
CopyCopied!
### Response
{
"success": true,
"results": [\
{\
"urls": {\
"featurebaseSubpath": "/help"\
},\
"helpCenterId": "2tgy0ig982j54qfl",\
"navItems": [\
{\
"type": "link",\
"title": "Developer Docs",\
"url": "https://developers.featurebase.app/install",\
"icon": null\
},\
{\
"type": "link",\
"title": "API",\
"url": "https://docs.featurebase.app/",\
"icon": null\
}\
],\
"isPublic": false,\
"organizationId": "6595518396205e06b897ad65",\
"defaultLocale": "en",\
"createdAt": "2024-06-26T13:27:21.920Z",\
"updatedAt": "2024-06-26T13:52:19.415Z",\
"__v": 0,\
"displayName": "Your Help Center",\
"locale": "en",\
"availableLocales": [\
"en"\
]\
}\
]
}
CopyCopied!
* * *
GET/v2/help\_center/help\_centers/:helpCenterId
[Get a Single Help Center](/help-center#get-a-single-help-center)
------------------------------------------------------------------
This endpoint allows you to retrieve a specific help center by its ID.
### Request
cURLNode.jsPython
GET
/v2/help\_center/help\_centers/:helpCenterId
curl -G https://do.featurebase.app/v2/help_center/help_centers/{helpCenterId} \
-H "X-API-Key: {token}"
CopyCopied!
### Response
{
"helpCenterId": "j7c5g8ah3ewxp4lo",
"navItems": [],
"isPublic": true,
"organizationId": "6595518396205e06b897ad65",
"defaultLocale": "en",
"createdAt": "2024-06-26T14:06:52.434Z",
"updatedAt": "2024-10-08T12:41:33.945Z",
"__v": 0,
"title": "Your Help Center",
"description": "",
"searchPlaceholder": "",
"locale": "en",
"availableLocales": [\
"en"\
],
"urls": {
"featurebaseSubpath": "/help"
}
}
CopyCopied!
* * *
[The Collection Model](/help-center#the-collection-model)
----------------------------------------------------------
Collections are sections of your help center that contain articles. Collections are nested and can be used to organize articles into a hierarchy by the parentId property.
### Properties
* Name
`collectionId`
Type
string
Description
The collection's unique ID.
* Name
`name`
Type
string
Description
The name of the collection.
* Name
`description`
Type
string
Description
A description of the collection.
* Name
`icon`
Type
object
Description
An object representing the collection's icon.
* Name
`parentId`
Type
string
Description
The ID of the parent collection, if the collection is nested.
* Name
`helpCenterId`
Type
string
Description
The ID of the help center this collection belongs to.
* Name
`organizationId`
Type
string
Description
The ID of the organization that the collection belongs to.
* Name
`defaultLocale`
Type
string
Description
The default locale of the collection.
* Name
`translations`
Type
object
Description
A dictionary of translations for different locales.
* Name
`order`
Type
integer
Description
The order of the collection in listings.
* Name
`type`
Type
string
Description
The type of the document, which is "collection".
* Name
`path`
Type
string
Description
The path to the collection within the help center hierarchy.
* Name
`slug`
Type
string
Description
The URL-friendly slug of the collection.
* Name
`featurebaseUrl`
Type
string
Description
The Featurebase URL for the collection.
* Name
`externalUrl`
Type
string
Description
The custom domain URL for the collection.
* Name
`locale`
Type
string
Description
The locale of the collection.
* Name
`availableLocales`
Type
string\[\]
Description
An array of available locales for the collection.
* * *
GET/v2/help\_center/collections
[List Collections](/help-center#list-collections)
--------------------------------------------------
This endpoint allows you to retrieve a paginated list of collections within your help centers.
### Query Parameters
* Name
`page`
Type
integer
Description
Page number. Default is 1.
* Name
`limit`
Type
integer
Description
Number of results per page. Maximum is 100. Default is 10.
### Request
cURLNode.jsPython
GET
/v2/help\_center/collections
curl -G https://do.featurebase.app/v2/help_center/collections \
-H "X-API-Key: {token}" \
--data-urlencode "page=1" \
--data-urlencode "limit=10"
CopyCopied!
### Response
{
"success": true,
"results": [\
{\
"collectionId": "6474684",\
"icon": null,\
"authorCount": 0,\
"articleCount": 0,\
"parentId": null,\
"helpCenterId": "j7c5g8ah3ewxp4lo",\
"organizationId": "6595518396205e06b897ad65",\
"defaultLocale": "en",\
"translations": {\
"de": {\
"name": "German Collection Name",\
"description": "Eine Beschreibung auf Deutsch",\
"slug": "6474684-deutsche-version",\
"featurebaseUrl": "https://yourorg.featurebase.app/de/help/collections/6474684-deutsche-version",\
"articleCount": 10,\
"authorCount": 2,\
"externalUrl": "https://help.yourdomain.com/de/collections/6474684-deutsche-version"\
},\
"en": {\
"name": "English Collection Name",\
"description": "A description in English",\
"slug": "6474684-english-version",\
"featurebaseUrl": "https://yourorg.featurebase.app/en/help/collections/6474684-english-version",\
"articleCount": 15,\
"authorCount": 3,\
"externalUrl": "https://help.yourdomain.com/en/collections/6474684-english-version"\
}\
},\
"order": null,\
"type": "collection",\
"path": "j7c5g8ah3ewxp4lo",\
"docCreatedAt": "2024-10-18T12:33:09.099Z",\
"docUpdatedAt": "2024-10-18T13:03:25.921Z",\
"__v": 0,\
"slug": "6474684-english-version",\
"name": "English Collection Name",\
"description": "A description in English",\
"featurebaseUrl": "https://yourorg.featurebase.app/en/help/collections/6474684-english-version",\
"externalUrl": "https://help.yourdomain.com/en/collections/6474684-english-version",\
"locale": "en",\
"availableLocales": [\
"de",\
"en"\
]\
},\
{\
"collectionId": "7013224",\
"icon": null,\
"authorCount": 0,\
"articleCount": 0,\
"parentId": null,\
"helpCenterId": "j7c5g8ah3ewxp4lo",\
"organizationId": "6595518396205e06b897ad65",\
"defaultLocale": "de",\
"translations": {\
"de": {\
"name": "Meine Sammlung",\
"description": "Eine andere Beschreibung",\
"slug": "7013224-meine-sammlung",\
"featurebaseUrl": "https://yourorg.featurebase.app/de/help/collections/7013224-meine-sammlung",\
"articleCount": 5,\
"authorCount": 1,\
"authors": ["Hans Müller"],\
"externalUrl": "https://help.yourdomain.com/de/collections/7013224-meine-sammlung"\
},\
"en": {\
"name": "My Collection",\
"description": "Another description in English",\
"slug": "7013224-my-collection",\
"featurebaseUrl": "https://yourorg.featurebase.app/en/help/collections/7013224-my-collection",\
"articleCount": 8,\
"authorCount": 1,\
"authors": ["John Doe"],\
"externalUrl": "https://help.yourdomain.com/en/collections/7013224-my-collection"\
}\
},\
"order": 1,\
"type": "collection",\
"path": "j7c5g8ah3ewxp4lo",\
"docCreatedAt": "2024-10-18T12:32:44.143Z",\
"docUpdatedAt": "2024-10-18T12:33:09.208Z",\
"__v": 0,\
"slug": "7013224-my-collection",\
"name": "My Collection",\
"description": "Another description in English",\
"featurebaseUrl": "https://yourorg.featurebase.app/en/help/collections/7013224-my-collection",\
"externalUrl": "https://help.yourdomain.com/en/collections/7013224-my-collection",\
"locale": "en",\
"availableLocales": [\
"de",\
"en"\
]\
}\
],
"totalResults": 2,
"page": 1,
"limit": 10
}
CopyCopied!
* * *
GET/v2/help\_center/collections/:collectionId
[Get Collection by ID](/help-center#get-collection-by-id)
----------------------------------------------------------
Retrieve a specific collection by its ID.
### Request
cURLNode.jsPython
GET
/v2/help\_center/collections/:collectionId
curl -G https://do.featurebase.app/v2/help_center/collections/{collectionId} \
-H "X-API-Key: {token}"
CopyCopied!
### Response
{
"collectionId": "3416135",
"icon": {
"type": "emoji",
"value": "🥾"
},
"authorCount": 0,
"articleCount": 0,
"parentId": null,
"helpCenterId": "j7c5g8ah3ewxp4lo",
"organizationId": "6595518396205e06b897ad65",
"defaultLocale": "en",
"translations": {
"de": {
"name": "Deutschsprachige Sammlung",
"description": "Dies ist eine Sammlung von Artikeln auf Deutsch.",
"slug": "3416135-deutschsprachige-sammlung",
"featurebaseUrl": "https://yourorg.featurebase.app/de/help/collections/3416135-deutschsprachige-sammlung",
"externalUrl": "https://feedback.mydomain.com/de/collections/3416135-deutschsprachige-sammlung"
},
"en": {
"name": "English Collection",
"description": "This is a collection of articles in English.",
"slug": "3416135-english-collection",
"featurebaseUrl": "https://yourorg.featurebase.app/en/help/collections/3416135-english-collection",
"externalUrl": "https://feedback.mydomain.com/en/collections/3416135-english-collection"
}
},
"type": "collection",
"path": "j7c5g8ah3ewxp4lo",
"docCreatedAt": "2024-09-13T17:51:36.252Z",
"docUpdatedAt": "2024-10-18T12:24:37.289Z",
"__v": 0,
"order": 3,
"slug": "3416135-english-collection",
"name": "English Collection",
"description": "This is a collection of articles in English.",
"featurebaseUrl": "https://yourorg.featurebase.app/en/help/collections/3416135-english-collection",
"externalUrl": "https://feedback.mydomain.com/en/collections/3416135-english-collection",
"locale": "en",
"availableLocales": [\
"de",\
"en"\
]
}
CopyCopied!
* * *
POST/v2/help\_center/collections
[Create Collection](/help-center#create-collection)
----------------------------------------------------
This endpoint allows you to create a new collection.
### Required Attributes
* Name
`name`
Type
string
Description
The name of the collection.
### Optional Attributes
* Name
`description`
Type
string
Description
A description of the collection.
* Name
`icon`
Type
object
Description
An icon object representing the collection icon.
* Name
`parentId`
Type
string
Description
The ID of the parent collection, if any.
* Name
`translations`
Type
object
Description
A dictionary of translations keyed by locale.
### Request
cURLNode.jsPython
POST
/v2/help\_center/collections
curl -X 'POST' 'https://do.featurebase.app/v2/help_center/collections' \
-H 'X-API-Key: {token}' \
-H 'Content-Type: application/json' \
-d '{
"name": "English Collection",
"description": "This is a collection of articles in English.",
"icon": {
"type": "emoji",
"value": "📚"
}
}'
CopyCopied!
### Response
{
"collectionId": "3416135",
"icon": {
"type": "emoji",
"value": "📚"
},
"authorCount": 0,
"articleCount": 0,
"parentId": null,
"helpCenterId": "j7c5g8ah3ewxp4lo",
"organizationId": "6595518396205e06b897ad65",
"defaultLocale": "en",
"translations": {
"de": {
"name": "Deutschsprachige Sammlung",
"description": "Dies ist eine Sammlung von Artikeln auf Deutsch.",
"slug": "3416135-deutschsprachige-sammlung",
"featurebaseUrl": "https://yourorg.featurebase.app/de/help/collections/3416135-deutschsprachige-sammlung",
"externalUrl": "https://feedback.mydomain.com/de/collections/3416135-deutschsprachige-sammlung"
},
"en": {
"name": "English Collection",
"description": "This is a collection of articles in English.",
"slug": "3416135-english-collection",
"featurebaseUrl": "https://yourorg.featurebase.app/en/help/collections/3416135-english-collection",
"externalUrl": "https://feedback.mydomain.com/en/collections/3416135-english-collection"
}
},
"type": "collection",
"path": "j7c5g8ah3ewxp4lo",
"docCreatedAt": "2024-09-13T17:51:36.252Z",
"docUpdatedAt": "2024-10-18T12:24:37.289Z",
"__v": 0,
"order": 3,
"slug": "3416135-english-collection",
"name": "English Collection",
"description": "This is a collection of articles in English.",
"featurebaseUrl": "https://yourorg.featurebase.app/en/help/collections/3416135-english-collection",
"externalUrl": "https://feedback.mydomain.com/en/collections/3416135-english-collection",
"locale": "en",
"availableLocales": [\
"de",\
"en"\
]
}
CopyCopied!
* * *
PATCH/v2/help\_center/collections/:collectionId
[Update Collection](/help-center#update-collection)
----------------------------------------------------
This endpoint allows you to update an existing collection. Only include the fields you wish to update.
### Required Parameters
* Name
`collectionId`
Type
string
Description
The ID of the collection to update.
### Optional Attributes
* Name
`name`
Type
string
Description
The new name of the collection.
* Name
`description`
Type
string
Description
The new description of the collection.
* Name
`icon`
Type
object
Description
An updated icon object for the collection.
* Name
`parentId`
Type
string
Description
The new parent collection ID, if applicable.
* Name
`translations`
Type
object
Description
A dictionary of updated translations keyed by locale.
### Request
cURLNode.jsPython
PATCH
/v2/help\_center/collections/:collectionId
curl -X 'PATCH' 'https://do.featurebase.app/v2/help_center/collections/{collectionId}' \
-H 'X-API-Key: {token}' \
-H 'Content-Type: application/json' \
-d '{
"name": "Updated Collection",
"description": "Updated description in English."
}'
CopyCopied!
### Response
{
"collectionId": "3416135",
"icon": {
"type": "emoji",
"value": "📝"
},
"authorCount": 0,
"articleCount": 0,
"parentId": null,
"helpCenterId": "j7c5g8ah3ewxp4lo",
"organizationId": "6595518396205e06b897ad65",
"defaultLocale": "en",
"translations": {
"de": {
"name": "Deutschsprachige Sammlung",
"description": "Dies ist eine Sammlung von Artikeln auf Deutsch.",
"slug": "3416135-deutschsprachige-sammlung",
"featurebaseUrl": "https://yourorg.featurebase.app/de/help/collections/3416135-deutschsprachige-sammlung",
"externalUrl": "https://feedback.mydomain.com/de/collections/3416135-deutschsprachige-sammlung"
},
"en": {
"name": "Updated Collection",
"description": "Updated description in English.",
"slug": "3416135-updated-collection",
"featurebaseUrl": "https://yourorg.featurebase.app/en/help/collections/3416135-updated-collection",
"externalUrl": "https://feedback.mydomain.com/en/collections/3416135-updated-collection"
}
},
"type": "collection",
"path": "j7c5g8ah3ewxp4lo",
"docCreatedAt": "2024-09-13T17:51:36.252Z",
"docUpdatedAt": "2024-10-18T12:24:37.289Z",
"__v": 0,
"order": 3,
"slug": "3416135-updated-collection",
"name": "Updated Collection",
"description": "Updated description in English.",
"featurebaseUrl": "https://yourorg.featurebase.app/en/help/collections/3416135-updated-collection",
"externalUrl": "https://feedback.mydomain.com/en/collections/3416135-updated-collection",
"locale": "en",
"availableLocales": [\
"de",\
"en"\
]
}
CopyCopied!
* * *
DELETE/v2/help\_center/collections/:collectionId
[Delete Collection](/help-center#delete-collection)
----------------------------------------------------
This endpoint allows you to delete a collection.
### Required Parameters
* Name
`collectionId`
Type
string
Description
The ID of the collection to delete.
### Request
cURLNode.jsPython
DELETE
/v2/help\_center/collections/:collectionId
curl -X 'DELETE' 'https://do.featurebase.app/v2/help_center/collections/{collectionId}' \
-H 'X-API-Key: {token}'
CopyCopied!
### Response
// No content returned; HTTP Status Code: 204 No Content
CopyCopied!
* * *
[The Article Model](/help-center#the-article-model)
----------------------------------------------------
The Article model contains all the information about an article, such as its title, description, body content, and translations. It has the following properties:
### Properties
* Name
`articleId`
Type
string
Description
The article's unique ID.
* Name
`title`
Type
string
Description
The title of the article.
* Name
`description`
Type
string
Description
A brief description of the article.
* Name
`body`
Type
string
Description
The HTML content of the article.
* Name
`icon`
Type
object
Description
An object representing the article's icon.
* Name
`parentId`
Type
string
Description
The ID of the parent collection, if any.
* Name
`helpCenterId`
Type
string
Description
The ID of the help center this article belongs to.
* Name
`organizationId`
Type
string
Description
The ID of the organization that the article belongs to.
* Name
`state`
Type
string
Description
The state of the article, either "live" or "draft".
* Name
`locale`
Type
string
Description
The locale of the article.
* Name
`translations`
Type
object
Description
A dictionary of translations for different locales.
* Name
`createdAt`
Type
Date
Description
The date when the article was created.
* Name
`updatedAt`
Type
Date
Description
The date when the article was last updated.
* Name
`author`
Type
object
Description
An object containing information about the author of the article.
* Name
`slug`
Type
string
Description
The URL-friendly slug of the article.
* Name
`featurebaseUrl`
Type
string
Description
The Featurebase URL for the article.
* Name
`externalUrl`
Type
string
Description
The external URL for the article.
* Name
`isDraftDiffersFromLive`
Type
boolean
Description
Indicates whether the draft version differs from the live published version.
* Name
`isPublished`
Type
boolean
Description
Indicates whether the article is published.
* Name
`availableLocales`
Type
string\[\]
Description
An array of available locales for the article.
* Name
`publishedLocales`
Type
string\[\]
Description
An array of locales in which the article is published.
* * *
GET/v2/help\_center/articles
[Get Articles](/help-center#get-articles)
------------------------------------------
This endpoint allows you to retrieve a paginated list of articles in your help center.
### Query Parameters
* Name
`state`
Type
string
Description
Filter articles by state. Can be "live" or "draft".
* Name
`page`
Type
integer
Description
Page number. Default is 1.
* Name
`limit`
Type
integer
Description
Number of results per page. Maximum is 100. Default is 10.
* Name
`parentId`
Type
string
Description
Get articles from a specific collection.
### Request
cURLNode.jsPython
GET
/v2/help\_center/articles
curl -G https://do.featurebase.app/v2/help_center/articles \
-H "X-API-Key: {token}" \
--data-urlencode "state=live" \
--data-urlencode "page=1" \
--data-urlencode "limit=10"
CopyCopied!
### Response
{
"results": [\
{\
"organizationId": "6595518396205e06b897ad65",\
"helpCenterId": "j7c5g8ah3ewxp4lo",\
"articleId": "2067523",\
"icon": null,\
"translations": {\
"en": {\
"title": "Test Article",\
"description": "This is a placeholder for an English test article.",\
"body": "This article is currently empty.
",\
"slug": "2067523-test-article",\
"featurebaseUrl": "https://yourorg.featurebase.app/en/help/articles/2067523-test-article",\
"externalUrl": "https://help.yourdomain.com/en/articles/2067523-test-article",\
"createdAt": "2024-10-16T11:29:11.208Z",\
"updatedAt": "2024-10-16T11:29:20.318Z",\
"author": {\
"name": "Bruno from Featurebase",\
"authorId": "5febde0bdc56d60012d47db5",\
"avatarUrl": "https://fb-usercontent.fra1.cdn.digitaloceanspaces.com/878ab937-3862-4491-ba5c-4a65113a3765.png"\
}\
},\
"de": {\
"title": "Dokument ohne Titel",\
"description": "Dies ist ein Platzhalter für einen Artikel ohne Inhalt.",\
"body": "Der Artikel ist derzeit leer.
",\
"slug": "2067523-dokument-ohne-titel",\
"featurebaseUrl": "https://yourorg.featurebase.app/de/help/articles/2067523-dokument-ohne-titel",\
"externalUrl": "https://help.yourdomain.com/de/articles/2067523-dokument-ohne-titel",\
"createdAt": "2024-10-16T11:29:03.852Z",\
"updatedAt": "2024-10-16T11:29:13.499Z",\
"author": {\
"name": "Bruno from Featurebase",\
"authorId": "5febde0bdc56d60012d47db5",\
"avatarUrl": "https://fb-usercontent.fra1.cdn.digitaloceanspaces.com/878ab937-3862-4491-ba5c-4a65113a3765.png"\
}\
}\
},\
"parentId": "2037123",\
"type": "article",\
"path": "j7c5g8ah3ewxp4lo/2037123",\
"docCreatedAt": "2024-10-16T11:29:03.914Z",\
"docUpdatedAt": "2024-10-16T11:29:20.318Z",\
"__v": 0,\
"slug": "2067523-test-article",\
"title": "Test Article",\
"description": "This is a placeholder for an English test article.",\
"body": "This article is currently empty.
",\
"featurebaseUrl": "https://yourorg.featurebase.app/en/help/articles/2067523-test-article",\
"externalUrl": "https://help.yourdomain.com/en/articles/2067523-test-article",\
"createdAt": "2024-10-16T11:29:11.208Z",\
"updatedAt": "2024-10-16T11:29:20.318Z",\
"author": {\
"name": "Bruno from Featurebase",\
"authorId": "5febde0bdc56d60012d47db5",\
"avatarUrl": "https://fb-usercontent.fra1.cdn.digitaloceanspaces.com/878ab937-3862-4491-ba5c-4a65113a3765.png"\
},\
"state": "live",\
"locale": "en",\
"isDraftDiffersFromLive": false,\
"isPublished": true,\
"availableLocales": [\
"en",\
"de"\
],\
"publishedLocales": [\
"en",\
"de"\
]\
},\
{\
"organizationId": "6595518396205e06b897ad65",\
"helpCenterId": "j7c5g8ah3ewxp4lo",\
"articleId": "6056746",\
"icon": null,\
"translations": {\
"en": {\
"title": "Sample Article",\
"description": "This is a sample English article.",\
"body": "Sample content for an English article.
",\
"slug": "6056746-sample-article",\
"featurebaseUrl": "https://yourorg.featurebase.app/en/help/articles/6056746-sample-article",\
"externalUrl": "https://help.yourdomain.com/en/articles/6056746-sample-article",\
"createdAt": "2024-09-16T13:14:51.841Z",\
"updatedAt": "2024-09-16T13:15:10.649Z",\
"author": {\
"name": "Bruno from Featurebase",\
"authorId": "5febde0bdc56d60012d47db5",\
"avatarUrl": "https://fb-usercontent.fra1.cdn.digitaloceanspaces.com/878ab937-3862-4491-ba5c-4a65113a3765.png"\
}\
},\
"de": {\
"title": "Beispielartikel",\
"description": "Dies ist ein deutscher Testartikel.",\
"body": "Beispielinhalt für einen Artikel auf Deutsch.
",\
"slug": "6056746-beispielartikel",\
"featurebaseUrl": "https://yourorg.featurebase.app/de/help/articles/6056746-beispielartikel",\
"externalUrl": "https://help.yourdomain.com/de/articles/6056746-beispielartikel",\
"createdAt": "2024-09-16T13:14:50.755Z",\
"updatedAt": "2024-09-16T13:15:01.218Z",\
"author": {\
"name": "Bruno from Featurebase",\
"authorId": "5febde0bdc56d60012d47db5",\
"avatarUrl": "https://fb-usercontent.fra1.cdn.digitaloceanspaces.com/878ab937-3862-4491-ba5c-4a65113a3765.png"\
}\
}\
},\
"parentId": null,\
"type": "article",\
"path": "j7c5g8ah3ewxp4lo",\
"docCreatedAt": "2024-09-16T13:14:50.757Z",\
"docUpdatedAt": "2024-10-10T17:24:22.419Z",\
"__v": 0,\
"surveyId": "67080dc6ed2a5a03d2809365",\
"slug": "6056746-sample-article",\
"title": "Sample Article",\
"description": "This is a sample English article.",\
"body": "Sample content for an English article.
",\
"featurebaseUrl": "https://yourorg.featurebase.app/en/help/articles/6056746-sample-article",\
"externalUrl": "https://help.yourdomain.com/en/articles/6056746-sample-article",\
"createdAt": "2024-09-16T13:14:51.841Z",\
"updatedAt": "2024-09-16T13:15:10.649Z",\
"author": {\
"name": "Bruno from Featurebase",\
"authorId": "5febde0bdc56d60012d47db5",\
"avatarUrl": "https://fb-usercontent.fra1.cdn.digitaloceanspaces.com/878ab937-3862-4491-ba5c-4a65113a3765.png"\
},\
"state": "live",\
"locale": "en",\
"isDraftDiffersFromLive": false,\
"isPublished": true,\
"availableLocales": [\
"en",\
"de"\
],\
"publishedLocales": [\
"en",\
"de"\
]\
}\
],
"totalResults": 2,
"page": 1,
"limit": 10
}
CopyCopied!
* * *
GET/v2/help\_center/articles/:articleId
[Get Article by ID](/help-center#get-article-by-id)
----------------------------------------------------
Retrieve a specific article by its ID.
### Request
cURLNode.jsPython
GET
/v2/help\_center/articles/:articleId
curl -G https://do.featurebase.app/v2/help_center/articles/{articleId} \
-H "X-API-Key: {token}"
CopyCopied!
### Response
{
"_id": "670fa37f367156b9a5b01bbb",
"organizationId": "6595518396205e06b897ad65",
"helpCenterId": "j7c5g8ah3ewxp4lo",
"articleId": "2067523",
"icon": null,
"translations": {
"en": {
"title": "Test Article",
"description": "This is a placeholder for an English test article.",
"body": "This article is currently empty.
",
"slug": "2067523-test-article",
"featurebaseUrl": "https://yourorg.featurebase.app/en/help/articles/2067523-test-article",
"externalUrl": "https://help.yourdomain.com/en/articles/2067523-test-article",
"createdAt": "2024-10-16T11:29:11.208Z",
"updatedAt": "2024-10-16T11:29:20.318Z",
"author": {
"name": "Bruno from Featurebase",
"authorId": "5febde0bdc56d60012d47db5",
"avatarUrl": "https://fb-usercontent.fra1.cdn.digitaloceanspaces.com/878ab937-3862-4491-ba5c-4a65113a3765.png"
}
},
"de": {
"title": "Dokument ohne Titel",
"description": "Dies ist ein Platzhalter für einen Artikel ohne Inhalt.",
"body": "Der Artikel ist derzeit leer.
",
"slug": "2067523-dokument-ohne-titel",
"featurebaseUrl": "https://yourorg.featurebase.app/de/help/articles/2067523-dokument-ohne-titel",
"externalUrl": "https://help.yourdomain.com/de/articles/2067523-dokument-ohne-titel",
"createdAt": "2024-10-16T11:29:03.852Z",
"updatedAt": "2024-10-16T11:29:13.499Z",
"author": {
"name": "Bruno from Featurebase",
"authorId": "5febde0bdc56d60012d47db5",
"avatarUrl": "https://fb-usercontent.fra1.cdn.digitaloceanspaces.com/878ab937-3862-4491-ba5c-4a65113a3765.png"
}
}
},
"parentId": "2037123",
"type": "article",
"path": "j7c5g8ah3ewxp4lo/2037123",
"docCreatedAt": "2024-10-16T11:29:03.914Z",
"docUpdatedAt": "2024-10-16T11:29:20.318Z",
"__v": 0,
"slug": "2067523-test-article",
"title": "Test Article",
"description": "This is a placeholder for an English test article.",
"body": "This article is currently empty.
",
"featurebaseUrl": "https://yourorg.featurebase.app/en/help/articles/2067523-test-article",
"externalUrl": "https://help.yourdomain.com/en/articles/2067523-test-article",
"createdAt": "2024-10-16T11:29:11.208Z",
"updatedAt": "2024-10-16T11:29:20.318Z",
"author": {
"name": "Bruno from Featurebase",
"authorId": "5febde0bdc56d60012d47db5",
"avatarUrl": "https://fb-usercontent.fra1.cdn.digitaloceanspaces.com/878ab937-3862-4491-ba5c-4a65113a3765.png"
},
"state": "live",
"locale": "en",
"isDraftDiffersFromLive": false,
"isPublished": true,
"availableLocales": [\
"en",\
"de"\
],
"publishedLocales": [\
"en",\
"de"\
]
}
CopyCopied!
* * *
POST/v2/help\_center/articles
[Create Article](/help-center#create-article)
----------------------------------------------
This endpoint allows you to create a new article.
### Required Attributes
* Name
`title`
Type
string
Description
The title of the article.
### Optional Attributes
* Name
`description`
Type
string
Description
A brief description of the article.
* Name
`body`
Type
string
Description
The HTML content of the article.
* Name
`formatter`
Type
string
Description
The formatter of the article. Can be "default" or "ai". The AI formatter is currently in beta and will convert any markdown/html content to the Featurebase format. The response times may be slow and the output is not guaranteed to be perfect. Learn more about importing help center articles [here](https://help.featurebase.app)
.
* Name
`parentId`
Type
string
Description
The ID of the parent collection, if any.
* Name
`icon`
Type
object
Description
An icon object representing the article icon.
* Name
`state`
Type
string
Description
The state of the article, either "live" or "draft". Defaults to "draft".
* Name
`translations`
Type
object
Description
A dictionary of translations keyed by locale.
### Request
cURLNode.jsPython
POST
/v2/help\_center/articles
curl -X 'POST' 'https://do.featurebase.app/v2/help_center/articles' \
-H 'X-API-Key: {token}' \
-H 'Content-Type: application/json' \
-d '{
"title": "New Article",
"description": "An article about new features.",
"body": "Content of the article.
",
"state": "draft"
}'
CopyCopied!
### Response
{
"organizationId": "6595518396205e06b897ad65",
"helpCenterId": "j7c5g8ah3ewxp4lo",
"articleId": "7890123",
"icon": null,
"translations": {
"en": {
"title": "New Article",
"description": "An article about new features.",
"body": "Content of the article.
",
"slug": "7890123-new-article",
"featurebaseUrl": "https://yourorg.featurebase.app/en/help/articles/7890123-new-article",
"externalUrl": "https://help.yourdomain.com/en/articles/7890123-new-article",
"createdAt": "2024-10-18T12:00:00.000Z",
"updatedAt": "2024-10-18T12:00:00.000Z",
"author": {
"name": "Your Name",
"authorId": "5febde0bdc56d60012d47db5",
"avatarUrl": "https://your-avatar-url.com/avatar.png"
}
},
"de": {
"title": "Neuer Artikel",
"description": "Ein Artikel über neue Funktionen.",
"body": "Inhalt des Artikels.
",
"slug": "7890123-neuer-artikel",
"featurebaseUrl": "https://yourorg.featurebase.app/de/help/articles/7890123-neuer-artikel",
"externalUrl": "https://help.yourdomain.com/de/articles/7890123-neuer-artikel",
"createdAt": "2024-10-18T12:00:00.000Z",
"updatedAt": "2024-10-18T12:00:00.000Z",
"author": {
"name": "Your Name",
"authorId": "5febde0bdc56d60012d47db5",
"avatarUrl": "https://your-avatar-url.com/avatar.png"
}
}
},
"parentId": null,
"type": "article",
"path": "j7c5g8ah3ewxp4lo",
"docCreatedAt": "2024-10-18T12:00:00.000Z",
"docUpdatedAt": "2024-10-18T12:00:00.000Z",
"__v": 0,
"slug": "7890123-new-article",
"title": "New Article",
"description": "An article about new features.",
"body": "Content of the article.
",
"featurebaseUrl": "https://yourorg.featurebase.app/en/help/articles/7890123-new-article",
"externalUrl": "https://help.yourdomain.com/en/articles/7890123-new-article",
"createdAt": "2024-10-18T12:00:00.000Z",
"updatedAt": "2024-10-18T12:00:00.000Z",
"author": {
"name": "Your Name",
"authorId": "5febde0bdc56d60012d47db5",
"avatarUrl": "https://your-avatar-url.com/avatar.png"
},
"state": "draft",
"locale": "en",
"isDraftDiffersFromLive": false,
"isPublished": false,
"availableLocales": [\
"en",\
"de"\
],
"publishedLocales": []
}
CopyCopied!
* * *
PATCH/v2/help\_center/articles/:articleId
[Update Article](/help-center#update-article)
----------------------------------------------
This endpoint allows you to update an existing article. Only include the fields you wish to update.
### Required Parameters
* Name
`articleId`
Type
string
Description
The ID of the article to update.
### Optional Attributes
* Name
`title`
Type
string
Description
The new title of the article.
* Name
`description`
Type
string
Description
The new description of the article.
* Name
`body`
Type
string
Description
The new HTML content of the article.
* Name
`icon`
Type
object
Description
An updated icon object for the article.
* Name
`parentId`
Type
string
Description
The new parent collection ID, if applicable.
* Name
`authorId`
Type
string
Description
The ID of the new author.
* Name
`state`
Type
string
Description
The new state of the article, either "live" or "draft". If set to "live", the article will be published immediately in the default locale & translations you provide.
* Name
`translations`
Type
object
Description
A dictionary of updated translations keyed by locale.
### Request
cURLNode.jsPython
PATCH
/v2/help\_center/articles/:articleId
curl -X 'PATCH' 'https://do.featurebase.app/v2/help_center/articles/{articleId}' \
-H 'X-API-Key: {token}' \
-H 'Content-Type: application/json' \
-d '{
"title": "Updated Article",
"state": "live"
}'
CopyCopied!
### Response
{
"organizationId": "6595518396205e06b897ad65",
"helpCenterId": "j7c5g8ah3ewxp4lo",
"articleId": "7890123",
"icon": null,
"translations": {
"en": {
"title": "Updated Article",
"description": "Updated description.",
"body": "Updated content of the article.
",
"slug": "7890123-updated-article",
"featurebaseUrl": "https://yourorg.featurebase.app/en/help/articles/7890123-updated-article",
"externalUrl": "https://help.yourdomain.com/en/articles/7890123-updated-article",
"createdAt": "2024-10-18T12:00:00.000Z",
"updatedAt": "2024-10-18T13:00:00.000Z",
"author": {
"name": "Your Name",
"authorId": "5febde0bdc56d60012d47db5",
"avatarUrl": "https://your-avatar-url.com/avatar.png"
}
}
},
"parentId": null,
"type": "article",
"path": "j7c5g8ah3ewxp4lo",
"docCreatedAt": "2024-10-18T12:00:00.000Z",
"docUpdatedAt": "2024-10-18T13:00:00.000Z",
"__v": 0,
"slug": "7890123-updated-article",
"title": "Updated Article",
"description": "Updated description.",
"body": "Updated content of the article.
",
"featurebaseUrl": "https://yourorg.featurebase.app/en/help/articles/7890123-updated-article",
"externalUrl": "https://help.yourdomain.com/en/articles/7890123-updated-article",
"createdAt": "2024-10-18T12:00:00.000Z",
"updatedAt": "2024-10-18T13:00:00.000Z",
"author": {
"name": "Your Name",
"authorId": "5febde0bdc56d60012d47db5",
"avatarUrl": "https://your-avatar-url.com/avatar.png"
},
"state": "live",
"locale": "en",
"isDraftDiffersFromLive": false,
"isPublished": true,
"availableLocales": [\
"en"\
],
"publishedLocales": [\
"en"\
]
}
CopyCopied!
* * *
DELETE/v2/help\_center/articles/:articleId
[Delete Article](/help-center#delete-article)
----------------------------------------------
This endpoint allows you to delete an article.
### Required Parameters
* Name
`articleId`
Type
string
Description
The ID of the article to delete.
### Request
cURLNode.jsPython
DELETE
/v2/help\_center/articles/:articleId
curl -X 'DELETE' 'https://do.featurebase.app/v2/help_center/articles/{articleId}' \
-H 'X-API-Key: {token}'
CopyCopied!
### Response
// No content returned; HTTP Status Code: 204 No Content
CopyCopied!
* * *
---
# 404: This page could not be found
404
===
This page could not be found.
-----------------------------
---