{"openapi":"3.1.0","info":{"title":"Daily Leveling API","version":"1.0.0","description":"The Daily Leveling API lets agents and external tools manage a user's quests (tasks) and goals on their behalf. Users mint a personal API key from inside the mobile app (Profile → API Access → Create API Key) and paste it into your agent. All endpoints under /v1 require Bearer auth with a key prefixed `dolo_`. Use this API to create quests, mark them complete, list outstanding work, or break long-term goals into daily tasks.","contact":{"name":"Daily Leveling","email":"info@dailyleveling.app","url":"https://api.dailyleveling.app"},"license":{"name":"Proprietary"}},"servers":[{"url":"https://api.dailyleveling.app","description":"Production"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Onboarding","description":"Account creation flow for agents — email-based magic link, no Bearer auth required."},{"name":"Tasks","description":"Daily quests. Each task earns 20–50 XP based on priority."},{"name":"Goals","description":"Long-term objectives. Each goal completion earns 150 XP."}],"paths":{"/v1/accounts/request-onboarding":{"post":{"tags":["Onboarding"],"summary":"Send a magic-link onboarding email on behalf of a user","description":"Public endpoint (no auth). Use this when a user wants to sign up for Daily Leveling through your agent. We email them a one-time confirmation link; they click it, and we create the account, mint an API key, and show it to them once. They paste it back to your agent. The agent never sees the password. Rate-limited: 3 per hour per IP, 1 per hour per email.","operationId":"requestOnboarding","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email","description":"User's email address. Used as identity proof."},"username":{"type":"string","description":"Optional. 3-40 chars, [a-zA-Z0-9_-]. We auto-generate one if omitted.","minLength":3,"maxLength":40},"agent_name":{"type":"string","description":"Your agent's name (e.g. 'ChatGPT', 'Claude Desktop'). Shown in the user's email.","maxLength":60}},"required":["email"]},"examples":{"basic":{"summary":"Minimal request","value":{"email":"sam@example.com","agent_name":"ChatGPT"}}}}}},"responses":{"200":{"description":"Onboarding email sent","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"409":{"description":"An account already exists for this email","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/tasks":{"get":{"tags":["Tasks"],"summary":"List & search tasks","description":"Returns the user's tasks. Supports filtering by completion, category, priority, parent task, and full-text search across title and description. Use this when an agent needs to find tasks before acting on them.","operationId":"listTasks","parameters":[{"name":"q","in":"query","schema":{"type":"string"},"description":"Full-text search across title + description"},{"name":"completed","in":"query","schema":{"type":"boolean"},"description":"Filter by completion status"},{"name":"category","in":"query","schema":{"$ref":"#/components/schemas/Category"}},{"name":"priority","in":"query","schema":{"$ref":"#/components/schemas/Priority"}},{"name":"parentTaskId","in":"query","schema":{"type":"string","format":"uuid"},"description":"Only return subtasks of this parent"},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200},"description":"Cap the result set"}],"responses":{"200":{"description":"Array of tasks","content":{"application/json":{"schema":{"type":"object","properties":{"tasks":{"type":"array","items":{"$ref":"#/components/schemas/Task"}}},"required":["tasks"]}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"tags":["Tasks"],"summary":"Create a new task (quest)","description":"Creates a quest in one of seven stat categories. XP is auto-assigned by priority: low=20, medium=30, high=50.","operationId":"createTask","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTaskRequest"},"examples":{"workout":{"summary":"Add a fitness quest","value":{"title":"Leg day","category":"fitness","priority":"high"}},"reading":{"summary":"Add a reading quest with a deadline","value":{"title":"Read 30 pages of Atomic Habits","description":"Chapter 4 → 6","category":"education","priority":"medium","deadline":"2026-05-15"}}}}}},"responses":{"200":{"description":"Task created","content":{"application/json":{"schema":{"type":"object","properties":{"task":{"$ref":"#/components/schemas/Task"}},"required":["task"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/v1/tasks/bulk":{"post":{"tags":["Tasks"],"summary":"Bulk create up to 50 tasks in one call","description":"Use this when an agent needs to import a routine, break a goal into quests, or onboard a user with several starter tasks at once. Each task is validated independently; partial success is reported in the response.","operationId":"bulkCreateTasks","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"tasks":{"type":"array","items":{"$ref":"#/components/schemas/CreateTaskRequest"},"minItems":1,"maxItems":50}},"required":["tasks"]},"examples":{"morningRoutine":{"summary":"Morning routine","value":{"tasks":[{"title":"Cold shower","category":"health","priority":"low"},{"title":"10m journal","category":"personal","priority":"low"},{"title":"Heavy push day","category":"fitness","priority":"high"},{"title":"Read 30 pages","category":"education","priority":"medium"}]}}}}}},"responses":{"200":{"description":"Bulk creation result with per-item success/failure","content":{"application/json":{"schema":{"type":"object","properties":{"created":{"type":"array","items":{"$ref":"#/components/schemas/Task"}},"failed":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer"},"error":{"type":"string"}}}},"createdCount":{"type":"integer"},"failedCount":{"type":"integer"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/v1/tasks/{id}/subtasks":{"get":{"tags":["Tasks"],"summary":"List subtasks of a parent task","description":"Returns all tasks whose parentTaskId equals the given UUID. Use this when an agent needs to walk a task tree.","operationId":"listSubtasks","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Array of subtasks","content":{"application/json":{"schema":{"type":"object","properties":{"subtasks":{"type":"array","items":{"$ref":"#/components/schemas/Task"}},"count":{"type":"integer"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/v1/goals/bulk":{"post":{"tags":["Goals"],"summary":"Bulk create up to 50 goals in one call","operationId":"bulkCreateGoals","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"goals":{"type":"array","items":{"$ref":"#/components/schemas/CreateGoalRequest"},"minItems":1,"maxItems":50}},"required":["goals"]}}}},"responses":{"200":{"description":"Bulk creation result","content":{"application/json":{"schema":{"type":"object","properties":{"created":{"type":"array","items":{"$ref":"#/components/schemas/Goal"}},"failed":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer"},"error":{"type":"string"}}}},"createdCount":{"type":"integer"},"failedCount":{"type":"integer"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/v1/tasks/{id}/complete":{"patch":{"tags":["Tasks"],"summary":"Mark a task as complete","description":"Marks the task complete, awards XP to its category, and may trigger a level-up event.","operationId":"completeTask","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Task ID returned from POST /v1/tasks or GET /v1/tasks"}],"responses":{"200":{"description":"Task completed","content":{"application/json":{"schema":{"type":"object","properties":{"task":{"$ref":"#/components/schemas/Task"}},"required":["task"]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/tasks/{id}":{"delete":{"tags":["Tasks"],"summary":"Delete a task","operationId":"deleteTask","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/goals":{"get":{"tags":["Goals"],"summary":"List & search goals","description":"Returns the user's goals. Supports same filters as /v1/tasks: q, completed, category, priority, limit.","operationId":"listGoals","parameters":[{"name":"q","in":"query","schema":{"type":"string"}},{"name":"completed","in":"query","schema":{"type":"boolean"}},{"name":"category","in":"query","schema":{"$ref":"#/components/schemas/Category"}},{"name":"priority","in":"query","schema":{"$ref":"#/components/schemas/Priority"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200}}],"responses":{"200":{"description":"Array of goals","content":{"application/json":{"schema":{"type":"object","properties":{"goals":{"type":"array","items":{"$ref":"#/components/schemas/Goal"}}},"required":["goals"]}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"tags":["Goals"],"summary":"Create a new long-term goal","description":"Goals award 150 XP on completion. Use these for outcomes; use tasks for daily quests.","operationId":"createGoal","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateGoalRequest"},"examples":{"business":{"summary":"Long-term business goal","value":{"title":"Hit $10k MRR","category":"business","priority":"high","targetDate":"2026-09-01"}}}}}},"responses":{"200":{"description":"Goal created","content":{"application/json":{"schema":{"type":"object","properties":{"goal":{"$ref":"#/components/schemas/Goal"}},"required":["goal"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/v1/goals/{id}/complete":{"patch":{"tags":["Goals"],"summary":"Mark a goal as complete","operationId":"completeGoal","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Goal completed","content":{"application/json":{"schema":{"type":"object","properties":{"goal":{"$ref":"#/components/schemas/Goal"}},"required":["goal"]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/goals/{id}":{"delete":{"tags":["Goals"],"summary":"Delete a goal","operationId":"deleteGoal","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"API Key","description":"Personal API key minted inside the Daily Leveling mobile app. Format: `dolo_` followed by 48 hex characters."}},"schemas":{"Category":{"type":"string","description":"One of seven stat categories. Pick the closest match — the user grinds XP per category and levels each one independently.","enum":["business","health","fitness","education","personal","finance","travel"],"examples":["fitness"]},"Priority":{"type":"string","description":"Effort level. low=20 XP, medium=30 XP, high=50 XP. Pick `high` only for genuinely demanding quests.","enum":["low","medium","high"],"examples":["medium"]},"Task":{"type":"object","description":"A daily quest. Awards XP to its category on completion.","properties":{"id":{"type":"string","format":"uuid"},"userId":{"type":"string","format":"uuid"},"title":{"type":"string","examples":["Leg day"]},"description":{"type":"string"},"xp":{"type":"integer","description":"Auto-set from priority. Read-only."},"priority":{"$ref":"#/components/schemas/Priority"},"category":{"$ref":"#/components/schemas/Category"},"deadline":{"type":["string","null"],"format":"date","description":"ISO date (YYYY-MM-DD) or null"},"completed":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","userId","title","priority","category","completed","createdAt"]},"Goal":{"type":"object","description":"A long-term objective. Awards 150 XP on completion.","properties":{"id":{"type":"string","format":"uuid"},"userId":{"type":"string","format":"uuid"},"title":{"type":"string","examples":["Hit $10k MRR"]},"description":{"type":"string"},"xp":{"type":"integer","examples":[150]},"priority":{"$ref":"#/components/schemas/Priority"},"category":{"$ref":"#/components/schemas/Category"},"targetDate":{"type":["string","null"],"format":"date"},"completed":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","userId","title","priority","category","completed","createdAt"]},"CreateTaskRequest":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string","maxLength":2000},"priority":{"$ref":"#/components/schemas/Priority"},"category":{"$ref":"#/components/schemas/Category"},"deadline":{"type":"string","format":"date","description":"ISO date YYYY-MM-DD"},"parentTaskId":{"type":"string","format":"uuid","description":"Make this task a subtask of an existing task"}},"required":["title"]},"CreateGoalRequest":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string","maxLength":2000},"priority":{"$ref":"#/components/schemas/Priority"},"category":{"$ref":"#/components/schemas/Category"},"targetDate":{"type":"string","format":"date"}},"required":["title"]},"SuccessResponse":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]},"Error":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}},"responses":{"Unauthorized":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"Resource not found or doesn't belong to the authenticated user","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"BadRequest":{"description":"Invalid request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}