Submissions API¶
!!! info "TL;DR" CRUD operations for feedback submissions. List, search, filter, create, update. Public read, authenticated write.
List Submissions¶
Get all submissions with optional filtering and sorting.
Authentication: Optional (public endpoint)
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
page | number | Page number (default: 1) |
limit | number | Items per page (default: 50, max: 100) |
status | enum | Filter by status |
type | enum | idea or problem |
category | string | Category ID or slug |
tag | string | Tag slug |
author | string | Author user ID |
q | string | Full-text search query |
sort | string | Sort field (created_at, votes, comments) |
order | string | asc or desc (default: desc) |
Example Request:
Example Response:
{
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"title": "Dark mode support",
"description": "Add a dark mode option to reduce eye strain",
"type": "idea",
"status": "planned",
"vote_count": 42,
"comment_count": 8,
"author_id": "uuid",
"category_id": "uuid",
"tags": ["ui", "accessibility"],
"created_at": "2026-01-15T10:30:00Z",
"updated_at": "2026-02-01T14:20:00Z"
}
],
"meta": {
"page": 1,
"limit": 50,
"total": 123,
"total_pages": 3,
"has_next": true,
"has_prev": false
}
}
Get Submission¶
Get a single submission by ID with expanded relations.
Authentication: Optional
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
expand | string | Comma-separated list: author, category, tags, comments |
Example Request:
curl "https://canviq.app/api/submissions/550e8400-e29b-41d4-a716-446655440000?expand=author,category"
Example Response:
{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"title": "Dark mode support",
"description": "Add a dark mode option to reduce eye strain...",
"type": "idea",
"status": "planned",
"vote_count": 42,
"comment_count": 8,
"author": {
"id": "uuid",
"name": "Jane Doe",
"avatar": "https://cdn.canviq.app/avatars/...",
"is_team_member": false
},
"category": {
"id": "uuid",
"name": "Feature Requests",
"slug": "feature-requests",
"color": "blue"
},
"tags": [
{ "name": "UI", "slug": "ui" },
{ "name": "Accessibility", "slug": "accessibility" }
],
"github_issue_url": null,
"is_following": false,
"user_vote": null,
"created_at": "2026-01-15T10:30:00Z",
"updated_at": "2026-02-01T14:20:00Z"
}
}
Create Submission¶
Create a new feedback submission.
Authentication: Required
Request Body:
{
"title": "Dark mode support",
"description": "Add a dark mode option to reduce eye strain during evening use. Many modern apps offer this feature.",
"type": "idea",
"category_id": "550e8400-e29b-41d4-a716-446655440000"
}
Fields:
| Field | Type | Required | Description |
|---|---|---|---|
title | string | Yes | 5-200 characters |
description | string | Yes | 20-5000 characters |
type | enum | Yes | idea or problem |
category_id | UUID | No | Category to assign |
Example Request:
curl -X POST https://canviq.app/api/submissions \
-H "Authorization: Bearer your-api-key" \
-H "Content-Type: application/json" \
-d '{
"title": "Dark mode support",
"description": "Add a dark mode option...",
"type": "idea",
"category_id": "550e8400-e29b-41d4-a716-446655440000"
}'
Example Response:
{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440001",
"title": "Dark mode support",
"status": "open",
"vote_count": 1,
"url": "https://canviq.app/submissions/550e8400-e29b-41d4-a716-446655440001"
}
}
The submitting user automatically votes for their own submission and follows it for updates.
Update Submission¶
Update an existing submission (author only, or admin).
Authentication: Required (must be author or admin)
Request Body:
Updatable Fields:
| Field | Type | Description |
|---|---|---|
title | string | Updated title |
description | string | Updated description |
category_id | UUID | Change category |
Example Request:
curl -X PATCH https://canviq.app/api/submissions/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer your-api-key" \
-H "Content-Type: application/json" \
-d '{"title": "Dark mode support for mobile app"}'
Search Submissions¶
Full-text search across titles and descriptions.
Authentication: Optional
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
q | string | Search query (required) |
page | number | Page number |
limit | number | Items per page |
status | enum | Filter by status |
type | enum | Filter by type |
Example Request:
Example Response:
{
"data": [
{
"id": "...",
"title": "Dark mode support",
"description": "...",
"relevance": 0.87,
"highlight": {
"title": "<mark>Dark mode</mark> support",
"description": "Add a <mark>dark mode</mark> option..."
}
}
],
"meta": {
"query": "dark mode",
"total": 3
}
}
!!! warning "XSS Warning" The highlight field contains raw HTML <mark> tags. Always sanitize these values before rendering in the browser to prevent cross-site scripting (XSS) attacks. Use a library like DOMPurify or sanitize-html.
Check for Duplicates¶
Find similar submissions before creating a new one.
Authentication: Optional
Rate Limit: 30 requests per minute (unauthenticated), 100 per minute (authenticated). This endpoint can be used for content enumeration — rate limiting is enforced.
Request Body:
Example Response:
{
"data": {
"has_duplicates": true,
"similar": [
{
"id": "...",
"title": "Dark theme for app",
"similarity": 0.92,
"vote_count": 42,
"status": "planned"
},
{
"id": "...",
"title": "Night mode",
"similarity": 0.78,
"vote_count": 15,
"status": "open"
}
]
}
}
Use this before calling POST /api/submissions to prevent duplicate submissions.
What's Next¶
- Votes API — Vote on submissions
- Comments API — Discuss submissions
- Filters — Advanced filtering patterns