Features.Vote - Build profitable features from user feedback | Product Hunt

FeaturesVote API

The FeaturesVote API is a management API for administering your feature voting board. Use it to integrate with CI/CD pipelines, build internal tools, or connect AI assistants via MCP.

Admin use only — not for public-facing UIs
This API is designed for board management — creating features, managing releases, moderating comments, and viewing analytics. API keys carry full admin privileges for your project. Do not use this API in client-side code, public websites, or end-user applications. Exposing your API key in a frontend would give anyone full control over your board.

Base URL: https://features.vote/api


Authentication

All API requests require a valid API key sent in the Authorization header as a Bearer token.

curl https://features.vote/api/features \
  -H "Authorization: Bearer fv_live_xxxxxxxxxxxxx"

Getting an API key

  1. Go to your project Settings → API Keys
  2. Click "Create API Key"
  3. Copy the key — it is only shown once
  4. Requires a Growth or VIP subscription plan
Keys start with fv_live_ followed by 40 random characters. Each key is bound to a single project.
!Keep your API key secret
API keys carry full admin privileges for your project. Never expose them in client-side JavaScript, public repositories, or frontend code. This API is intended for server-side integrations, internal tools, and CI/CD pipelines only — not for public-facing UIs or end-user applications.

Rate Limits

PlanPer-Key LimitIP Rate Limit
Growth100 requests / minute10 writes / 2 min (edge)
VIP300 requests / minute10 writes / 2 min (edge)

Rate limit info is included in response headers: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset.


Response Format

Successful responses wrap data in a data field. Paginated endpoints include a meta field.

Success
{
  "data": { ... },
  "meta": { "page": 1, "limit": 50, "total": 123 }
}
Error
{
  "error": "error_code",
  "message": "Human-readable description"
}

Features

Create, read, update, and delete feature requests. Manage voters, merge duplicates, and link features to releases.

GET/api/features

List all features for the project. Supports filtering and pagination.

Parameters

status
Filter by status (Pending, Approved, In Progress, Done, Rejected)
tag
Filter by tag name
search
Search in title and description
page
Page number (default: 1)
limit
Items per page (default: 50, max: 100)

Example Request

curl "https://features.vote/api/features?status=Pending&limit=10" \
  -H "Authorization: Bearer fv_live_xxx"

Response

{
  "data": [
    {
      "id": "uuid",
      "title": "Add dark mode",
      "description": "...",
      "status": "Pending",
      "total_votes": 42,
      "tags": ["UI"],
      "created_at": "2024-01-01T00:00:00Z"
    }
  ],
  "meta": { "page": 1, "limit": 10, "total": 42 }
}
POST/api/features/create

Create a new feature.

Request Body

{
  "title": "Add dark mode",
  "description": "Support dark theme across the app",
  "status": "Pending",
  "tags": ["UI", "UX"]
}

Example Request

curl -X POST https://features.vote/api/features/create \
  -H "Authorization: Bearer fv_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{"title": "Add dark mode", "description": "...", "tags": ["UI"]}'

Response

{
  "data": {
    "id": "uuid",
    "title": "Add dark mode",
    "status": "Pending",
    "total_votes": 0
  }
}
GET/api/features?featureId={id}

Get a single feature by ID.

Example Request

curl "https://features.vote/api/features?featureId=FEATURE_ID" \
  -H "Authorization: Bearer fv_live_xxx"

Response

{
  "id": "...",
  "title": "...",
  "description": "...",
  "status": "Pending",
  "total_votes": 42,
  "tags": ["UI"]
}
PUT/api/features

Update a feature. Only provided fields are updated.

Request Body

{
  "id": "feature-uuid",
  "title": "Updated title",
  "description": "Updated description",
  "status": "Approved",
  "tags": ["UI", "Priority"]
}

Example Request

curl -X PUT https://features.vote/api/features \
  -H "Authorization: Bearer fv_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{"id": "FEATURE_ID", "status": "Approved"}'

Response

{
  "id": "...",
  "title": "...",
  "status": "Approved"
}
PUT/api/features?is_status_update=true

Update only the status of a feature. Triggers subscriber notifications.

Request Body

{
  "id": "feature-uuid",
  "status": "In Progress"
}

Example Request

curl -X PUT "https://features.vote/api/features?is_status_update=true" \
  -H "Authorization: Bearer fv_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{"id": "FEATURE_ID", "status": "In Progress"}'

Response

{
  "id": "...",
  "status": "In Progress"
}
DELETE/api/features

Delete a feature. Remove comments first if the feature has any.

Request Body

{ "id": "feature-uuid" }

Example Request

curl -X DELETE https://features.vote/api/features \
  -H "Authorization: Bearer fv_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{"id": "FEATURE_ID"}'

Response

null
GET/api/features/voters?featureId={id}

List all voters for a feature.

Example Request

curl "https://features.vote/api/features/voters?featureId=FEATURE_ID" \
  -H "Authorization: Bearer fv_live_xxx"

Response

{
  "data": {
    "voters": [
      { "id": "...", "name": "John", "email": "john@example.com" }
    ],
    "total_votes": 42
  }
}
POST/api/features/add-voter

Add a voter to a feature. Provide an existing user_id or new_user details.

Request Body

// With existing user
{
  "feature_id": "feature-uuid",
  "user_id": "existing-user-uuid"
}

// With new user
{
  "feature_id": "feature-uuid",
  "new_user": {
    "name": "Jane Doe",
    "email": "jane@example.com",
    "app_user_id": "usr_123"
  }
}

Example Request

curl -X POST https://features.vote/api/features/add-voter \
  -H "Authorization: Bearer fv_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{"feature_id": "FEATURE_ID", "new_user": {"name": "Jane", "email": "jane@example.com"}}'

Response

{
  "message": "Successfully added voter to feature",
  "feature": { "id": "...", "total_votes": 43 }
}
POST/api/features/merge

Merge two features. Voters, subscribers, and tags from the source are added to the target. The source is deleted.

Request Body

{
  "source_feature_id": "uuid-to-merge-from",
  "target_feature_id": "uuid-to-merge-into"
}

Example Request

curl -X POST https://features.vote/api/features/merge \
  -H "Authorization: Bearer fv_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{"source_feature_id": "...", "target_feature_id": "..."}'

Response

{
  "message": "Posts merged successfully",
  "targetFeature": { ... },
  "mergeStats": {
    "addedVoters": 5,
    "addedSubscribers": 2
  }
}

Comments

Manage comments on feature requests. All API-created comments are marked as admin comments.

GET/api/comments?featureId={featureId}

List all comments for a feature.

Example Request

curl "https://features.vote/api/comments?featureId=FEATURE_ID" \
  -H "Authorization: Bearer fv_live_xxx"

Response

[
  {
    "id": "...",
    "comment": "This would be great!",
    "is_admin": true,
    "is_internal": false,
    "created_at": "2024-01-01T00:00:00Z"
  }
]
POST/api/comments/create?featureId={featureId}

Create a comment on a feature. All API comments are marked as admin comments.

Request Body

{
  "feature_id": "feature-uuid",
  "comment": "We're working on this!",
  "is_internal": false
}

Example Request

curl -X POST "https://features.vote/api/comments/create?featureId=FEATURE_ID" \
  -H "Authorization: Bearer fv_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{"feature_id": "...", "comment": "Working on it!"}'

Response

{
  "data": {
    "id": "...",
    "comment": "Working on it!",
    "is_admin": true
  }
}
PUT/api/comments

Update a comment.

Request Body

{
  "id": "comment-uuid",
  "comment": "Updated text"
}

Example Request

curl -X PUT https://features.vote/api/comments \
  -H "Authorization: Bearer fv_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{"id": "COMMENT_ID", "comment": "Updated text"}'

Response

{
  "id": "...",
  "comment": "Updated text"
}
DELETE/api/comments

Delete a comment.

Request Body

{ "id": "comment-uuid" }

Example Request

curl -X DELETE https://features.vote/api/comments \
  -H "Authorization: Bearer fv_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{"id": "COMMENT_ID"}'

Response

null

Releases / Changelogs

Create and manage releases. Generate AI-powered changelogs and send email notifications to subscribers.

GET/api/releases

List all releases for the project.

Example Request

curl https://features.vote/api/releases \
  -H "Authorization: Bearer fv_live_xxx"

Response

{
  "data": [
    {
      "id": "...",
      "version": "1.2.0",
      "title": "January Release",
      "short_description": "...",
      "released_at": "2024-01-15T00:00:00Z"
    }
  ]
}
POST/api/releases

Create a new release. Optionally link features.

Request Body

{
  "version": "1.2.0",
  "title": "January Release",
  "short_description": "Bug fixes and improvements",
  "long_description": "# What's New\n...",
  "feature_ids": ["feat-1", "feat-2"]
}

Example Request

curl -X POST https://features.vote/api/releases \
  -H "Authorization: Bearer fv_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{"version": "1.2.0", "title": "January Release"}'

Response

{
  "data": { "id": "...", "version": "1.2.0" }
}
GET/api/releases?releaseId={id}

Get a single release.

Example Request

curl "https://features.vote/api/releases?releaseId=RELEASE_ID" \
  -H "Authorization: Bearer fv_live_xxx"

Response

{
  "id": "...",
  "version": "1.2.0",
  "title": "January Release"
}
PUT/api/releases

Update a release. Optionally update linked features.

Request Body

{
  "release": {
    "id": "release-uuid",
    "title": "Updated Title"
  },
  "featureIds": ["feat-1", "feat-3"]
}

Example Request

curl -X PUT https://features.vote/api/releases \
  -H "Authorization: Bearer fv_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{"release": {"id": "RELEASE_ID", "title": "Updated Title"}, "featureIds": []}'

Response

null
DELETE/api/releases?releaseId={id}

Delete a release. Linked features will be unlinked.

Example Request

curl -X DELETE "https://features.vote/api/releases?releaseId=RELEASE_ID" \
  -H "Authorization: Bearer fv_live_xxx"

Response

null
POST/api/releases/send-changelog-email

Send the changelog email to subscribers. Max 50 recipients per request.

Request Body

{
  "releaseId": "release-uuid",
  "subject": "What's new in v1.2.0",
  "bodyMarkdown": "# What's New\n\n- Feature A\n- Bug fix B"
}

Example Request

curl -X POST https://features.vote/api/releases/send-changelog-email \
  -H "Authorization: Bearer fv_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{"releaseId": "RELEASE_ID", "subject": "What\'s new", "bodyMarkdown": "# Changes\n..."}'

Response

{
  "success": true,
  "emailsSent": 12,
  "recipients": ["a@b.com", ...]
}
POST/api/releases/generate-changelog

AI-generate a changelog from linked features. Limited to 5 per day per project.

Request Body

{
  "releaseId": "release-uuid",
  "customPrompt": "Write in a friendly tone",
  "existingChangelog": "Optional existing text to improve"
}

Example Request

curl -X POST https://features.vote/api/releases/generate-changelog \
  -H "Authorization: Bearer fv_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{"releaseId": "RELEASE_ID"}'

Response

{
  "changelog": "# v1.2.0 - January Release\n\n## New Features\n...",
  "remaining": 4,
  "limit": 5
}

Project

Retrieve project details and usage analytics.

GET/api/projects

Get details of the project associated with the API key.

Example Request

curl https://features.vote/api/projects \
  -H "Authorization: Bearer fv_live_xxx"

Response

{
  "data": {
    "id": "...",
    "name": "My App",
    "slug": "my-app",
    "website_url": "https://myapp.com",
    "logo_url": "...",
    "created_at": "2024-01-01T00:00:00Z"
  }
}
GET/api/usage

Get usage analytics for the project.

Example Request

curl https://features.vote/api/usage \
  -H "Authorization: Bearer fv_live_xxx"

Response

{
  "data": {
    "total_upvotes": 1234,
    "total_feature_requests": 89,
    "total_views": 5678,
    "total_features": 42,
    "total_releases": 7
  }
}

Error Codes

StatusCodeDescription
400validation_errorMissing or invalid request parameters
401unauthorizedMissing or invalid API key
401api_key_expiredAPI key has passed its expiration date
403plan_requiredGrowth or VIP subscription required
404not_foundResource not found
405method_not_allowedHTTP method not supported for this endpoint
429rate_limit_exceededToo many requests — check X-RateLimit-Reset header
500internal_errorUnexpected server error

MCP Integration

FeaturesVote provides an MCP (Model Context Protocol) server that wraps this REST API, allowing AI assistants like Claude to manage your feature board directly.

Setup (Claude Desktop)

Add the following to your claude_desktop_config.json:

claude_desktop_config.json
{
  "mcpServers": {
    "featuresvote": {
      "command": "npx",
      "args": ["@featuresvote/mcp-server"],
      "env": {
        "FEATURESVOTE_API_KEY": "fv_live_your_key_here"
      }
    }
  }
}
The MCP server exposes tools for all API operations: listing features, creating releases, managing comments, and more.

FeaturesVote API Documentation