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¶
Endpoints under /api/v1/* and the MCP server require a Bearer token in the Authorization header:
Get an API key from the admin dashboard under Settings → API Keys.
Live and test keys are separate¶
Every key is bound to one environment, named in its prefix: pk_live_… for production, pk_test_… for the sandbox. The two never cross. A test key reads and writes test data only, and that includes the keys themselves — with a test key, GET /api/v1/keys lists only your test keys, and a live key's ID returns 404, the same as an ID that does not exist. POST /api/v1/keys always creates the key in the calling key's own environment; sending an environment that does not match yours is refused with 403.
To manage keys in the other environment, use a key from that environment, or the dashboard, which shows both.
Agent keys are rotated from the dashboard¶
A key tied to an MCP agent takes its access from that agent's policies rather than from the key itself, so a replacement key carries that agent's access whatever the caller holds. POST /api/v1/keys/{id} with action: "rotate" therefore refuses an agent key with 403. You can still read it with GET and revoke it with DELETE — rotation is the one thing unavailable here. Rotate it from the API keys page in your dashboard instead.
Public vs Authenticated Endpoints¶
| Access Level | Endpoints | Example |
|---|---|---|
| Admin | Moderation, analytics, bulk actions | POST /api/admin/merge |
| Agent | MCP tools | POST /api/mcp/tools |
GET /api/submissions requires a logged-in browser session (magic link or GitHub OAuth), not an org API key. It is not part of the Bearer-token surface above; it is called from Canviq's own admin dashboard. There is no public REST API for reading, filtering, or writing submissions, votes, or comments today. See Votes API and Comments API for details.
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: 20, max: 100)
Response includes pagination metadata:
{
"data": [...],
"meta": {
"page": 2,
"limit": 25,
"total": 123,
"total_pages": 5,
"has_next": true,
"has_prev": true
}
}
Filtering, Sorting, and Field Expansion¶
GET /api/submissions does not support query-param filtering, a sort parameter, or an expand parameter today. Results are always newest-first.
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:
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:
- Session-authenticated endpoints (e.g.,
GET /api/submissions): Require session cookies (sameSite: lax) which are only sent for same-site requests. /api/v1/*and 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