REST API Reference

Full API for managing feedback, votes, comments, changelog, and roadmap programmatically.

Authentication

Reflet uses two types of API keys to separate read and write operations.

Public Key pk_...

Passed as a query parameter. Used for read-only operations that are safe to call from client-side code.

GET /api/v1/feedback?publicKey=pk_your_public_key

Secret Key sk_...

Passed as an Authorization header. Used for write operations and should only be used from server-side code.

Authorization: Bearer sk_your_secret_key

Get your API keys from Dashboard > Settings > API Keys.

Base URL

https://your-deployment.convex.site/api/v1

This is the Convex HTTP endpoint for your deployment. Replace your-deployment with your actual Convex deployment URL.

Endpoints

Feedback

GET /api/v1/feedback

List all feedback for an organization.

Query parameters

ParameterTypeDescription
publicKeystringRequired. Your public API key.
statusstringFilter by status (e.g. open, in_progress, closed).
sortstringSort order: votes, newest, or oldest.
limitnumberNumber of items to return (default 20).
cursorstringPagination cursor from a previous response.

Example request

curl "https://your-deployment.convex.site/api/v1/feedback?publicKey=pk_xxx&sort=votes&limit=10"

Example response

{
  "feedback": [
    {
      "id": "fb_abc123",
      "title": "Add dark mode",
      "description": "Please add a dark mode option.",
      "status": "open",
      "voteCount": 42,
      "commentCount": 5,
      "createdAt": "2026-01-15T10:30:00Z"
    }
  ],
  "config": {
    "statuses": ["open", "in_progress", "completed", "closed"],
    "tags": ["feature", "bug", "improvement"]
  },
  "nextCursor": "eyJpZCI6ImZiX2RlZjQ1NiJ9"
}

POST /api/v1/feedback

Create new feedback. Requires a secret key or user token.

Request body

{
  "title": "Add dark mode",
  "description": "It would be great to have a dark mode option.",
  "tagId": "tag_feature"
}

Example request

curl -X POST "https://your-deployment.convex.site/api/v1/feedback" \
  -H "Authorization: Bearer sk_xxx" \
  -H "Content-Type: application/json" \
  -d '{"title": "Add dark mode", "description": "Please add a dark mode option."}'

Example response

{
  "id": "fb_abc123",
  "title": "Add dark mode",
  "description": "Please add a dark mode option.",
  "status": "open",
  "voteCount": 0,
  "commentCount": 0,
  "createdAt": "2026-02-24T12:00:00Z"
}

GET /api/v1/feedback/:id

Get a single feedback item by ID. Returns the feedback object with vote count, comments count, and status.

Example request

curl "https://your-deployment.convex.site/api/v1/feedback/fb_abc123?publicKey=pk_xxx"

Example response

{
  "id": "fb_abc123",
  "title": "Add dark mode",
  "description": "Please add a dark mode option.",
  "status": "open",
  "voteCount": 42,
  "commentCount": 5,
  "tagId": "tag_feature",
  "createdAt": "2026-01-15T10:30:00Z",
  "updatedAt": "2026-02-20T08:15:00Z"
}

POST /api/v1/feedback/:id/vote

Vote on a feedback item.

Request body

{
  "feedbackId": "fb_abc123",
  "voteType": "upvote"
}

Example request

curl -X POST "https://your-deployment.convex.site/api/v1/feedback/fb_abc123/vote" \
  -H "Authorization: Bearer sk_xxx" \
  -H "Content-Type: application/json" \
  -d '{"feedbackId": "fb_abc123", "voteType": "upvote"}'

The voteType field accepts upvote or downvote.

GET /api/v1/feedback/:id/comments

Get comments for a feedback item. Returns an array of comments with nested replies.

Example request

curl "https://your-deployment.convex.site/api/v1/feedback/fb_abc123/comments?publicKey=pk_xxx"

Example response

{
  "comments": [
    {
      "id": "cmt_001",
      "body": "This would be amazing!",
      "authorName": "Jane Doe",
      "createdAt": "2026-01-16T09:00:00Z",
      "replies": [
        {
          "id": "cmt_002",
          "body": "Agreed, especially for late-night use.",
          "authorName": "John Smith",
          "parentId": "cmt_001",
          "createdAt": "2026-01-16T10:30:00Z"
        }
      ]
    }
  ]
}

POST /api/v1/feedback/:id/comments

Add a comment to a feedback item. Optionally include a parentId to create a reply.

Request body

{
  "feedbackId": "fb_abc123",
  "body": "Great idea, would love this feature!",
  "parentId": "cmt_001"
}

Example request

curl -X POST "https://your-deployment.convex.site/api/v1/feedback/fb_abc123/comments" \
  -H "Authorization: Bearer sk_xxx" \
  -H "Content-Type: application/json" \
  -d '{"feedbackId": "fb_abc123", "body": "Great idea!"}'

Example response

{
  "id": "cmt_003",
  "body": "Great idea!",
  "authorName": "You",
  "feedbackId": "fb_abc123",
  "createdAt": "2026-02-24T12:00:00Z"
}

Changelog

GET /api/v1/changelog

Get published changelog entries for an organization.

Example request

curl "https://your-deployment.convex.site/api/v1/changelog?publicKey=pk_xxx"

Example response

{
  "entries": [
    {
      "id": "cl_001",
      "title": "Dark mode is here",
      "body": "We shipped dark mode across the entire app...",
      "publishedAt": "2026-02-20T14:00:00Z",
      "tags": ["feature", "ui"]
    }
  ]
}

Roadmap

GET /api/v1/roadmap

Get public roadmap milestones for an organization.

Example request

curl "https://your-deployment.convex.site/api/v1/roadmap?publicKey=pk_xxx"

Example response

{
  "milestones": [
    {
      "id": "ms_001",
      "title": "Q1 2026",
      "description": "First quarter priorities",
      "status": "in_progress",
      "items": [
        {
          "id": "fb_abc123",
          "title": "Add dark mode",
          "status": "completed"
        },
        {
          "id": "fb_def456",
          "title": "API webhooks",
          "status": "in_progress"
        }
      ]
    }
  ]
}

Subscriptions

POST /api/v1/subscribe

Subscribe an email address to changelog updates.

Request body

{
  "email": "user@example.com"
}

Example request

curl -X POST "https://your-deployment.convex.site/api/v1/subscribe" \
  -H "Authorization: Bearer sk_xxx" \
  -H "Content-Type: application/json" \
  -d '{"email": "user@example.com"}'

Example response

{
  "subscribed": true,
  "email": "user@example.com"
}

Rate Limiting

API requests are rate limited per API key. When you exceed the limit, requests will return a 429 status code. Check the response headers to monitor your usage.

HeaderDescription
X-RateLimit-LimitMaximum number of requests allowed per window.
X-RateLimit-RemainingNumber of requests remaining in the current window.

Errors

All error responses follow a consistent JSON format with an error field describing the issue.

{
  "error": "Error message description"
}
Status CodeMeaningDescription
400Bad RequestThe request body or parameters are invalid.
401UnauthorizedMissing or invalid API key.
404Not FoundThe requested resource does not exist.
429Rate LimitedToo many requests. Wait and retry after the rate limit window resets.