Overview
Start here
The public API currently exposes the minimum surface needed for integrations to discover projects and log writing progress. This page documents the public project and session endpoints available today. For AI assistants, see the MCP guide.
https://quilvo.app/api/v1application/jsonBearer tokenprojects:* / sessions:*Authentication
Bearer tokens
Users create public API keys from Settings / API Keys. Each key can be limited to the project and session abilities needed by the integration.
Authorization: Bearer YOUR_API_KEY
Accept: application/json
Content-Type: application/jsonAbilities
| Ability | Description |
|---|---|
projects:read | Read projectsList projects and read project details. |
projects:write | Write projectsCreate projects and update project metadata. |
sessions:read | Read sessionsList writing sessions and read today's session summary. |
sessions:write | Write sessionsCreate single or bulk writing sessions. |
Requests
Request conventions
- Send JSON request bodies for write endpoints.
- Dates use
YYYY-MM-DD. - Resource IDs are UUID strings.
- List endpoints use cursor pagination and accept
per_page.
Responses
Response formats
Paginated lists
{
"data": [],
"links": {
"first": "...",
"last": "...",
"prev": null,
"next": "..."
},
"meta": {
"path": "https://quilvo.app/api/v1/projects",
"per_page": 25,
"next_cursor": "...",
"prev_cursor": null
}
}Error responses
{
"error": {
"code": "validation_error",
"message": "The given data was invalid.",
"details": {
"word_count": ["The word count field is required."]
}
}
}Projects
Project endpoints
Use project endpoints to list existing projects, create projects for a linked tool, or update project metadata. For ordinary word count changes, use session endpoints instead.
/projectsList projects for the authenticated user.
Required ability: projects:read
Query parameters
status | active by default. Use archived or all when needed. |
type | Filter by project type, such as novel or short_story. |
series_id | Filter projects by series UUID. |
search | Case-insensitive title search. |
per_page | Cursor page size. Maximum 100. |
/projects/{project}Read one project, including detail fields, recent sessions, and summary stats.
Required ability: projects:read
Response excerpt
{
"id": "9b7d4f6a-...",
"title": "Draft novel",
"type": "novel",
"status": "drafting",
"current_word_count": 42100,
"target_word_count": 80000,
"target_unit": "words",
"progress_percent": 52.63,
"recent_sessions": []
}/projectsCreate a project.
Required ability: projects:write
Body fields
| Field | Type | Required | Description |
|---|---|---|---|
title | string | Create | Project title. |
type | string | Create | Project type enum, for example novel. |
status | string | No | Project status enum, for example drafting. |
target_word_count | integer | No | Target count. Minimum 0. |
current_word_count | integer | No | Baseline/import count only. Prefer session logging for ongoing changes. |
target_date | date | No | Alias for target_completion_date. |
description | string | No | Alias for the short project description. |
Request example
{
"title": "Draft novel",
"type": "novel",
"status": "drafting",
"target_word_count": 80000
}/projects/{project}Update project metadata. This endpoint accepts the same fields as project creation, but all fields are optional.
Required ability: projects:write
{
"status": "revising",
"target_word_count": 90000
}Sessions
Session endpoints
Session endpoints are the preferred way to update word counts because Quilvo stores the event history and updates the project total for you.
/sessionsList writing sessions.
Required ability: sessions:read
Query parameters
project_id | Filter sessions for a single project UUID. |
date_from | Start date in YYYY-MM-DD format. |
date_to | End date in YYYY-MM-DD format. |
per_page | Cursor page size. Maximum 100. |
/sessions/todayRead today's sessions and totals in the account timezone.
Required ability: sessions:read
{
"date": "2026-05-24",
"sessions": [],
"summary": {
"total_words": 750,
"total_sessions": 1,
"total_minutes": 45
}
}/sessions Log a single writing session. Use add for deltas or set_total when the client knows the new project total.
Required ability: sessions:write
Idempotency-Key header, or a top-level idempotency_key body field. Reuse the same key only for retrying the same request. Keys are stored for 24 hours. Body fields
| Field | Type | Required | Description |
|---|---|---|---|
project_id | uuid | Yes | The project to log progress against. |
word_count_action | string | No | add by default. Use set_total when sending the new project total. |
word_count | integer | Yes | For add, the delta. For set_total, the new total; Quilvo stores the calculated delta. |
date | date | No | YYYY-MM-DD. Defaults to today. Cannot be in the future. |
duration_minutes | integer | No | Duration from 0 to 1440 minutes. |
notes | string | No | Optional session notes. Maximum 1000 characters. |
Request example
curl -X POST https://quilvo.app/api/v1/sessions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Idempotency-Key: local-log-2026-05-24-0830" \
-H "Content-Type: application/json" \
-d '{
"project_id": "9b7d4f6a-...",
"word_count_action": "add",
"word_count": 750,
"date": "2026-05-24",
"duration_minutes": 45
}'Response excerpt
{
"session": {
"id": "9c1a...",
"project_id": "9b7d4f6a-...",
"date": "2026-05-24",
"word_count": 750,
"unit": "words",
"duration_minutes": 45
},
"today_stats": {
"total_words": 750,
"daily_goal": 1000,
"goal_progress_percent": 75,
"goal_achieved": false
}
}/sessions/bulkCreate up to 30 session records in one request. Bulk logging accepts deltas only.
Required ability: sessions:write
Idempotency-Key header or idempotency_key body field as POST /sessions. Body fields
| Field | Type | Required | Description |
|---|---|---|---|
sessions | array | Yes | 1 to 30 session objects. |
sessions.*.project_id | uuid | Yes | Project UUID owned by the authenticated user. |
sessions.*.date | date | Yes | YYYY-MM-DD. Cannot be in the future. |
sessions.*.word_count | integer | Yes | Delta only. set_total is intentionally not supported in bulk. |
{
"sessions": [
{
"project_id": "9b7d4f6a-...",
"date": "2026-05-23",
"word_count": 320
}
]
}Errors
Status codes
| Status | Meaning |
|---|---|
200 | Successful read or replayed write. |
201 | Resource created. |
401 | Missing or invalid bearer token. |
403 | Token is valid but missing the required ability. |
404 | Resource not found or not owned by this account. |
409 | Idempotency key conflict or in-progress request. |
422 | Validation failed. See `error.details`. |
429 | Too many requests. |