Overview
llms.md
LLM API Reference
TaskWorks API for LLMs
Comprehensive reference for integrating TaskWorks API with LLM applications.
# TaskWorks API for LLMs
This document provides a comprehensive reference for integrating TaskWorks API with LLM applications. All endpoints return user-specific data only (RLS-protected).
## Authentication
### ApiKey Authentication (Recommended for LLMs)
```
Authorization: ApiKey <token>
```
- Generate API key from Settings > API Key Management
- Token is shown only once, keep it secure
- Works for most endpoints
### Bearer Token Authentication
```
Authorization: Bearer <token>
```
- Used for service-to-service communication
- Required for some endpoints (e.g., /api/v1/blocks/windows)
### Cookie Authentication
- Standard session-based authentication
- Used by web client
- Required for cookie-only endpoints
## Common Response Format
All successful responses follow this structure:
```json
{
"data": <response_data>,
"error": null
}
```
All error responses follow this structure:
```json
{
"error": "<error_type>",
"message": "<human_readable_message>",
"code": "<optional_error_code>",
"context": <optional_additional_context>
}
```
## HTTP Status Codes
- 200: Success
- 201: Created
- 400: Bad Request (validation error)
- 401: Unauthorized (authentication required)
- 403: Forbidden (permission denied)
- 404: Not Found
- 409: Conflict (resource conflict)
- 500: Internal Server Error
## Pagination
Some endpoints support cursor-based pagination:
- cursor: Starting point for next page
- limit: Number of items to return (1-100, default varies)
Response format:
```json
{
"data": {
"items": [...],
"nextCursor": "string | null",
"hasMore": boolean
},
"error": null
}
```
## API Endpoints
### Auth
#### GET /api/v1/auth/me
Get current authenticated user information.
Authentication: ApiKey / Bearer / Cookie
Response Schema:
```json
{
"data": {
"id": "string",
"userId": "string",
"email": "string",
"name": "string"
},
"error": null
}
```
Response Example:
```json
{
"data": {
"id": "user_123",
"userId": "user_123",
"email": "user@example.com",
"name": "John Doe"
},
"error": null
}
```
Error Cases:
- 401: Authentication required
#### GET /api/v1/auth/api-keys
List user's API keys.
Authentication: Cookie only
Response Schema:
```json
{
"data": [
{
"id": "string",
"name": "string | null",
"scope": "string",
"revoked": boolean,
"expiresAt": "string | null",
"lastUsedAt": "string | null",
"createdAt": "string"
}
],
"error": null
}
```
#### POST /api/v1/auth/api-keys
Create a new API key.
Authentication: Cookie only
Request Body:
```json
{
"name": "string | null",
"scope": "string",
"expiresAt": "string | null"
}
```
Response Schema:
```json
{
"data": {
"id": "string",
"key": "string",
"name": "string | null",
"scope": "string",
"expiresAt": "string | null",
"createdAt": "string"
},
"error": null
}
```
#### DELETE /api/v1/auth/api-keys
Revoke an API key.
Authentication: Cookie only
Query Parameters:
- id: string (required) - API key ID to revoke
#### POST /api/v1/auth/api-keys/verify
Verify if an API key is valid.
Authentication: Cookie only
Request Body:
```json
{
"key": "string"
}
```
Response Schema:
```json
{
"data": {
"valid": boolean,
"userId": "string | null"
},
"error": null
}
```
### Tasks
#### GET /api/v1/tasks
Get all tasks for authenticated user.
Authentication: ApiKey / Bearer / Cookie
Query Parameters:
- active: boolean (optional) - Filter by active status
- kind: string (optional) - Filter by task kind ("single" | "habit")
Response Schema:
```json
{
"data": [
{
"id": "string",
"title": "string",
"description": "string | null",
"kind": "single" | "habit",
"active": boolean,
"start_date": "string | null",
"end_date": "string | null",
"created_at": "string",
"updated_at": "string",
"period_rules": Array<PeriodRule>,
"time_rules": Array<TimeRule>,
"tags": Array<{ "id": string, "name": string }>
}
],
"error": null
}
```
#### POST /api/v1/tasks
Create a new task.
Authentication: ApiKey / Bearer / Cookie
Request Body:
```json
{
"title": "string (required)",
"description": "string | null",
"kind": "single" | "habit",
"active": boolean,
"start_date": "string | null",
"end_date": "string | null"
}
```
Response Schema:
```json
{
"data": {
"id": "string",
"title": "string",
"description": "string | null",
"kind": "single" | "habit",
"active": boolean,
"start_date": "string | null",
"end_date": "string | null",
"created_at": "string",
"updated_at": "string",
"period_rules": Array<PeriodRule>,
"time_rules": Array<TimeRule>
},
"error": null
}
```
Error Cases:
- 400: Title is required
#### GET /api/v1/tasks/today
Get today's tasks with time slots.
Authentication: ApiKey / Bearer / Cookie
Query Parameters:
- date: string (optional, ISO 8601 format, e.g., "2025-01-17")
- timezone: string (optional, default: "Asia/Tokyo")
Response Schema:
```json
{
"data": {
"date": "string",
"timezone": "string",
"tasks": [
{
"taskId": "string",
"slotId": "string",
"title": "string",
"kind": "single" | "habit",
"tags": Array<string>,
"timeLabel": "string",
"anytime": boolean,
"startTime": "string | null",
"endTime": "string | null",
"target": number,
"completed": number,
"remaining": number,
"status": "todo" | "done" | "skipped",
"sortMinutes": number
}
]
},
"error": null
}
```
Error Cases:
- 400: Invalid date format
- 401: Authentication required
#### GET /api/v1/tasks/overview
Get task overview with statistics.
Authentication: ApiKey / Bearer / Cookie
Query Parameters:
- date: string (optional, ISO 8601 format)
- timezone: string (optional, default: "Asia/Tokyo")
Response Schema:
```json
{
"data": {
"date": "string",
"timezone": "string",
"today": Array<TodayTaskRow>,
"stats": {
"totalTasks": number,
"completedTasks": number,
"remainingTasks": number,
"completionRate": number
}
},
"error": null
}
```
#### GET /api/v1/tasks/search
Search tasks by keyword.
Authentication: ApiKey / Bearer / Cookie
Query Parameters:
- q: string (required) - Search keyword
- limit: number (optional, 1-50, default: 8)
Response Schema:
```json
{
"data": [
{
"id": "string",
"title": "string",
"description": "string | null",
"kind": "single" | "habit"
}
],
"error": null
}
```
Error Cases:
- 400: Search keyword is required or limit is invalid
#### GET /api/v1/tasks/streak
Get current streak count.
Authentication: ApiKey / Bearer / Cookie
Response Schema:
```json
{
"data": {
"current": number,
"longest": number,
"breakDate": "string | null"
},
"error": null
}
```
Note: Returns 0 for current/longest if unauthenticated.
#### GET /api/v1/tasks/:id
Get specific task details.
Authentication: ApiKey / Bearer / Cookie
Path Parameters:
- id: string (required) - Task ID
Response Schema:
```json
{
"data": {
"id": "string",
"title": "string",
"description": "string | null",
"kind": "single" | "habit",
"active": boolean,
"start_date": "string | null",
"end_date": "string | null",
"period_rules": Array<PeriodRule>,
"time_rules": Array<TimeRule>,
"tags": Array<{ "id": string, "name": string }>
},
"error": null
}
```
#### PUT /api/v1/tasks/:id
Update a specific task.
Authentication: ApiKey / Bearer / Cookie
Path Parameters:
- id: string (required) - Task ID
Request Body:
```json
{
"title": "string",
"description": "string | null",
"kind": "single" | "habit",
"active": boolean,
"start_date": "string | null",
"end_date": "string | null"
}
```
Response Schema: Same as GET /api/v1/tasks/:id
#### DELETE /api/v1/tasks/:id
Delete a specific task.
Authentication: ApiKey / Bearer / Cookie
Path Parameters:
- id: string (required) - Task ID
Response Schema:
```json
{
"data": {
"success": true
},
"error": null
}
```
#### POST /api/v1/tasks/:id/execute
Log task execution and award cat cans.
Authentication: ApiKey / Bearer / Cookie
Path Parameters:
- id: string (required) - Task ID
Request Body:
```json
{
"qty": number (optional, default: 1)
}
```
Response Schema:
```json
{
"data": {
"success": boolean,
"qty": number,
"rewardTotal": number,
"rewardErrors": Array<{ "source": string, "message": string }>,
"streakDays": number
},
"error": null
}
```
#### POST /api/v1/tasks/:id/skip
Skip a task with reason.
Authentication: ApiKey / Bearer / Cookie
Path Parameters:
- id: string (required) - Task ID
Request Body:
```json
{
"reason": "string",
"scheduled_date": "string"
}
```
Response Schema:
```json
{
"data": {
"id": "string",
"task_id": "string",
"reason": "string",
"scheduled_date": "string",
"skipped_at": "string"
},
"error": null
}
```
#### DELETE /api/v1/tasks/:id/skip
Cancel a task skip.
Authentication: ApiKey / Bearer / Cookie
Path Parameters:
- id: string (required) - Task ID
Response Schema:
```json
{
"data": {
"success": true
},
"error": null
}
```
### Habits
#### GET /api/v1/habits/dashboard
Get habit dashboard data.
Authentication: ApiKey / Bearer / Cookie
Query Parameters:
- year: number (optional, 2020-2030, default: current year)
- month: number (optional, 1-12, default: current month)
Response Schema:
```json
{
"data": {
"summary": {
"year": number,
"month": number,
"days": Array<{ "date": string, "done": boolean }>
},
"dayStats": Record<string, {
"required": number,
"completedTasks": number,
"done": boolean
}>,
"completionRate": number,
"totals": {
"trackedDays": number,
"doneDays": number,
"remainingDays": number
},
"today": {
"required": number,
"completed": number,
"percentage": number
},
"streak": {
"current": number,
"longest": number,
"breakDate": "string | null"
},
"timezone": "string",
"taskCount": number,
"isCurrentMonth": boolean
},
"error": null
}
```
Error Cases:
- 400: Invalid year (must be 2020-2030) or month (must be 1-12)
- 401: Authentication required
### Evaluations (Pomodoro)
#### POST /api/v1/evaluations/submit
Submit pomodoro evaluation (concentration, mood).
Authentication: ApiKey / Bearer / Cookie
Request Body:
```json
{
"task_id": "string (required)",
"concentration_level": -2 | -1 | 0 | 1 | 2,
"mood_level": -2 | -1 | 0 | 1 | 2,
"has_comment": boolean,
"comment_text": "string | null",
"pomodoro_session_id": "string | null",
"execute_task": boolean,
"task_qty": number
}
```
Response Schema:
```json
{
"data": {
"id": "string",
"user_id": "string",
"task_id": "string | null",
"pomodoro_session_id": "string | null",
"happened_at": "string",
"concentration_level": -2 | -1 | 0 | 1 | 2,
"mood_level": -2 | -1 | 0 | 1 | 2,
"has_comment": boolean,
"comment_text": "string | null"
},
"task_execution": {
"qty": number,
"rewardTotal": number,
"streakDays": number,
"bonusAmount": number,
"rewardErrors": Array<{ "source": string, "message": string }>,
"hasRewardFailure": boolean
},
"error": null
}
```
Error Cases:
- 400: task_id is required, concentration_level or mood_level out of range (-2 to 2)
- 403: Permission denied for task execution
#### GET /api/v1/evaluations/last-task
Get last task for default selection.
Authentication: ApiKey / Bearer / Cookie
Response Schema:
```json
{
"data": {
"task_id": "string",
"task_title": "string",
"selected_at": "string"
},
"error": null
}
```
#### POST /api/v1/evaluations/unanswered
Record unanswered pomodoro evaluations.
Authentication: ApiKey / Bearer / Cookie
Request Body:
```json
{
"events": Array<{
"id": "string",
"user_id": "string",
"task_id": "string | null",
"pomodoro_session_id": "string | null",
"happened_at": "string",
"reason": "ignored" | "closed" | "cancelled"
}>
}
```
Response Schema:
```json
{
"data": {
"success": true,
"count": number
},
"error": null
}
```
### Analytics
#### GET /api/v1/analytics/monthly-comparison
Compare monthly data for trends.
Authentication: ApiKey / Bearer / Cookie
Query Parameters:
- months: number (optional, default: 3)
Response Schema:
```json
{
"data": {
"months": [
{
"year": number,
"month": number,
"completionRate": number,
"avgConcentration": number | null,
"avgMood": number | null,
"streak": { "current": number, "longest": number }
}
],
"trends": {
"completionRate": "improving" | "declining" | "stable",
"concentration": "improving" | "declining" | "stable",
"mood": "improving" | "declining" | "stable"
},
"insights": Array<string>
},
"error": null
}
```
#### GET /api/v1/analytics/daily-averages
Get daily concentration/mood averages.
Authentication: ApiKey / Bearer / Cookie
Query Parameters:
- days: number (optional)
- timezone: string (optional, default: "Asia/Tokyo")
- includeTasks: boolean (optional)
Response Schema:
```json
{
"data": {
"overall": Array<{
"date": "string",
"avg_concentration": number | null,
"avg_mood": number | null,
"answer_count": number,
"unanswered_count": number
}>,
"tasks": Record<string, {
"taskTitle": "string",
"data": Array<DailyAverage>
}> | null
},
"error": null
}
```
#### GET /api/v1/analytics/task-completion-grid
Get task completion heatmap data.
Authentication: ApiKey / Bearer / Cookie
Query Parameters:
- days: number (optional)
- timezone: string (optional, default: "Asia/Tokyo")
Response Schema:
```json
{
"data": Array<{
"date": "string",
"task_id": "string",
"task_title": "string",
"status": "not_scheduled" | "completed" | "not_completed",
"target_count": number,
"completed_count": number,
"time_slots": Array<TimeSlotSummary> | null
}>,
"dates": Array<string>,
"tasks": Array<{ "id": string, "title": string }>,
"error": null
}
```
#### GET /api/v1/analytics/task-day-detail
Get detailed task data for specific day.
Authentication: ApiKey / Bearer / Cookie
Query Parameters:
- date: string (required, ISO 8601 format)
- timezone: string (optional, default: "Asia/Tokyo")
Response Schema:
```json
{
"data": {
"date": "string",
"tasks": Array<{
"task_id": "string",
"task_title": "string",
"status": "not_scheduled" | "completed" | "not_completed",
"target_count": number,
"completed_count": number,
"answer_events": Array<{
"id": "string",
"happened_at": "string",
"concentration_level": -2 | -1 | 0 | 1 | 2,
"mood_level": -2 | -1 | 0 | 1 | 2,
"comment_text": "string | null"
}>,
"comments": Array<string>,
"ai_prediction": {
"broad_category": "string",
"specific_reason": "string",
"suggestion": "string | null",
"confidence": number | null
} | null
}>
},
"error": null
}
```
#### GET /api/v1/analytics/daily-detail
Get daily detail analysis via RPC.
Authentication: ApiKey / Bearer / Cookie
Query Parameters:
- date: string (required, ISO 8601 format)
- timezone: string (optional, default: "Asia/Tokyo")
Response Schema:
```json
{
"data": {
"date": "string",
"avg_concentration": number | null,
"avg_mood": number | null,
"answer_events": Array<{
"id": "string",
"happened_at": "string",
"task_id": "string | null",
"task_title": "string | null",
"concentration_level": -2 | -1 | 0 | 1 | 2,
"mood_level": -2 | -1 | 0 | 1 | 2,
"comment_text": "string | null"
}>,
"comments": Array<{
"id": "string",
"happened_at": "string",
"task_title": "string | null",
"text": "string"
}>,
"unanswered_count": number,
"unanswered_events": Array<{
"id": "string",
"happened_at": "string",
"reason": "ignored" | "closed" | "cancelled",
"task_title": "string | null"
}>
},
"error": null
}
```
### Pomodoro
#### GET /api/v1/pomodoro
Get active pomodoro session.
Authentication: ApiKey / Bearer / Cookie
Response Schema:
```json
{
"data": {
"id": "string",
"user_id": "string",
"task_id": "string | null",
"session_type": "work" | "short_break" | "long_break",
"duration_minutes": number,
"started_at": "string",
"scheduled_end_at": "string",
"actual_end_at": "string | null",
"status": "active" | "completed" | "cancelled",
"notification_sent": boolean,
"evaluation_submitted": boolean,
"created_at": "string",
"updated_at": "string"
} | null,
"error": null
}
```
#### POST /api/v1/pomodoro
Start new pomodoro session.
Authentication: ApiKey / Bearer / Cookie
Request Body:
```json
{
"task_id": "string | null",
"session_type": "work" | "short_break" | "long_break",
"duration_minutes": number (required, positive)
}
```
Response Schema:
```json
{
"data": {
"id": "string",
"user_id": "string",
"task_id": "string | null",
"session_type": "work" | "short_break" | "long_break",
"duration_minutes": number,
"started_at": "string",
"scheduled_end_at": "string",
"status": "active",
"notification_sent": false,
"evaluation_submitted": false,
"created_at": "string",
"updated_at": "string"
},
"error": null
}
```
Error Cases:
- 400: duration_minutes is required and must be positive
#### POST /api/v1/pomodoro/:id/complete
Complete a pomodoro session.
Authentication: ApiKey / Bearer / Cookie
Path Parameters:
- id: string (required) - Session ID
Response Schema:
```json
{
"data": {
"id": "string",
"actual_end_at": "string",
"status": "completed"
},
"error": null
}
```
#### DELETE /api/v1/pomodoro/:id/cancel
Cancel a pomodoro session.
Authentication: ApiKey / Bearer / Cookie
Path Parameters:
- id: string (required) - Session ID
Response Schema:
```json
{
"data": {
"id": "string",
"status": "cancelled"
},
"error": null
}
```
### AI
#### POST /api/v1/ai/chat
Chat with AI assistant (LLM).
Authentication: ApiKey / Bearer / Cookie
Request Body:
```json
{
"question": "string (required)",
"context": {
"year": number,
"month": number,
"completionRate": number,
"streak": number,
"taskCount": number,
"habitDashboard": Object,
"monthlyComparison": Object,
"concentrationMoodData": Array<Object>,
"habitsMatrix": Object
} | {},
"messages": Array<{
"role": "user" | "assistant",
"content": "string",
"timestamp": "string"
}>
}
```
Response Schema:
```json
{
"data": {
"answer": "string",
"messages": Array<{
"role": "user" | "assistant",
"content": "string",
"timestamp": "string"
}>
},
"error": null
}
```
Error Cases:
- 400: Question is required or empty
- 400: No available LLM provider configuration
- 503: LLM configuration table not created
#### GET /api/v1/ai/report
Get saved AI habit report.
Authentication: ApiKey / Bearer / Cookie
Query Parameters:
- providerId: string (optional)
Response Schema:
```json
{
"data": {
"id": "string",
"year": number,
"month": number,
"content": "string",
"providerName": "string",
"providerKind": "openai" | "anthropic" | "azure-openai" | "openrouter" | "custom-openai",
"generatedAt": "string",
"createdAt": "string",
"updatedAt": "string"
},
"error": null
}
```
#### POST /api/v1/ai/report
Generate AI habit analysis report.
Authentication: ApiKey / Bearer / Cookie
Request Body:
```json
{
"providerId": "string | null",
"useOfficial": boolean,
"year": number,
"month": number
}
```
Response Schema:
```json
{
"data": {
"content": "string",
"generatedAt": "string",
"providerName": "string",
"providerKind": "openai" | "anthropic" | "azure-openai" | "openrouter" | "custom-openai"
},
"error": null
}
```
#### GET /api/v1/ai/providers
List LLM provider configurations.
Authentication: ApiKey / Bearer / Cookie
Response Schema:
```json
{
"data": [
{
"id": "string",
"name": "string",
"kind": "openai" | "anthropic" | "azure-openai" | "openrouter" | "custom-openai",
"apiKey": "string",
"isDefault": boolean,
"model": "string | null",
"maxTokens": number | null,
"temperature": number | null
}
],
"error": null
}
```
#### POST /api/v1/ai/providers
Create/update LLM provider configuration.
Authentication: ApiKey / Bearer / Cookie
Request Body:
```json
{
"id": "string | null",
"name": "string",
"kind": "openai" | "anthropic" | "azure-openai" | "openrouter" | "custom-openai",
"apiKey": "string",
"isDefault": boolean,
"model": "string | null",
"maxTokens": number | null,
"temperature": number | null
}
```
Response Schema: Same as GET /api/v1/ai/providers (single item in array)
#### DELETE /api/v1/ai/providers
Delete LLM provider configuration.
Authentication: ApiKey / Bearer / Cookie
Request Body:
```json
{
"providerId": "string (required)"
}
```
Response Schema:
```json
{
"data": {
"success": true
},
"error": null
}
```
#### POST /api/v1/ai/daily-reflection
Generate daily reflection with AI.
Authentication: ApiKey / Bearer / Cookie
Request Body:
```json
{
"question": "string",
"context": Object,
"providerId": "string | null"
}
```
Response Schema:
```json
{
"data": {
"reflection": "string",
"generatedAt": "string"
},
"error": null
}
```
### Gacha
#### POST /api/v1/gacha/draw
Draw gacha (single or ten pull).
Authentication: ApiKey / Bearer / Cookie
Request Body:
```json
{
"gacha": {
"id": "string (required)",
"name": "string (required)",
"cost": {
"single": number (required, non-negative),
"ten": number (required, non-negative)
}
},
"drawType": "single" | "ten"
}
```
Response Schema:
```json
{
"data": {
"result": {
"id": "string",
"gachaId": "string",
"gachaName": "string",
"drawType": "single" | "ten",
"cards": [
{
"image": "string",
"rarity": "normal" | "rare" | "ultra" | null,
"clip": "stage" | "supporter" | "trainer" | null
}
],
"featuredIndex": number,
"cost": number,
"recordedAt": "string"
},
"catCanBalance": number,
"catCanDelta": number,
"ledgerId": "string"
},
"error": null
}
```
#### GET /api/v1/gacha/draw
Get latest draw result and balance.
Authentication: ApiKey / Bearer / Cookie
Response Schema:
```json
{
"data": {
"result": Object | null,
"catCanBalance": number
},
"error": null
}
```
#### GET /api/v1/gacha/inventory
Get gacha inventory (owned items).
Authentication: ApiKey / Bearer / Cookie
Query Parameters:
- limit: number (optional)
Response Schema:
```json
{
"data": {
"cards": [
{
"image": "string",
"rarity": "normal" | "rare" | "ultra" | null,
"clip": "stage" | "supporter" | "trainer" | null,
"count": number,
"latestRecordedAt": "string",
"latestGachaName": "string",
"accentFrom": "string | null"
}
],
"totalUnique": number,
"totalCount": number
},
"error": null
}
```
#### GET /api/v1/gacha/history
Get gacha draw history (paginated).
Authentication: ApiKey / Bearer / Cookie
Query Parameters:
- limit: number (optional)
- cursor: string (optional)
Response Schema:
```json
{
"data": {
"items": [
{
"id": "string",
"gachaId": "string",
"gachaName": "string",
"drawType": "single" | "ten",
"cards": Array<Object>,
"featuredIndex": number,
"cost": number,
"recordedAt": "string"
}
],
"nextCursor": "string | null",
"hasMore": boolean
},
"error": null
}
```
### Notifications
#### POST /api/v1/notifications/send
Send test notification via FCM.
Authentication: Cookie only
Request Body:
```json
{
"title": "string",
"body": "string",
"data": Object
}
```
Response Schema:
```json
{
"data": {
"success": boolean,
"messageId": "string | null"
},
"error": null
}
```
#### GET /api/v1/notifications/token
Get active FCM tokens for user.
Authentication: Cookie only
Response Schema:
```json
{
"data": [
{
"id": "string",
"token": "string",
"isActive": boolean,
"deviceInfo": Object | null,
"lastSeenAt": "string | null",
"createdAt": "string"
}
],
"error": null
}
```
#### POST /api/v1/notifications/token
Register/update FCM push token.
Authentication: Cookie only
Request Body:
```json
{
"token": "string (required)",
"deviceInfo": Object | null
}
```
Response Schema:
```json
{
"data": {
"id": "string",
"token": "string",
"isActive": boolean,
"createdAt": "string"
},
"error": null
}
```
#### DELETE /api/v1/notifications/token
Deactivate FCM push token.
Authentication: Cookie only
Request Body:
```json
{
"token": "string (required)"
}
```
Response Schema:
```json
{
"data": {
"success": true
},
"error": null
}
```
### Communities
#### GET /api/v1/communities
List all communities (public).
Authentication: None (public)
Response Schema:
```json
{
"data": [
{
"id": "string",
"name": "string",
"description": "string",
"icon_url": "string | null",
"background_url": "string | null",
"url": "string | null",
"member_count": number | null,
"help_count": number | null,
"registration_status": "string | null",
"language": "string | null",
"category": "string | null",
"created_at": "string | null",
"updated_at": "string | null"
}
],
"error": null
}
```
#### GET /api/v1/communities?communityId=:id
Get specific community with posts (public).
Authentication: None (public)
Query Parameters:
- communityId: string (required) - Community ID
Response Schema:
```json
{
"data": {
"community": Object,
"posts": Array<CommunityPost>
},
"error": null
}
```
#### POST /api/v1/communities
Create new community.
Authentication: Cookie only
Request Body:
```json
{
"name": "string (required)",
"description": "string",
"icon_url": "string | null",
"background_url": "string | null",
"category": "string | null",
"language": "string | null"
}
```
Response Schema:
```json
{
"data": {
"id": "string",
"name": "string",
"description": "string",
"createdAt": "string"
},
"error": null
}
```
#### DELETE /api/v1/communities/:id
Delete community.
Authentication: Cookie + Admin privileges
Path Parameters:
- id: string (required) - Community ID
Response Schema:
```json
{
"data": {
"success": true
},
"error": null
}
```
Error Cases:
- 403: Forbidden (admin privileges required)
#### GET /api/v1/communities/me/avatar
Get user's community profile.
Authentication: Cookie only
Response Schema:
```json
{
"data": {
"id": "string",
"userId": "string",
"name": "string",
"handle": "string",
"avatarUrl": "string | null",
"bio": "string | null"
},
"error": null
}
```
#### PUT /api/v1/communities/me/avatar
Update user's community profile.
Authentication: Cookie only
Request Body:
```json
{
"name": "string",
"handle": "string",
"avatarUrl": "string | null",
"bio": "string | null"
}
```
Response Schema: Same as GET /api/v1/communities/me/avatar
#### POST /api/v1/communities/:id/join
Join community.
Authentication: Cookie only
Path Parameters:
- id: string (required) - Community ID
Response Schema:
```json
{
"data": {
"id": "string",
"communityId": "string",
"userId": "string",
"joinedAt": "string"
},
"error": null
}
```
#### DELETE /api/v1/communities/:id/join
Leave community.
Authentication: Cookie only
Path Parameters:
- id: string (required) - Community ID
Response Schema:
```json
{
"data": {
"success": true
},
"error": null
}
```
#### POST /api/v1/communities/:id/follow
Follow user within community.
Authentication: Cookie only
Path Parameters:
- id: string (required) - Community ID
Request Body:
```json
{
"followingId": "string (required)"
}
```
Response Schema:
```json
{
"data": {
"id": "string",
"communityId": "string",
"followerId": "string",
"followingId": "string",
"createdAt": "string"
},
"error": null
}
```
#### DELETE /api/v1/communities/:id/follow
Unfollow user within community.
Authentication: Cookie only
Path Parameters:
- id: string (required) - Community ID
Request Body:
```json
{
"followingId": "string (required)"
}
```
Response Schema:
```json
{
"data": {
"success": true
},
"error": null
}
```
#### POST /api/v1/communities/:id/posts
Create new post.
Authentication: Cookie only
Path Parameters:
- id: string (required) - Community ID
Request Body:
```json
{
"content": "string (required)",
"replyTo": "string | null",
"images": Array<Object> | null
}
```
Response Schema:
```json
{
"data": {
"post": {
"id": "string",
"author": {
"id": "string",
"name": "string",
"handle": "string",
"avatarUrl": "string | null"
},
"content": "string",
"createdAt": "string",
"updatedAt": "string | null",
"likesCount": number,
"repliesCount": number,
"repostsCount": number,
"isLiked": boolean,
"isReposted": boolean,
"communityId": "string",
"images": Array<Object> | null,
"replyTo": "string | null"
}
},
"error": null
}
```
#### GET /api/v1/communities/:id/posts/:postId
Get specific post with replies (public).
Authentication: None (public)
Path Parameters:
- id: string (required) - Community ID
- postId: string (required) - Post ID
Response Schema:
```json
{
"data": {
"post": CommunityPost,
"replies": Array<CommunityPost>
},
"error": null
}
```
#### DELETE /api/v1/communities/:id/posts/:postId
Delete post.
Authentication: Cookie + Owner or Admin privileges
Path Parameters:
- id: string (required) - Community ID
- postId: string (required) - Post ID
Response Schema:
```json
{
"data": {
"success": true
},
"error": null
}
```
Error Cases:
- 403: Forbidden (must be post owner or admin)
#### POST /api/v1/communities/:id/posts/:postId/reactions
Add like/repost reaction.
Authentication: Cookie only
Path Parameters:
- id: string (required) - Community ID
- postId: string (required) - Post ID
Request Body:
```json
{
"reactionType": "like" | "repost (required)"
}
```
Response Schema:
```json
{
"data": {
"id": "string",
"postId": "string",
"userId": "string",
"reactionType": "like" | "repost",
"createdAt": "string"
},
"error": null
}
```
#### DELETE /api/v1/communities/:id/posts/:postId/reactions
Remove like/repost reaction.
Authentication: Cookie only
Path Parameters:
- id: string (required) - Community ID
- postId: string (required) - Post ID
Request Body:
```json
{
"reactionType": "like" | "repost (required)"
}
```
Response Schema:
```json
{
"data": {
"success": true
},
"error": null
}
```
#### GET /api/v1/communities/:id/reports
List community reports (admin only).
Authentication: Cookie + Admin privileges
Path Parameters:
- id: string (required) - Community ID
Response Schema:
```json
{
"data": [
{
"id": "string",
"communityId": "string",
"postId": "string",
"reportedBy": "string",
"reason": "string",
"status": "pending" | "resolved" | "dismissed",
"createdAt": "string",
"updatedAt": "string | null"
}
],
"error": null
}
```
#### POST /api/v1/communities/:id/reports
Report a post.
Authentication: Cookie only
Path Parameters:
- id: string (required) - Community ID
Request Body:
```json
{
"postId": "string (required)",
"reason": "string (required)"
}
```
Response Schema:
```json
{
"data": {
"id": "string",
"communityId": "string",
"postId": "string",
"reportedBy": "string",
"reason": "string",
"status": "pending",
"createdAt": "string"
},
"error": null
}
```
#### PATCH /api/v1/communities/:id/reports/:reportId
Update report status (admin only).
Authentication: Cookie + Admin privileges
Path Parameters:
- id: string (required) - Community ID
- reportId: string (required) - Report ID
Request Body:
```json
{
"status": "resolved" | "dismissed (required)"
}
```
Response Schema:
```json
{
"data": {
"id": "string",
"status": "resolved" | "dismissed",
"updatedAt": "string"
},
"error": null
}
```
### Direct Messages (DM)
#### GET /api/v1/dm/threads
List DM threads.
Authentication: Cookie only
Response Schema:
```json
{
"data": [
{
"id": "string",
"userId": "string",
"friendId": "string",
"lastMessageAt": "string | null",
"unreadCount": number,
"friend": {
"id": "string",
"name": "string",
"handle": "string",
"avatarUrl": "string | null"
}
}
],
"error": null
}
```
#### POST /api/v1/dm/threads
Create new DM thread with friend.
Authentication: Cookie only
Request Body:
```json
{
"friendId": "string (required)"
}
```
Response Schema:
```json
{
"data": {
"id": "string",
"userId": "string",
"friendId": "string",
"createdAt": "string",
"friend": Object
},
"error": null
}
```
#### GET /api/v1/dm/threads/:threadId
Get thread messages.
Authentication: Cookie only
Path Parameters:
- threadId: string (required) - Thread ID
Response Schema:
```json
{
"data": {
"thread": Object,
"messages": [
{
"id": "string",
"threadId": "string",
"senderId": "string",
"content": "string",
"createdAt": "string",
"readAt": "string | null"
}
]
},
"error": null
}
```
#### POST /api/v1/dm/threads/:threadId/messages
Send message to thread.
Authentication: Cookie only
Path Parameters:
- threadId: string (required) - Thread ID
Request Body:
```json
{
"content": "string (required)"
}
```
Response Schema:
```json
{
"data": {
"id": "string",
"threadId": "string",
"senderId": "string",
"content": "string",
"createdAt": "string"
},
"error": null
}
```
#### POST /api/v1/dm/threads/:threadId/read
Mark thread as read.
Authentication: Cookie only
Path Parameters:
- threadId: string (required) - Thread ID
Response Schema:
```json
{
"data": {
"success": true
},
"error": null
}
```
#### GET /api/v1/dm/messages/:messageId
Get message details (for deletion).
Authentication: Cookie only
Path Parameters:
- messageId: string (required) - Message ID
Response Schema:
```json
{
"data": {
"id": "string",
"threadId": "string",
"senderId": "string",
"content": "string",
"createdAt": "string"
},
"error": null
}
```
### Friends
#### GET /api/v1/friends
List friends and friend requests.
Authentication: Cookie only
Response Schema:
```json
{
"data": {
"friends": Array<{
"id": "string",
"name": "string",
"handle": "string",
"avatarUrl": "string | null",
"friendsSince": "string"
}>,
"pendingRequests": Array<{
"id": "string",
"fromUser": Object,
"createdAt": "string"
}>,
"sentRequests": Array<{
"id": "string",
"toUser": Object,
"status": "pending" | "accepted" | "rejected",
"createdAt": "string"
}>
},
"error": null
}
```
#### POST /api/v1/friends/requests
Send friend request.
Authentication: Cookie only
Request Body:
```json
{
"recipientId": "string (required)"
}
```
Response Schema:
```json
{
"data": {
"id": "string",
"fromUserId": "string",
"toUserId": "string",
"status": "pending",
"createdAt": "string"
},
"error": null
}
```
#### PATCH /api/v1/friends/requests/:requestId
Accept/reject friend request.
Authentication: Cookie only
Path Parameters:
- requestId: string (required) - Request ID
Request Body:
```json
{
"action": "accept" | "reject (required)"
}
```
Response Schema:
```json
{
"data": {
"id": "string",
"status": "accepted" | "rejected",
"updatedAt": "string"
},
"error": null
}
```
### Realtime (WebRTC Video Rooms)
#### POST /api/v1/realtime/rooms
Create new voice/video room (uses WebRTC offer).
Authentication: None (uses WebRTC offer)
Request Body:
```json
{
"offer": Object (WebRTC offer)
}
```
Response Schema:
```json
{
"data": {
"roomId": "string",
"answer": Object (WebRTC answer)
},
"error": null
}
```
#### POST /api/v1/realtime/rooms/:roomId/session
Join existing room (uses WebRTC offer).
Authentication: None (uses WebRTC offer)
Path Parameters:
- roomId: string (required) - Room ID
Request Body:
```json
{
"offer": Object (WebRTC offer)
}
```
Response Schema:
```json
{
"data": {
"roomId": "string",
"answer": Object (WebRTC answer),
"participantId": "string"
},
"error": null
}
```
#### GET /api/v1/realtime/rooms/:roomId/state
Get room state.
Authentication: Cookie only
Path Parameters:
- roomId: string (required) - Room ID
Response Schema:
```json
{
"data": {
"roomId": "string",
"participants": Array<{
"id": "string",
"userId": "string",
"joinedAt": "string"
}>,
"activeTracks": Array<Object>,
"createdAt": "string",
"updatedAt": "string"
},
"error": null
}
```
#### POST /api/v1/realtime/rooms/:roomId/tracks/publish
Publish media track.
Authentication: Cookie only
Path Parameters:
- roomId: string (required) - Room ID
Request Body:
```json
{
"track": Object (WebRTC track data)
}
```
Response Schema:
```json
{
"data": {
"trackId": "string",
"publishedAt": "string"
},
"error": null
}
```
#### POST /api/v1/realtime/rooms/:roomId/tracks/subscribe
Subscribe to media track.
Authentication: Cookie only
Path Parameters:
- roomId: string (required) - Room ID
Request Body:
```json
{
"trackId": "string (required)"
}
```
Response Schema:
```json
{
"data": {
"subscribed": true,
"subscribedAt": "string"
},
"error": null
}
```
#### POST /api/v1/realtime/rooms/:roomId/renegotiate
Renegotiate WebRTC connection.
Authentication: Cookie only
Path Parameters:
- roomId: string (required) - Room ID
Request Body:
```json
{
"offer": Object (WebRTC offer)
}
```
Response Schema:
```json
{
"data": {
"answer": Object (WebRTC answer)
},
"error": null
}
```
#### POST /api/v1/realtime/communities/:communityId/spaces
List community spaces.
Authentication: Cookie only
Path Parameters:
- communityId: string (required) - Community ID
Response Schema:
```json
{
"data": [
{
"id": "string",
"communityId": "string",
"name": "string",
"roomId": "string | null",
"createdAt": "string"
}
],
"error": null
}
```
### Room Viewer (3D Room Customization)
#### GET /api/v1/room-viewer/cats
Get user's 3D room cats.
Authentication: Cookie only
Response Schema:
```json
{
"data": [
{
"id": "string",
"userId": "string",
"catId": "string",
"position": { "x": number, "y": number, "z": number },
"rotation": { "x": number, "y": number, "z": number },
"scale": { "x": number, "y": number, "z": number },
"createdAt": "string",
"updatedAt": "string"
}
],
"error": null
}
```
#### POST /api/v1/room-viewer/cats
Add cat to 3D room.
Authentication: Cookie only
Request Body:
```json
{
"catId": "string (required)",
"position": { "x": number, "y": number, "z": number },
"rotation": { "x": number, "y": number, "z": number },
"scale": { "x": number, "y": number, "z": number }
}
```
Response Schema:
```json
{
"data": {
"id": "string",
"userId": "string",
"catId": "string",
"position": Object,
"rotation": Object,
"scale": Object,
"createdAt": "string"
},
"error": null
}
```
#### PUT /api/v1/room-viewer/cats/:catId
Update cat position/rotation/scale.
Authentication: Cookie only
Path Parameters:
- catId: string (required) - Cat ID
Request Body:
```json
{
"position": { "x": number, "y": number, "z": number },
"rotation": { "x": number, "y": number, "z": number },
"scale": { "x": number, "y": number, "z": number }
}
```
Response Schema: Same as POST /api/v1/room-viewer/cats
#### DELETE /api/v1/room-viewer/cats/:catId
Remove cat from 3D room.
Authentication: Cookie only
Path Parameters:
- catId: string (required) - Cat ID
Response Schema:
```json
{
"data": {
"success": true
},
"error": null
}
```
#### GET /api/v1/room-viewer/screenshots
Get user's room screenshots.
Authentication: Cookie only
Response Schema:
```json
{
"data": [
{
"id": "string",
"userId": "string",
"imageUrl": "string",
"thumbnailUrl": "string",
"capturedAt": "string"
}
],
"error": null
}
```
#### POST /api/v1/room-viewer/screenshots
Save room screenshot.
Authentication: Cookie only
Request Body:
```json
{
"imageData": "string (required, base64)",
"thumbnailData": "string (optional, base64)"
}
```
Response Schema:
```json
{
"data": {
"id": "string",
"userId": "string",
"imageUrl": "string",
"thumbnailUrl": "string",
"capturedAt": "string"
},
"error": null
}
```
#### DELETE /api/v1/room-viewer/screenshots/:id
Delete screenshot.
Authentication: Cookie only
Path Parameters:
- id: string (required) - Screenshot ID
Response Schema:
```json
{
"data": {
"success": true
},
"error": null
}
```
#### GET /api/v1/room-viewer/settings
Get room viewer settings.
Authentication: Cookie only
Response Schema:
```json
{
"data": {
"id": "string",
"userId": "string",
"backgroundColor": "string | null",
"floorColor": "string | null",
"wallColor": "string | null",
"lightingIntensity": number,
"createdAt": "string",
"updatedAt": "string"
},
"error": null
}
```
#### PUT /api/v1/room-viewer/settings
Update room viewer settings.
Authentication: Cookie only
Request Body:
```json
{
"backgroundColor": "string | null",
"floorColor": "string | null",
"wallColor": "string | null",
"lightingIntensity": number
}
```
Response Schema: Same as GET /api/v1/room-viewer/settings
### Blocks
#### GET /api/v1/blocks/windows
Get task blocking windows for TaskWorks.
Authentication: Bearer / Session only (ApiKey NOT supported)
Query Parameters:
- date: string (optional, ISO 8601 format)
- timezone: string (optional, default: "UTC")
- focus_only: boolean (optional, default: false)
- merge: boolean (optional, default: false)
- debug: boolean (optional, default: false)
- pre_grace_min: number (optional, default: 0)
- post_grace_min: number (optional, default: 0)
- duration_default_min: number (optional, default: 60)
Response Schema (debug: false):
```json
{
"data": [
{
"taskId": "string",
"taskTitle": "string",
"startTime": "string",
"endTime": "string",
"redirectUrl": "string"
}
],
"error": null
}
```
Response Schema (debug: true):
```json
{
"data": [
/* Same window objects */
],
"meta": {
"dateIso": "string",
"timeZone": "string",
"focusOnly": boolean,
"mergeOverlaps": boolean,
"taskCount": number,
"completedTaskCount": number,
"completedCounts": Record<string, number>,
"windowCount": number
},
"error": null
}
```
Error Cases:
- 401: Unauthorized (ApiKey not supported)
- 401: User not found
## Data Schemas
### Period Rule
```json
{
"id": "string",
"cadence": "daily" | "weekly" | "monthly" | "interval",
"times_per_period": number | null,
"period": "string",
"days_of_week": Array<number> | null,
"timezone": "string"
}
```
### Time Rule
```json
{
"id": "string",
"start_time": "string | null",
"end_time": "string | null",
"anytime": boolean
}
```
### Community Post
```json
{
"id": "string",
"author": {
"id": "string",
"name": "string",
"handle": "string",
"avatarUrl": "string | null",
"bio": "string | null",
"followersCount": number,
"followingCount": number,
"postsCount": number,
"joinedAt": "string",
"isFollowing": boolean,
"isFriend": boolean
},
"content": "string",
"createdAt": "string",
"updatedAt": "string | null",
"likesCount": number,
"repliesCount": number,
"repostsCount": number,
"isLiked": boolean,
"isReposted": boolean,
"communityId": "string",
"images": Array<{
"id": "string",
"url": "string",
"alt": "string",
"width": number,
"height": number
}> | null,
"replyTo": "string | null",
"replies": Array<CommunityPost> | null
}
```
## Use Cases
### Creating and Completing a Task Flow
1. Create a task: POST /api/v1/tasks
2. Get today's tasks: GET /api/v1/tasks/today
3. Execute task: POST /api/v1/tasks/:id/execute
4. Submit evaluation: POST /api/v1/evaluations/submit
### Analyzing Task Completion Patterns
1. Get daily averages: GET /api/v1/analytics/daily-averages
2. Get task completion grid: GET /api/v1/analytics/task-completion-grid
3. Get monthly comparison: GET /api/v1/analytics/monthly-comparison
### Working with Habits
1. Get habit dashboard: GET /api/v1/habits/dashboard?year=2025&month=1
2. Get daily detail: GET /api/v1/analytics/daily-detail
### Pomodoro Workflow
1. Start session: POST /api/v1/pomodoro
2. Get active session: GET /api/v1/pomodoro
3. Complete session: POST /api/v1/pomodoro/:id/complete
4. Submit evaluation: POST /api/v1/evaluations/submit
### Gacha Operations
1. Get balance and latest result: GET /api/v1/gacha/draw
2. Draw single or ten: POST /api/v1/gacha/draw
3. View inventory: GET /api/v1/gacha/inventory
4. View history: GET /api/v1/gacha/history
## Fewshot Examples
### Python: Get Tomorrow's Tasks
```python
#!/usr/bin/env python3
"""
Get tomorrow's tasks from TaskWorks API.
Setup:
export TASKWORKS_API_KEY="YOUR_TOKEN"
pip install requests
"""
import os
import requests
from datetime import datetime, timedelta
DEFAULT_BASE_URL = "https://my-app.yinyoo2904.workers.dev"
DEFAULT_TIMEZONE = "Asia/Tokyo"
def tomorrow_iso_date(timezone: str = DEFAULT_TIMEZONE) -> str:
"""Return tomorrow's date in YYYY-MM-DD format."""
from zoneinfo import ZoneInfo
tz = ZoneInfo(timezone)
now = datetime.now(tz=tz)
return (now.date() + timedelta(days=1)).isoformat()
def get_tasks_today(api_key: str, target_date: str, timezone: str = DEFAULT_TIMEZONE):
"""Get tasks for a specific date."""
url = f"{DEFAULT_BASE_URL}/api/v1/tasks/today"
headers = {
"Authorization": f"ApiKey {api_key}",
"Accept": "application/json",
}
params = {
"date": target_date,
"timezone": timezone
}
response = requests.get(url, headers=headers, params=params, timeout=20)
response.raise_for_status()
body = response.json()
if body.get("error") is not None:
raise RuntimeError(f"API error: {body.get('error')}: {body.get('message')}")
return body["data"]
def main():
api_key = os.environ.get("TASKWORKS_API_KEY", "").strip()
if not api_key:
raise ValueError("TASKWORKS_API_KEY environment variable is not set")
target_date = tomorrow_iso_date()
data = get_tasks_today(api_key, target_date)
print(f"date: {data.get('date')} timezone: {data.get('timezone')}")
tasks = data.get("tasks", [])
if not tasks:
print("No tasks for tomorrow.")
return
for task in tasks:
time_part = task.get("timeLabel") or ("Anytime" if task.get("anytime") else "")
tags_part = f" [{', '.join(task.get('tags', []))}]" if task.get("tags") else ""
progress = f"{task.get('completed', 0):g}/{task.get('target', 0):g}"
status = task.get("status", "")
print(f"- {time_part:>10} | {task.get('title')}{tags_part} | {status} | {progress}")
if __name__ == "__main__":
main()
```
### JavaScript/TypeScript: Create and Complete Task
```typescript
/**
* TaskWorks API Client for TypeScript/JavaScript
*/
interface TaskWorksClientConfig {
apiKey: string;
baseUrl?: string;
}
class TaskWorksClient {
private apiKey: string;
private baseUrl: string;
constructor(config: TaskWorksClientConfig) {
this.apiKey = config.apiKey;
this.baseUrl = config.baseUrl || "https://my-app.yinyoo2904.workers.dev";
}
private headers(): HeadersInit {
return {
"Authorization": `ApiKey ${this.apiKey}`,
"Accept": "application/json",
"Content-Type": "application/json",
};
}
async getTasksToday(date?: string, timezone: string = "Asia/Tokyo") {
const url = new URL(`${this.baseUrl}/api/v1/tasks/today`);
if (date) url.searchParams.set("date", date);
url.searchParams.set("timezone", timezone);
const response = await fetch(url.toString(), {
headers: this.headers(),
});
if (!response.ok) {
const body = await response.json();
throw new Error(`API error: ${body.error}: ${body.message}`);
}
return response.json();
}
async createTask(task: {
title: string;
description?: string;
kind?: "single" | "habit";
}) {
const response = await fetch(`${this.baseUrl}/api/v1/tasks`, {
method: "POST",
headers: this.headers(),
body: JSON.stringify(task),
});
if (!response.ok) {
const body = await response.json();
throw new Error(`API error: ${body.error}: ${body.message}`);
}
return response.json();
}
async executeTask(taskId: string, qty: number = 1) {
const response = await fetch(`${this.baseUrl}/api/v1/tasks/${taskId}/execute`, {
method: "POST",
headers: this.headers(),
body: JSON.stringify({ qty }),
});
if (!response.ok) {
const body = await response.json();
throw new Error(`API error: ${body.error}: ${body.message}`);
}
return response.json();
}
async submitEvaluation(evaluation: {
taskId: string;
concentrationLevel: -2 | -1 | 0 | 1 | 2;
moodLevel: -2 | -1 | 0 | 1 | 2;
hasComment: boolean;
commentText?: string;
}) {
const response = await fetch(`${this.baseUrl}/api/v1/evaluations/submit`, {
method: "POST",
headers: this.headers(),
body: JSON.stringify(evaluation),
});
if (!response.ok) {
const body = await response.json();
throw new Error(`API error: ${body.error}: ${body.message}`);
}
return response.json();
}
}
async function main() {
const apiKey = process.env.TASKWORKS_API_KEY;
if (!apiKey) {
throw new Error("TASKWORKS_API_KEY environment variable is not set");
}
const client = new TaskWorksClient({ apiKey });
try {
// Get today's tasks
const todayResponse = await client.getTasksToday();
console.log("Today's tasks:", todayResponse.data.tasks);
if (todayResponse.data.tasks.length > 0) {
const firstTask = todayResponse.data.tasks[0];
console.log(`
First task: ${firstTask.title}`);
// Execute the task
const execResponse = await client.executeTask(firstTask.taskId, 1);
console.log("Task executed:", execResponse.data);
if (execResponse.data.success) {
console.log(`
Reward received: ${execResponse.data.rewardTotal} cat cans`);
// Submit evaluation
const evalResponse = await client.submitEvaluation({
taskId: firstTask.taskId,
concentrationLevel: 1,
moodLevel: 1,
hasComment: false,
});
console.log("Evaluation submitted:", evalResponse.data);
}
}
} catch (error) {
console.error("Error:", error instanceof Error ? error.message : error);
process.exit(1);
}
}
if (require.main === module) {
main();
}
```
### Node.js: Get Habit Dashboard
```javascript
/**
* Get habit dashboard for a specific month
*/
const https = require('https');
class TaskWorksClient {
constructor(apiKey, baseUrl = 'https://my-app.yinyoo2904.workers.dev') {
this.apiKey = apiKey;
this.baseUrl = baseUrl;
}
getHeaders() {
return {
'Authorization': `ApiKey ${this.apiKey}`,
'Accept': 'application/json',
};
}
async getHabitDashboard(year, month) {
const url = new URL(`${this.baseUrl}/api/v1/habits/dashboard`);
url.searchParams.set('year', year);
url.searchParams.set('month', month);
return this.request(url.toString());
}
async request(url) {
return new Promise((resolve, reject) => {
const urlObj = new URL(url);
const options = {
hostname: urlObj.hostname,
path: urlObj.pathname + urlObj.search,
method: 'GET',
headers: this.getHeaders(),
};
const req = https.request(options, (res) => {
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
try {
const body = JSON.parse(data);
if (res.statusCode !== 200) {
reject(new Error(`API error: ${res.statusCode} ${body.error}: ${body.message}`));
}
resolve(body);
} catch (e) {
reject(new Error(`HTTP ${res.statusCode}: ${res.statusMessage}`));
}
});
});
res.on('end', () => {
if (res.statusCode >= 200 && res.statusCode < 300) {
try {
resolve(JSON.parse(data));
} catch (e) {
reject(new Error('Invalid JSON response'));
}
} else {
try {
const body = JSON.parse(data);
reject(new Error(`API error: ${res.statusCode} ${body.error}: ${body.message}`));
} catch (e) {
reject(new Error(`HTTP ${res.statusCode}: ${res.statusMessage}`));
}
}
});
});
req.on('error', (e) => {
reject(e);
});
req.end();
});
}
}
async function main() {
const apiKey = process.env.TASKWORKS_API_KEY;
if (!apiKey) {
console.error('TASKWORKS_API_KEY environment variable is not set');
process.exit(1);
}
const client = new TaskWorksClient(apiKey);
try {
const now = new Date();
const year = now.getFullYear();
const month = now.getMonth() + 1;
const response = await client.getHabitDashboard(year, month);
const dashboard = response.data;
console.log(`Habit Dashboard for ${year}-${month.toString().padStart(2, '0')}`);
console.log(`Completion rate: ${dashboard.completionRate.toFixed(1)}%`);
console.log(`Streak: ${dashboard.streak.current} days (longest: ${dashboard.streak.longest} days)`);
console.log(`Tasks: ${dashboard.taskCount} habits`);
console.log(`
Today: ${dashboard.today.completed}/${dashboard.today.required} completed (${dashboard.today.percentage}%)`);
console.log(`Month: ${dashboard.totals.doneDays}/${dashboard.totals.trackedDays} days done, ${dashboard.totals.remainingDays} remaining`);
} catch (error) {
console.error('Error:', error.message);
process.exit(1);
}
}
if (require.main === module) {
main();
}
```
### cURL: Search Tasks
```bash
#!/bin/bash
# Search tasks by keyword
API_KEY="${TASKWORKS_API_KEY:-YOUR_TOKEN}"
BASE_URL="${BASE_URL:-https://my-app.yinyoo2904.workers.dev}"
KEYWORD="${1:-task}"
LIMIT="${2:-10}"
echo "Searching for: $KEYWORD (limit: $LIMIT)"
curl -X GET "${BASE_URL}/api/v1/tasks/search?q=${KEYWORD}&limit=${LIMIT}" \
-H "Authorization: ApiKey ${API_KEY}" \
-H "Accept: application/json" \
-s | jq '.data'
```
### Python: Get Daily Averages
```python
#!/usr/bin/env python3
"""
Get daily concentration and mood averages
"""
import os
import requests
from datetime import datetime, timedelta
DEFAULT_BASE_URL = "https://my-app.yinyoo2904.workers.dev"
def get_daily_averages(api_key: str, days: int = 30, timezone: str = "Asia/Tokyo"):
"""Get daily concentration and mood averages."""
url = f"{DEFAULT_BASE_URL}/api/v1/analytics/daily-averages"
headers = {
"Authorization": f"ApiKey {api_key}",
"Accept": "application/json",
}
params = {
"days": days,
"timezone": timezone,
"includeTasks": "true"
}
response = requests.get(url, headers=headers, params=params, timeout=20)
response.raise_for_status()
body = response.json()
if body.get("error") is not None:
raise RuntimeError(f"API error: {body.get('error')}: {body.get('message')}")
return body["data"]
def main():
api_key = os.environ.get("TASKWORKS_API_KEY", "").strip()
if not api_key:
raise ValueError("TASKWORKS_API_KEY environment variable is not set")
data = get_daily_averages(api_key, days=30)
print("Daily Averages (last 30 days)")
print("=" * 60)
overall = data.get("overall", [])
for entry in overall:
date = entry.get("date", "")
conc = entry.get("avg_concentration")
mood = entry.get("avg_mood")
answers = entry.get("answer_count", 0)
missed = entry.get("unanswered_count", 0)
conc_str = f"{conc:.2f}" if conc is not None else "N/A"
mood_str = f"{mood:.2f}" if mood is not None else "N/A"
print(f"{date} | Conc: {conc_str:>6} | Mood: {mood_str:>6} | Answers: {answers:2d} | Missed: {missed:2d}")
if __name__ == "__main__":
main()
```
### JavaScript: Pomodoro Workflow
```javascript
/**
* Complete Pomodoro workflow: start session, complete it, submit evaluation
*/
class PomodoroClient extends TaskWorksClient {
async startPomodoro({ taskId, sessionType, durationMinutes }) {
const response = await fetch(`${this.baseUrl}/api/v1/pomodoro`, {
method: "POST",
headers: this.headers(),
body: JSON.stringify({
task_id: taskId,
session_type: sessionType,
duration_minutes: durationMinutes,
}),
});
if (!response.ok) {
const body = await response.json();
throw new Error(`API error: ${body.error}: ${body.message}`);
}
return response.json();
}
async completePomodoro(sessionId) {
const response = await fetch(`${this.baseUrl}/api/v1/pomodoro/${sessionId}/complete`, {
method: "POST",
headers: this.headers(),
});
if (!response.ok) {
const body = await response.json();
throw new Error(`API error: ${body.error}: ${body.message}`);
}
return response.json();
}
async getActivePomodoro() {
const response = await fetch(`${this.baseUrl}/api/v1/pomodoro`, {
method: "GET",
headers: this.headers(),
});
if (!response.ok) {
const body = await response.json();
throw new Error(`API error: ${body.error}: ${body.message}`);
}
return response.json();
}
}
async function main() {
const apiKey = process.env.TASKWORKS_API_KEY;
if (!apiKey) {
throw new Error("TASKWORKS_API_KEY environment variable is not set");
}
const client = new PomodoroClient({ apiKey });
try {
// Check if there's an active session
const activeResponse = await client.getActivePomodoro();
if (activeResponse.data) {
console.log("Active session found:", activeResponse.data.id);
return;
}
// Start a new 25-minute work session
console.log("Starting 25-minute work session...");
const startResponse = await client.startPomodoro({
taskId: null,
sessionType: "work",
durationMinutes: 25,
});
const session = startResponse.data;
console.log("Session started:", session.id);
console.log("Scheduled to end at:", session.scheduled_end_at);
// Wait for user to complete the session
console.log("
Press Enter when the session is complete...");
await new Promise((resolve) => process.stdin.once('data', resolve));
// Complete the session
console.log("Completing session...");
const completeResponse = await client.completePomodoro(session.id);
console.log("Session completed:", completeResponse.data);
} catch (error) {
console.error("Error:", error instanceof Error ? error.message : error);
process.exit(1);
}
}
if (require.main === module) {
main();
}
```
### Python: Gacha Draw
```python
#!/usr/bin/env python3
"""
Draw gacha cards
"""
import os
import requests
from dataclasses import dataclass
from typing import List, Optional
DEFAULT_BASE_URL = "https://my-app.yinyoo2904.workers.dev"
@dataclass
class GachaConfig:
id: str
name: str
cost: dict
@dataclass
class GachaCard:
image: str
rarity: Optional[str]
clip: Optional[str]
class GachaClient:
def __init__(self, api_key: str, base_url: str = DEFAULT_BASE_URL):
self.api_key = api_key
self.base_url = base_url
def get_headers(self):
return {
"Authorization": f"ApiKey {self.api_key}",
"Accept": "application/json",
"Content-Type": "application/json",
}
def draw_gacha(self, gacha: GachaConfig, draw_type: str = "single"):
"""Draw gacha cards."""
url = f"{self.base_url}/api/v1/gacha/draw"
body = {
"gacha": {
"id": gacha.id,
"name": gacha.name,
"cost": gacha.cost
},
"drawType": draw_type
}
response = requests.post(url, headers=self.get_headers(), json=body, timeout=30)
response.raise_for_status()
data = response.json()
if data.get("error") is not None:
raise RuntimeError(f"API error: {data.get('error')}: {data.get('message')}")
return data["data"]
def get_balance(self):
"""Get current cat can balance."""
url = f"{self.base_url}/api/v1/gacha/draw"
response = requests.get(url, headers=self.get_headers(), timeout=20)
response.raise_for_status()
data = response.json()
if data.get("error") is not None:
raise RuntimeError(f"API error: {data.get('error')}: {data.get('message')}")
return data["data"]["catCanBalance"]
def get_inventory(self, limit: int = 100):
"""Get gacha inventory."""
url = f"{self.base_url}/api/v1/gacha/inventory"
params = {"limit": limit}
response = requests.get(url, headers=self.get_headers(), params=params, timeout=20)
response.raise_for_status()
data = response.json()
if data.get("error") is not None:
raise RuntimeError(f"API error: {data.get('error')}: {data.get('message')}")
return data["data"]
def main():
api_key = os.environ.get("TASKWORKS_API_KEY", "").strip()
if not api_key:
raise ValueError("TASKWORKS_API_KEY environment variable is not set")
client = GachaClient(api_key)
try:
# Get current balance
balance = client.get_balance()
print(f"Current balance: {balance} cat cans")
# Define gacha configuration (example values)
gacha_config = GachaConfig(
id="example_gacha_1",
name="Example Gacha",
cost={"single": 100, "ten": 1000}
)
# Draw single card
print("
Drawing single card (cost: 100)...")
result = client.draw_gacha(gacha_config, "single")
print(f"Result ID: {result['result']['id']}")
print(f"Gacha: {result['result']['gachaName']}")
print(f"Cost: {result['cost']} cat cans")
print(f"Balance after: {result['catCanBalance']} cat cans")
# Display drawn cards
cards = result["result"]["cards"]
print(f"
Drawn cards ({len(cards)}):")
for i, card in enumerate(cards, 1):
rarity = card.get("rarity", "normal")
print(f" {i}. {card['image']} (rarity: {rarity})")
# Get inventory
print("
Inventory:")
inventory = client.get_inventory()
print(f" Total unique: {inventory['totalUnique']}")
print(f" Total count: {inventory['totalCount']}")
for item in inventory["cards"][:5]:
print(f" - {item['image']} x{item['count']}")
if len(inventory["cards"]) > 5:
print(f" ... and {len(inventory['cards']) - 5} more")
except Exception as error:
print(f"Error: {error}")
import sys
sys.exit(1)
if __name__ == "__main__":
main()
```
## Quick Start Example
### cURL
### JavaScript (fetch)
### Python (requests)
## Important Notes
- RLS Protection: All endpoints return user-specific data only
- ApiKey Limitations: /api/v1/blocks/windows does not support ApiKey authentication (use Bearer or Session)
- Admin Endpoints: Some community endpoints require administrator permissions
- Rate Limiting: High-frequency clients should set expiresAt for periodic key rotation
- Security: API keys are shown only once after generation. Store them securely.