# 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. ----------------------------- ---