Authentication
All API requests require authentication via the X-API-Key header. You can find your project API key in the FeedbackKit dashboard under Project Settings.
X-API-Key: your-project-api-key
X-User-Id: optional-user-id # For personalized hasVoted state
Content-Type: application/json
Optional: X-User-Id Header
Include the X-User-Id header to get personalized hasVoted state in feedback responses. Without it, hasVoted will always be false.
Endpoints Overview
All endpoints are prefixed with /api/v1. The base URL for production is https://api.feedbackkit.app.
| Method | Path | Description |
|---|---|---|
| GET | /feedbacks | List all feedback |
| POST | /feedbacks | Submit new feedback |
| GET | /feedbacks/:id | Get feedback by ID |
| POST | /feedbacks/:id/votes | Vote for feedback |
| DELETE | /feedbacks/:id/votes | Remove vote |
| GET | /feedbacks/:id/comments | List comments |
| POST | /feedbacks/:id/comments | Add comment |
| POST | /users/register | Register SDK user |
| POST | /events/track | Track analytics event |
Feedback
/feedbacks
Retrieves all feedback for the project, sorted by vote count (descending). Merged feedback items are excluded by default.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
| status | string | Filter by status: pending, approved, in_progress, testflight, completed, rejected |
| category | string | Filter by category: feature_request, bug_report, improvement, other |
| includeMerged | boolean | Include merged feedback items. Default: false |
curl -X GET "https://api.feedbackkit.app/api/v1/feedbacks?status=approved" \
-H "X-API-Key: your-api-key" \
-H "X-User-Id: user_12345"
Response
[
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"title": "Add dark mode support",
"description": "It would be great to have a dark mode option.",
"status": "approved",
"category": "feature_request",
"userId": "user_12345",
"voteCount": 42,
"hasVoted": false,
"commentCount": 5,
"createdAt": "2026-02-01T10:30:00Z",
"updatedAt": "2026-02-05T14:20:00Z"
}
]
/feedbacks
Creates a new feedback item. The creator automatically receives a vote (voteCount starts at 1). Triggers notifications to project members and configured integrations.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| title | string | Yes | Feedback title (1-200 chars) |
| description | string | Yes | Detailed description (1-5000 chars) |
| category | string | Yes | feature_request, bug_report, improvement, other |
| userId | string | Yes | Unique identifier of the submitting user |
| userEmail | string | No | Email for status update notifications |
curl -X POST "https://api.feedbackkit.app/api/v1/feedbacks" \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"title": "Add dark mode support",
"description": "It would be great to have a dark mode option.",
"category": "feature_request",
"userId": "user_12345",
"userEmail": "user@example.com"
}'
/feedbacks/:id
Retrieves a single feedback item by its UUID.
curl -X GET "https://api.feedbackkit.app/api/v1/feedbacks/550e8400-e29b-41d4-a716-446655440000" \
-H "X-API-Key: your-api-key" \
-H "X-User-Id: user_12345"
Votes
/feedbacks/:id/votes
Adds a vote to a feedback item. Each user can only vote once per feedback.
Restrictions
- Cannot vote on archived projects (403)
- Cannot vote on completed or rejected feedback (403)
- Cannot vote twice on the same feedback (409)
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| userId | string | Yes | Unique identifier of the voting user |
| string | No | Email for status change notifications | |
| notifyStatusChange | boolean | No | Opt-in to email notifications on status changes. Default: false |
curl -X POST "https://api.feedbackkit.app/api/v1/feedbacks/550e8400-.../votes" \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"userId": "user_12345",
"email": "user@example.com",
"notifyStatusChange": true
}'
Response
{
"feedbackId": "550e8400-e29b-41d4-a716-446655440000",
"voteCount": 43,
"hasVoted": true
}
/feedbacks/:id/votes
Removes the user's vote from a feedback item.
curl -X DELETE "https://api.feedbackkit.app/api/v1/feedbacks/550e8400-.../votes" \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{"userId": "user_12345"}'
Users
/users/register
Registers or updates an SDK user. Use this to track user activity and associate MRR (Monthly Recurring Revenue). If the user already exists, their lastSeenAt timestamp and MRR will be updated.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| userId | string | Yes | Unique identifier of the SDK user |
| mrr | number | No | Monthly Recurring Revenue for this user |
curl -X POST "https://api.feedbackkit.app/api/v1/users/register" \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"userId": "user_12345",
"mrr": 9.99
}'
Response
{
"id": "770e8400-e29b-41d4-a716-446655440000",
"userId": "user_12345",
"mrr": 9.99,
"firstSeenAt": "2026-01-15T08:00:00Z",
"lastSeenAt": "2026-02-08T12:30:00Z"
}
Events
/events/track
Tracks a custom event for analytics. Use this to measure user engagement with the feedback system.
Common Events
| Event Name | Description |
|---|---|
| feedback_list | User viewed the feedback list |
| feedback_detail | User viewed feedback details |
| submit_feedback | User opened the submit form |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| eventName | string | Yes | Name of the event (1-100 chars) |
| userId | string | Yes | Unique identifier of the user |
| properties | object | No | Key-value properties for the event |
curl -X POST "https://api.feedbackkit.app/api/v1/events/track" \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"eventName": "feedback_list",
"userId": "user_12345",
"properties": {
"filter": "feature_request",
"sort": "votes"
}
}'
Models
FeedbackResponse
| Field | Type | Description |
|---|---|---|
| id | UUID | Unique identifier |
| title | string | Feedback title |
| description | string | Detailed description |
| status | FeedbackStatus | Current status of the feedback |
| category | FeedbackCategory | Feedback category |
| userId | string | ID of the submitting user |
| userEmail | string? | Email of the submitter (if provided) |
| voteCount | integer | Total number of votes |
| hasVoted | boolean | Whether the current user has voted |
| commentCount | integer | Total number of comments |
| totalMrr | number? | Combined MRR of all voters |
| createdAt | ISO 8601 | Creation timestamp |
| updatedAt | ISO 8601 | Last update timestamp |
| rejectionReason | string? | Explanation for rejection (max 500 chars) |
| mergedIntoId | UUID? | ID of feedback this was merged into |
| mergedAt | ISO 8601? | When this feedback was merged |
| mergedFeedbackIds | UUID[]? | IDs of feedback merged into this one |
FeedbackStatus
| Value | Description | Voting |
|---|---|---|
| pending | New, awaiting review | Allowed |
| approved | Accepted for consideration | Allowed |
| in_progress | Currently being worked on | Allowed |
| testflight | Available in beta/TestFlight | Allowed |
| completed | Shipped and available | Blocked |
| rejected | Won't be implemented | Blocked |
FeedbackCategory
| Value | Description |
|---|---|
| feature_request | New functionality request |
| bug_report | Issue or problem report |
| improvement | Enhancement to existing feature |
| other | General feedback |
VoteResponse
| Field | Type | Description |
|---|---|---|
| feedbackId | UUID | ID of the feedback item |
| voteCount | integer | Updated vote count |
| hasVoted | boolean | Whether the user has voted after this action |
CommentResponse
| Field | Type | Description |
|---|---|---|
| id | UUID | Unique identifier |
| content | string | Comment text |
| userId | string | ID of the commenting user |
| isAdmin | boolean | Whether this is an admin comment |
| createdAt | ISO 8601 | Creation timestamp |
Error Handling
All errors follow a consistent format with an error boolean and a human-readable reason string.
{
"error": true,
"reason": "Invalid API key"
}
HTTP Status Codes
| Code | Name | Description |
|---|---|---|
| 200 | OK | Request succeeded |
| 400 | Bad Request | Validation error (missing or invalid fields) |
| 401 | Unauthorized | Missing or invalid API key |
| 402 | Payment Required | Subscription tier limit exceeded |
| 403 | Forbidden | Action not allowed (archived project, completed feedback, etc.) |
| 404 | Not Found | Resource does not exist |
| 409 | Conflict | Duplicate action (e.g., already voted) |
| 429 | Too Many Requests | Rate limit exceeded |
Subscription Tiers
Some API features are limited by subscription tier. Exceeding limits returns a 402 Payment Required response.
| Feature | Free | Pro | Team |
|---|---|---|---|
| Projects | 1 | 2 | Unlimited |
| Feedback per project | 10 | Unlimited | Unlimited |
| Team members | - | - | Unlimited |
| Integrations | - | All | All |
| Voter notifications | - | - | Yes |
Comments
/feedbacks/:id/commentsRetrieves all comments for a feedback item, sorted by creation time (ascending).
Response
/feedbacks/:id/commentsAdds a comment to a feedback item. Cannot comment on archived projects.
Request Body
false