The Jility server provides a REST API for managing tickets, projects, comments, and dependencies. It also includes WebSocket support for real-time updates.
Base URL: http://localhost:3000
WebSocket: ws://localhost:3000/ws
Currently, the API does not require authentication (marked as TODO in the code). All endpoints are accessible without tokens.
GET /api/projects
Response:
[
{
"id": "uuid",
"name": "Project Name",
"description": "Optional description",
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z"
}
]POST /api/projects
Content-Type: application/json
{
"name": "My Project",
"description": "Optional description"
}
Response:
{
"id": "uuid",
"name": "My Project",
"description": "Optional description",
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z"
}GET /api/projects/:id
Response: Same as create project response.
GET /api/tickets?project_id={uuid}&status={status}&assignee={name}&epic_id={uuid}
Query Parameters:
project_id(optional): Filter by project UUIDstatus(optional): Filter by status (backlog, todo, in_progress, review, done, blocked)assignee(optional): Filter by assignee nameepic_id(optional): Filter by epic UUID (shows only tickets belonging to this epic)
Response:
[
{
"id": "uuid",
"number": "TASK-1",
"title": "Ticket Title",
"description": "Ticket description",
"status": "backlog",
"story_points": 5,
"assignees": ["alice", "agent-1"],
"labels": ["backend", "feature"],
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z",
"created_by": "alice",
"parent_id": null,
"epic_id": null
}
]POST /api/tickets
Content-Type: application/json
{
"title": "Add user authentication",
"description": "Implement JWT-based auth",
"story_points": 5,
"status": "todo",
"assignees": ["alice", "agent-1"],
"labels": ["backend", "feature"],
"parent_id": null,
"parent_epic_id": null,
"is_epic": false,
"epic_color": null
}
Epic Fields:
is_epic(boolean): Set totrueto create an epic instead of a regular ticketepic_color(string): Hex color code for epic badge (e.g., "#3b82f6"). Optional, defaults to theme primary.parent_epic_id(uuid): ID of the epic this ticket belongs to. Cannot be set ifis_epicis true.
Response: Same format as ticket in list response.
WebSocket Broadcast: Sends TicketCreated message to all connected clients.
GET /api/tickets/:id
Response:
{
"ticket": {
"id": "uuid",
"number": "TASK-1",
"title": "Ticket Title",
...
},
"comments": [
{
"id": "uuid",
"ticket_id": "uuid",
"author": "alice",
"content": "Comment text",
"created_at": "2024-01-01T00:00:00Z",
"updated_at": null
}
],
"dependencies": [
{
"id": "uuid",
"number": "TASK-2",
"title": "Dependency ticket",
"status": "done"
}
],
"dependents": [...],
"linked_commits": [
{
"id": "uuid",
"commit_hash": "abc123",
"commit_message": "Fix bug",
"linked_at": "2024-01-01T00:00:00Z",
"linked_by": "alice"
}
],
"recent_changes": [
{
"id": "uuid",
"change_type": "status_changed",
"field_name": "status",
"old_value": "todo",
"new_value": "in_progress",
"changed_by": "alice",
"changed_at": "2024-01-01T00:00:00Z",
"message": null
}
]
}PUT /api/tickets/:id
Content-Type: application/json
{
"title": "Updated title",
"story_points": 8,
"parent_id": "uuid",
"epic_id": "uuid"
}
Response: Ticket response.
WebSocket Broadcast: Sends TicketUpdated message.
PATCH /api/tickets/:id/description
Content-Type: application/json
{
"description": "New description text",
"operation": "replace_all"
}
Response: Ticket response.
PATCH /api/tickets/:id/status
Content-Type: application/json
{
"status": "in_progress"
}
Valid statuses: backlog, todo, in_progress, review, done, blocked
Response: Ticket response.
WebSocket Broadcast: Sends StatusChanged message.
POST /api/tickets/:id/assign
Content-Type: application/json
{
"assignee": "alice"
}
Response: Ticket response with updated assignees.
POST /api/tickets/:id/unassign
Content-Type: application/json
{
"assignee": "alice"
}
Response: Ticket response with updated assignees.
DELETE /api/tickets/:id
Soft Delete: Marks the ticket as deleted (deleted_at timestamp set) but preserves it in the database for audit trail. Deleted tickets are filtered out of list and board views.
Response:
{
"success": true
}GET /api/epics
Returns all epics with progress statistics.
Response:
[
{
"id": "uuid",
"number": "JIL-42",
"title": "User Authentication",
"description": "Complete auth system",
"is_epic": true,
"epic_color": "#3b82f6",
"progress": {
"total": 10,
"done": 3,
"in_progress": 2,
"todo": 5,
"blocked": 0,
"completion_percentage": 30
},
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z"
}
]GET /api/epics/:id
Returns epic details with progress tracking.
Response: Same format as epic in list response.
GET /api/epics/:id/tickets
Returns all tickets belonging to an epic with status breakdown.
Response:
{
"epic": {
"id": "uuid",
"number": "JIL-42",
"title": "User Authentication",
...
},
"tickets": [
{
"id": "uuid",
"number": "JIL-43",
"title": "Build login UI",
"status": "in_progress",
"parent_epic_id": "uuid",
...
}
],
"progress": {
"total": 10,
"done": 3,
"in_progress": 2,
"todo": 5,
"blocked": 0,
"completion_percentage": 30
}
}GET /api/tickets/:id/comments
Response:
[
{
"id": "uuid",
"ticket_id": "uuid",
"author": "alice",
"content": "Comment text",
"created_at": "2024-01-01T00:00:00Z",
"updated_at": null
}
]POST /api/tickets/:id/comments
Content-Type: application/json
{
"content": "This is a comment"
}
Response: Comment object.
WebSocket Broadcast: Sends CommentAdded message.
PUT /api/comments/:id
Content-Type: application/json
{
"content": "Updated comment text"
}
Response: Comment object.
DELETE /api/comments/:id
Response:
{
"success": true
}POST /api/tickets/:id/dependencies
Content-Type: application/json
{
"depends_on_id": "uuid"
}
Response:
{
"success": true
}DELETE /api/tickets/:id/dependencies/:dep_id
Response:
{
"success": true
}GET /api/tickets/:id/dependency-graph
Response:
{
"ticket": {
"id": "uuid",
"number": "TASK-1",
"title": "Ticket Title",
"status": "in_progress"
},
"dependencies": [...],
"dependents": [...]
}GET /api/tickets/:id/activity
Returns all changes to a ticket in chronological order.
Response:
[
{
"id": "uuid",
"change_type": "status_changed",
"field_name": "status",
"old_value": "todo",
"new_value": "in_progress",
"changed_by": "alice",
"changed_at": "2024-01-01T00:00:00Z",
"message": null
}
]GET /api/tickets/:id/history
Returns all versions of the ticket description.
Response:
[
{
"version": 1,
"description": "Original description",
"changed_by": "alice",
"changed_at": "2024-01-01T00:00:00Z"
}
]GET /api/tickets/:id/history/:version
Response:
{
"version": 1,
"description": "Description at this version",
"changed_by": "alice",
"changed_at": "2024-01-01T00:00:00Z"
}POST /api/tickets/:id/revert/:version
Response:
{
"success": true,
"message": "Not implemented yet"
}GET /api/search?q=authentication&limit=10
Query Parameters:
q(required): Search querylimit(optional): Maximum results
Response: Array of ticket responses.
Note: Currently only searches in ticket titles. Full-text search with FTS5 is marked as TODO.
POST /api/tickets/:id/commits
Content-Type: application/json
{
"commit_hash": "abc123def456",
"commit_message": "Fix authentication bug"
}
Response:
{
"id": "uuid",
"commit_hash": "abc123def456",
"commit_message": "Fix authentication bug",
"linked_at": "2024-01-01T00:00:00Z",
"linked_by": "alice"
}GET /api/tickets/:id/commits
Response:
[
{
"id": "uuid",
"commit_hash": "abc123def456",
"commit_message": "Fix authentication bug",
"linked_at": "2024-01-01T00:00:00Z",
"linked_by": "alice"
}
]Connect to ws://localhost:3000/ws
The server broadcasts the following message types:
TicketCreated:
{
"type": "ticket_created",
"ticket": { ... }
}TicketUpdated:
{
"type": "ticket_updated",
"ticket": { ... }
}StatusChanged:
{
"type": "status_changed",
"ticket_id": "uuid",
"old_status": "todo",
"new_status": "in_progress"
}CommentAdded:
{
"type": "comment_added",
"ticket_id": "uuid",
"comment": { ... }
}DescriptionEdited:
{
"type": "description_edited",
"ticket_id": "uuid",
"version": 2
}All endpoints return errors in the following format:
{
"error": "error_type",
"message": "Human readable error message",
"details": null
}Status Codes:
400 Bad Request- Invalid input or validation error404 Not Found- Resource not found500 Internal Server Error- Database or server error
The following change types are tracked in ticket_changes:
created- Ticket createdtitle_changed- Title updateddescription_changed- Description updatedstatus_changed- Status changedstory_points_changed- Story points changedassignee_added- Assignee addedassignee_removed- Assignee removedlabel_added- Label addedlabel_removed- Label removeddependency_added- Dependency addeddependency_removed- Dependency removedparent_changed- Parent changedepic_changed- Epic changedcomment_added- Comment addedcommit_linked- Commit linkedadded_to_sprint- Added to sprintremoved_from_sprint- Removed from sprint