Skip to content

Comments API

!!! info "TL;DR" Discussion threads on submissions. Public read, authenticated write. Official badge for team members. Nested replies supported.

List Comments

Get all comments for a submission.

GET /api/submissions/:id/comments

Authentication: Optional

Query Parameters:

Parameter Type Description
page number Page number (default: 1)
limit number Items per page (default: 50)
sort string created_at or votes (default: created_at)
order string asc or desc (default: asc)

Example Request:

curl "https://canviq.app/api/submissions/550e8400-e29b-41d4-a716-446655440000/comments"

Example Response:

{
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440010",
      "body": "This would be really helpful for late-night use!",
      "author": {
        "id": "uuid",
        "name": "Jane Doe",
        "avatar": "https://cdn.canviq.app/avatars/...",
        "is_team_member": false
      },
      "is_official": false,
      "vote_count": 5,
      "reply_count": 2,
      "parent_id": null,
      "created_at": "2026-01-16T08:30:00Z",
      "updated_at": "2026-01-16T08:30:00Z"
    },
    {
      "id": "550e8400-e29b-41d4-a716-446655440011",
      "body": "We've planned this for Q2 2026. Thanks for the feedback!",
      "author": {
        "id": "uuid",
        "name": "Product Team",
        "avatar": "...",
        "is_team_member": true
      },
      "is_official": true,
      "vote_count": 12,
      "reply_count": 0,
      "parent_id": null,
      "created_at": "2026-02-01T14:20:00Z",
      "updated_at": "2026-02-01T14:20:00Z"
    }
  ],
  "meta": {
    "total": 8
  }
}

Get Comment

Get a single comment by ID with nested replies.

GET /api/comments/:id

Authentication: Optional

Query Parameters:

Parameter Type Description
expand string replies to include nested comments

Example Request:

curl "https://canviq.app/api/comments/550e8400-e29b-41d4-a716-446655440010?expand=replies"

Example Response:

{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440010",
    "body": "This would be really helpful!",
    "author": {...},
    "replies": [
      {
        "id": "550e8400-e29b-41d4-a716-446655440012",
        "body": "Agreed! Especially on mobile.",
        "author": {...},
        "parent_id": "550e8400-e29b-41d4-a716-446655440010",
        "created_at": "2026-01-16T09:00:00Z"
      }
    ],
    "created_at": "2026-01-16T08:30:00Z"
  }
}

Create Comment

Add a comment to a submission.

POST /api/submissions/:id/comments

Authentication: Required

Request Body:

{
  "body": "This would be really helpful for late-night use!",
  "parent_id": null
}

Fields:

Field Type Required Description
body string Yes 1-2000 characters
parent_id UUID No Parent comment for nested replies

Example Request:

curl -X POST https://canviq.app/api/submissions/550e8400-e29b-41d4-a716-446655440000/comments \
  -H "Authorization: Bearer your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "body": "This would be really helpful!",
    "parent_id": null
  }'

Example Response:

{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440013",
    "body": "This would be really helpful!",
    "author": {
      "id": "uuid",
      "name": "Your Name"
    },
    "is_official": false,
    "created_at": "2026-02-10T15:45:00Z"
  }
}

Side Effects:

  • Increments comment_count on submission (via trigger)
  • Sends notification to submission author
  • Sends notification to parent comment author (if replying)
  • Sends notification to all followers

Update Comment

Edit a comment (author only, within 15 minutes).

PATCH /api/comments/:id

Authentication: Required (must be author)

Request Body:

{
  "body": "Updated comment text"
}

Example Request:

curl -X PATCH https://canviq.app/api/comments/550e8400-e29b-41d4-a716-446655440010 \
  -H "Authorization: Bearer your-api-key" \
  -H "Content-Type: application/json" \
  -d '{"body": "Updated comment text"}'

Comments can only be edited within 15 minutes of creation. After that, the endpoint returns 403 Forbidden.

Delete Comment

Delete a comment (author or admin).

DELETE /api/comments/:id

Authentication: Required (must be author or admin)

Example Request:

curl -X DELETE https://canviq.app/api/comments/550e8400-e29b-41d4-a716-446655440010 \
  -H "Authorization: Bearer your-api-key"

Example Response:

{
  "data": {
    "deleted": true
  }
}

Deleting a parent comment also deletes all nested replies (cascade).

Official Comments

Team members can post official comments that get a special badge. Official comments:

  • Display an "Official" badge
  • Appear at the top of comment threads (sorted first)
  • Send notifications to all followers
  • Are used in submission status updates

To post an official comment, the author must be in the team_members table. The is_official flag is set automatically based on team membership.

Vote on Comments

Comments support voting just like submissions.

POST /api/comments/:id/vote
DELETE /api/comments/:id/vote

Works identically to submission voting. Useful for surfacing helpful comments.

Realtime Comment Updates

Subscribe to new comments via Supabase Realtime:

const channel = supabase
  .channel(`comments:submission=${submissionId}`)
  .on(
    'postgres_changes',
    {
      event: 'INSERT',
      schema: 'public',
      table: 'comments',
      filter: `submission_id=eq.${submissionId}`,
    },
    (payload) => {
      console.log('New comment:', payload.new)
      // Update UI with new comment
    }
  )
  .subscribe()

Rate Limits

Endpoint Limit Window
POST /comments 20 1 hour
PATCH /comments/:id 10 1 hour
DELETE /comments/:id 10 1 hour
GET /comments 100 1 minute

What's Next