API Reference Overview¶
!!! info "TL;DR" REST API at https://canviq.app/api. Authenticate with Bearer token. JSON request/response. Paginated results. Standard error format.
Base URL¶
All API endpoints are prefixed with:
For local development:
Authentication¶
All authenticated endpoints require a Bearer token in the Authorization header:
Get an API key from the admin dashboard under Settings → API Keys.
Public vs Authenticated Endpoints¶
| Access Level | Endpoints | Example |
|---|---|---|
| Public | Read submissions, categories, tags | GET /api/submissions |
| Authenticated | Vote, comment, create submissions | POST /api/submissions/:id/vote |
| Admin | Moderation, analytics, bulk actions | POST /api/admin/merge |
| Agent | MCP tools | POST /api/mcp/tools |
Content Type¶
All requests and responses use JSON:
Response Format¶
Success Response¶
Error Response¶
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid input",
"details": [
{
"field": "title",
"message": "Title must be at least 5 characters"
}
]
}
}
HTTP Status Codes¶
| Code | Meaning | When |
|---|---|---|
200 | OK | Successful GET, PATCH, DELETE |
201 | Created | Successful POST |
400 | Bad Request | Invalid input, validation failed |
401 | Unauthorized | Missing or invalid API key |
403 | Forbidden | Authenticated but lacking permissions |
404 | Not Found | Resource doesn't exist |
429 | Too Many Requests | Rate limit exceeded |
500 | Internal Server Error | Server error |
Pagination¶
List endpoints return paginated results. Use query parameters to navigate:
Parameters:
page— Page number (1-indexed, default: 1)limit— Items per page (default: 50, max: 100)
Response includes pagination metadata:
{
"data": [...],
"meta": {
"page": 2,
"limit": 25,
"total": 123,
"total_pages": 5,
"has_next": true,
"has_prev": true
}
}
Filtering¶
Most list endpoints support filtering via query parameters:
Common filters:
status— Filter by submission statuscategory— Filter by category ID or slugtag— Filter by tag slugtype— Filter byideaorproblemauthor— Filter by author IDq— Full-text search query
Sorting¶
Use sort and order parameters:
Parameters:
sort— Field to sort by (created_at,votes,comments,title)order— Sort direction (ascordesc, default:desc)
Rate Limits¶
| Access Level | Limit | Window |
|---|---|---|
| Public | 30 requests | 1 minute |
| Authenticated | 100 requests | 1 minute |
| Admin | 300 requests | 1 minute |
| Agent | Tier-based | 1 minute |
Rate limit headers are included in every response:
If rate limited, the server returns 429 with:
Field Expansion¶
Some endpoints support expanding related resources. Use the expand parameter:
Without expansion, you get IDs:
With expansion, you get full objects:
{
"author": {
"id": "uuid",
"name": "Jane Doe",
"avatar": "..."
},
"category": {
"id": "uuid",
"name": "Feature Requests",
"slug": "feature-requests"
}
}
Internationalization¶
Set the Accept-Language header to get localized content:
Supported locales: en, es, fr, de, ru, pt-BR, ja, it
Category and tag names are returned in the requested locale if translations exist, otherwise fall back to English.
CORS¶
CORS is configured per-endpoint:
- Read-only public endpoints (e.g.,
GET /api/submissions): Same-origin requests only. Cross-origin requests require the appropriateAccess-Control-Allow-Originheader configured in the admin dashboard. - Authenticated endpoints: Require session cookies (
sameSite: lax) which are only sent for same-site requests. - MCP endpoints: Accept Bearer token authentication (no cookie dependency).
!!! warning "CORS is NOT open by default" Unlike some APIs, Canviq does not enable Access-Control-Allow-Origin: *. Cross-origin access must be explicitly configured.
Webhooks¶
Subscribe to events via webhooks. Configure in admin dashboard under Settings → Webhooks.
Supported events:
submission.createdsubmission.updatedvote.createdcomment.createdstatus.changed
What's Next¶
- Submissions API — CRUD, search, filter
- Votes API — Voting operations
- Comments API — Discussion threads
- Surveys API — Survey management
- MCP Tools API — AI agent endpoints