Documentation
¶
Overview ¶
Package ticktick provides a Go client for the TickTick Open API.
Usage ¶
import "github.com/slavkluev/go-ticktick"
Construct a new client with an OAuth2 access token, then call methods to access the TickTick API. For example:
client := ticktick.NewClient("your-access-token")
// List all projects.
projects, err := client.GetProjects(ctx)
// Create a high-priority task.
task, err := client.CreateTask(ctx, &ticktick.CreateTaskRequest{
Title: "Buy groceries",
ProjectID: projects[0].ID,
Priority: ticktick.Int(ticktick.PriorityHigh),
})
// Mark it complete.
err = client.CompleteTask(ctx, task.ProjectID, task.ID)
The client supports customization through functional options:
client := ticktick.NewClient("your-access-token",
ticktick.WithHTTPClient(httpClient),
ticktick.WithBaseURL("https://api.dida365.com"),
)
All methods accept a context.Context as the first parameter for cancellation and timeouts.
Authentication ¶
The TickTick API uses OAuth2 Bearer tokens. Obtain an access token through the Authorization Code flow described in the TickTick Developer Center at https://developer.ticktick.com/api, then pass it to NewClient.
Creating and Updating Resources ¶
Request types use pointer fields for optional values, allowing the API to distinguish between unset fields and zero values. Helper functions String, Int, Int64, Bool, and NewTime create the required pointers:
req := &ticktick.CreateTaskRequest{
Title: "Weekly report",
ProjectID: "project-id",
Content: ticktick.String("Status update"),
Priority: ticktick.Int(ticktick.PriorityMedium),
DueDate: ticktick.NewTime(time.Now().Add(24 * time.Hour)),
}
Error Handling ¶
API errors are returned as *Error with the HTTP status code and response body. Use errors.As to inspect them:
task, err := client.GetTask(ctx, projectID, taskID)
if err != nil {
var apiErr *ticktick.Error
if errors.As(err, &apiErr) {
log.Printf("HTTP %d: %s", apiErr.StatusCode, apiErr.Body)
}
}
Index ¶
- Constants
- func Bool(v bool) *bool
- func Int(v int) *int
- func Int64(v int64) *int64
- func String(v string) *string
- type ChecklistItem
- type Client
- func (c *Client) CompleteTask(ctx context.Context, projectID, taskID string) error
- func (c *Client) CreateProject(ctx context.Context, req *CreateProjectRequest) (*Project, error)
- func (c *Client) CreateTask(ctx context.Context, req *CreateTaskRequest) (*Task, error)
- func (c *Client) DeleteProject(ctx context.Context, projectID string) error
- func (c *Client) DeleteTask(ctx context.Context, projectID, taskID string) error
- func (c *Client) GetProject(ctx context.Context, projectID string) (*Project, error)
- func (c *Client) GetProjectData(ctx context.Context, projectID string) (*ProjectData, error)
- func (c *Client) GetProjects(ctx context.Context) ([]Project, error)
- func (c *Client) GetTask(ctx context.Context, projectID, taskID string) (*Task, error)
- func (c *Client) UpdateProject(ctx context.Context, projectID string, req *UpdateProjectRequest) (*Project, error)
- func (c *Client) UpdateTask(ctx context.Context, taskID string, req *UpdateTaskRequest) (*Task, error)
- type Column
- type CreateChecklistItemRequest
- type CreateProjectRequest
- type CreateTaskRequest
- type Error
- type Option
- type Project
- type ProjectData
- type Task
- type Time
- type UpdateProjectRequest
- type UpdateTaskRequest
Examples ¶
Constants ¶
const ( PriorityNone = 0 PriorityLow = 1 PriorityMedium = 3 PriorityHigh = 5 )
Task priority levels.
const ( TaskStatusNormal = 0 TaskStatusCompleted = 2 )
Task completion status values.
const ( ChecklistStatusNormal = 0 ChecklistStatusCompleted = 1 )
ChecklistItem completion status values.
const ( ViewModeList = "list" ViewModeKanban = "kanban" ViewModeTimeline = "timeline" )
Project view modes.
const ( ProjectKindTask = "TASK" ProjectKindNote = "NOTE" )
Project kinds.
const ( TaskKindText = "TEXT" TaskKindNote = "NOTE" TaskKindChecklist = "CHECKLIST" )
Task kinds.
const ( PermissionRead = "read" PermissionWrite = "write" PermissionComment = "comment" )
Project permission levels.
const DefaultBaseURL = "https://api.ticktick.com"
DefaultBaseURL is the default base URL of the TickTick API.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type ChecklistItem ¶
type ChecklistItem struct {
ID string `json:"id"`
Title string `json:"title"`
Status int `json:"status"`
CompletedTime Time `json:"completedTime"`
IsAllDay bool `json:"isAllDay"`
SortOrder int64 `json:"sortOrder"`
StartDate Time `json:"startDate"`
TimeZone string `json:"timeZone"`
}
ChecklistItem represents a subtask within a task.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client manages communication with the TickTick Open API.
func NewClient ¶
NewClient creates a new TickTick API client with the given access token.
Example ¶
client := ticktick.NewClient("your-access-token")
projects, err := client.GetProjects(context.Background())
if err != nil {
// handle error
return
}
for _, p := range projects {
fmt.Println(p.Name)
}
Example (WithOptions) ¶
client := ticktick.NewClient("your-access-token",
ticktick.WithHTTPClient(&http.Client{
Timeout: 10 * time.Second,
}),
// Use Dida365 API (TickTick's Chinese version).
ticktick.WithBaseURL("https://api.dida365.com"),
)
projects, err := client.GetProjects(context.Background())
if err != nil {
// handle error
return
}
for _, p := range projects {
fmt.Println(p.Name)
}
func (*Client) CompleteTask ¶
CompleteTask marks a task as complete.
func (*Client) CreateProject ¶
CreateProject creates a new project.
Example ¶
client := ticktick.NewClient("your-access-token")
project, err := client.CreateProject(context.Background(), &ticktick.CreateProjectRequest{
Name: "Work Tasks",
Color: ticktick.String("#F18181"),
ViewMode: ticktick.String(ticktick.ViewModeList),
Kind: ticktick.String(ticktick.ProjectKindTask),
})
if err != nil {
// handle error
return
}
fmt.Println(project.ID)
func (*Client) CreateTask ¶
CreateTask creates a new task.
Example ¶
client := ticktick.NewClient("your-access-token")
task, err := client.CreateTask(context.Background(), &ticktick.CreateTaskRequest{
Title: "Buy groceries",
ProjectID: "project-id",
Priority: ticktick.Int(ticktick.PriorityHigh),
})
if err != nil {
// handle error
return
}
fmt.Println(task.ID)
Example (WithDetails) ¶
client := ticktick.NewClient("your-access-token")
task, err := client.CreateTask(context.Background(), &ticktick.CreateTaskRequest{
Title: "Weekly report",
ProjectID: "project-id",
Content: ticktick.String("Prepare and send the weekly status report"),
Desc: ticktick.String("Include metrics from dashboard"),
IsAllDay: ticktick.Bool(false),
StartDate: ticktick.NewTime(time.Date(2024, 1, 15, 9, 0, 0, 0, time.UTC)),
DueDate: ticktick.NewTime(time.Date(2024, 1, 15, 17, 0, 0, 0, time.UTC)),
TimeZone: ticktick.String("America/New_York"),
// Reminders use iCalendar TRIGGER format.
// "TRIGGER:PT0S" — at the time of the event.
// "TRIGGER:P0DT9H0M0S" — 9 hours before.
// "TRIGGER:-PT30M" — 30 minutes before.
Reminders: []string{"TRIGGER:PT0S", "TRIGGER:-PT30M"},
// RepeatFlag uses iCalendar RRULE format.
// "RRULE:FREQ=DAILY;INTERVAL=1" — every day.
// "RRULE:FREQ=WEEKLY;INTERVAL=2" — every 2 weeks.
// "RRULE:FREQ=MONTHLY;INTERVAL=1;BYDAY=1MO" — first Monday of each month.
RepeatFlag: ticktick.String("RRULE:FREQ=WEEKLY;INTERVAL=1"),
Priority: ticktick.Int(ticktick.PriorityMedium),
SortOrder: ticktick.Int64(100),
Items: []ticktick.CreateChecklistItemRequest{
{Title: "Gather metrics"},
{Title: "Write summary"},
{Title: "Send to team"},
},
})
if err != nil {
// handle error
return
}
fmt.Println(task.ID)
func (*Client) DeleteProject ¶
DeleteProject deletes a project.
func (*Client) DeleteTask ¶
DeleteTask deletes a task.
func (*Client) GetProject ¶
GetProject retrieves a project by ID.
func (*Client) GetProjectData ¶
GetProjectData retrieves a project along with its tasks and columns.
Example ¶
client := ticktick.NewClient("your-access-token")
data, err := client.GetProjectData(context.Background(), "project-id")
if err != nil {
// handle error
return
}
fmt.Printf("Project: %s\n", data.Project.Name)
for _, task := range data.Tasks {
fmt.Printf(" Task: %s (priority=%d)\n", task.Title, task.Priority)
}
for _, col := range data.Columns {
fmt.Printf(" Column: %s\n", col.Name)
}
func (*Client) GetProjects ¶
GetProjects returns all projects for the authenticated user.
func (*Client) GetTask ¶
GetTask retrieves a task by project ID and task ID.
Example (ErrorHandling) ¶
client := ticktick.NewClient("your-access-token")
task, err := client.GetTask(context.Background(), "project-id", "task-id")
if err != nil {
var apiErr *ticktick.Error
if errors.As(err, &apiErr) {
fmt.Printf("API error: HTTP %d: %s\n", apiErr.StatusCode, apiErr.Body)
return
}
// Network or other error.
fmt.Printf("unexpected error: %v\n", err)
return
}
fmt.Println(task.Title)
func (*Client) UpdateProject ¶
func (c *Client) UpdateProject(ctx context.Context, projectID string, req *UpdateProjectRequest) (*Project, error)
UpdateProject updates an existing project.
func (*Client) UpdateTask ¶
func (c *Client) UpdateTask(ctx context.Context, taskID string, req *UpdateTaskRequest) (*Task, error)
UpdateTask updates an existing task.
Example ¶
client := ticktick.NewClient("your-access-token")
task, err := client.UpdateTask(context.Background(), "task-id", &ticktick.UpdateTaskRequest{
ID: "task-id",
ProjectID: "project-id",
Title: ticktick.String("Updated title"),
Priority: ticktick.Int(ticktick.PriorityLow),
DueDate: ticktick.NewTime(time.Date(2024, 2, 1, 12, 0, 0, 0, time.UTC)),
})
if err != nil {
// handle error
return
}
fmt.Println(task.Title)
type Column ¶
type Column struct {
ID string `json:"id"`
ProjectID string `json:"projectId"`
Name string `json:"name"`
SortOrder int64 `json:"sortOrder"`
}
Column represents a kanban column within a project.
type CreateChecklistItemRequest ¶
type CreateChecklistItemRequest struct {
Title string `json:"title"`
StartDate *Time `json:"startDate,omitempty"`
IsAllDay *bool `json:"isAllDay,omitempty"`
SortOrder *int64 `json:"sortOrder,omitempty"`
TimeZone *string `json:"timeZone,omitempty"`
Status *int `json:"status,omitempty"`
CompletedTime *Time `json:"completedTime,omitempty"`
}
CreateChecklistItemRequest contains the fields for a subtask in a create or update request.
type CreateProjectRequest ¶
type CreateProjectRequest struct {
Name string `json:"name"`
Color *string `json:"color,omitempty"`
SortOrder *int64 `json:"sortOrder,omitempty"`
ViewMode *string `json:"viewMode,omitempty"`
Kind *string `json:"kind,omitempty"`
}
CreateProjectRequest contains the fields for creating a new project.
type CreateTaskRequest ¶
type CreateTaskRequest struct {
Title string `json:"title"`
ProjectID string `json:"projectId"`
Content *string `json:"content,omitempty"`
Desc *string `json:"desc,omitempty"`
IsAllDay *bool `json:"isAllDay,omitempty"`
StartDate *Time `json:"startDate,omitempty"`
DueDate *Time `json:"dueDate,omitempty"`
TimeZone *string `json:"timeZone,omitempty"`
Reminders []string `json:"reminders,omitzero"`
RepeatFlag *string `json:"repeatFlag,omitempty"`
Priority *int `json:"priority,omitempty"`
SortOrder *int64 `json:"sortOrder,omitempty"`
Items []CreateChecklistItemRequest `json:"items,omitzero"`
}
CreateTaskRequest contains the fields for creating a new task.
type Option ¶
type Option func(*Client)
Option configures a Client.
func WithHTTPClient ¶
WithHTTPClient sets a custom HTTP client.
type Project ¶
type Project struct {
ID string `json:"id"`
Name string `json:"name"`
Color string `json:"color"`
SortOrder int64 `json:"sortOrder"`
Closed bool `json:"closed"`
GroupID string `json:"groupId"`
ViewMode string `json:"viewMode"`
Permission string `json:"permission"`
Kind string `json:"kind"`
}
Project represents a TickTick project.
type ProjectData ¶
type ProjectData struct {
Project Project `json:"project"`
Tasks []Task `json:"tasks"`
Columns []Column `json:"columns"`
}
ProjectData holds a project along with its tasks and columns.
type Task ¶
type Task struct {
ID string `json:"id"`
ProjectID string `json:"projectId"`
Title string `json:"title"`
IsAllDay bool `json:"isAllDay"`
CompletedTime Time `json:"completedTime"`
Content string `json:"content"`
Desc string `json:"desc"`
DueDate Time `json:"dueDate"`
Items []ChecklistItem `json:"items"`
Priority int `json:"priority"`
Reminders []string `json:"reminders"`
RepeatFlag string `json:"repeatFlag"`
SortOrder int64 `json:"sortOrder"`
StartDate Time `json:"startDate"`
Status int `json:"status"`
TimeZone string `json:"timeZone"`
Kind string `json:"kind"`
}
Task represents a TickTick task.
type Time ¶
Time wraps time.Time with custom JSON marshaling for the TickTick API date format.
func NewTime ¶
NewTime creates a pointer to a Time value. Useful for optional date fields in request types.
func (Time) MarshalJSON ¶
MarshalJSON serializes a Time to JSON using the TickTick date format. A zero Time marshals to an empty string.
func (*Time) UnmarshalJSON ¶
UnmarshalJSON deserializes a Time from JSON. It handles the standard TickTick date string format, date strings with fractional seconds, Unix millisecond timestamps (used in some checklist item fields), empty strings, and null values.
type UpdateProjectRequest ¶
type UpdateProjectRequest struct {
Name *string `json:"name,omitempty"`
Color *string `json:"color,omitempty"`
SortOrder *int64 `json:"sortOrder,omitempty"`
ViewMode *string `json:"viewMode,omitempty"`
Kind *string `json:"kind,omitempty"`
}
UpdateProjectRequest contains the fields for updating an existing project.
type UpdateTaskRequest ¶
type UpdateTaskRequest struct {
ID string `json:"id"`
ProjectID string `json:"projectId"`
Title *string `json:"title,omitempty"`
Content *string `json:"content,omitempty"`
Desc *string `json:"desc,omitempty"`
IsAllDay *bool `json:"isAllDay,omitempty"`
StartDate *Time `json:"startDate,omitempty"`
DueDate *Time `json:"dueDate,omitempty"`
TimeZone *string `json:"timeZone,omitempty"`
Reminders []string `json:"reminders,omitzero"`
RepeatFlag *string `json:"repeatFlag,omitempty"`
Priority *int `json:"priority,omitempty"`
SortOrder *int64 `json:"sortOrder,omitempty"`
Items []CreateChecklistItemRequest `json:"items,omitzero"`
}
UpdateTaskRequest contains the fields for updating an existing task.