Daily Habits

Public API reference

Device Weekly APIs

These two read-only endpoints expose the weekly triathlon plan and the rolling daily habits view for a second device. All dates use the Europe/Warsaw day boundary.

Auth: none Format: JSON Timezone: Europe/Warsaw

Endpoint 1

Triathlon current week

GET

https://discipline.nomoonshots.com/api/triathlon/current-week

Returns the current training week, including week metadata and one entry per day. Workout days contain the full workout object. Rest days contain the rest suggestion.

Top-level fields

  • today: current date in Warsaw.
  • week_index: zero-based index of the active training week.
  • start_date and end_date: current week boundaries.
  • phase and focus: summary of the training block.
  • days: seven day records for the current week.

Day object fields

  • date, dow, status, phase, is_today.
  • workout is present only for workout days.
  • rest_suggestion is present only for rest days.
  • workout includes title, duration, intensity, segments, substitutions, and equipment data.

Example response

Open endpoint
{
  "today": "2026-04-26",
  "week_index": 7,
  "start_date": "2026-04-20",
  "end_date": "2026-04-26",
  "phase": "Tri base → build",
  "focus": "More race-effort bike; optional tempo run.",
  "days": [
    {
      "date": "2026-04-20",
      "dow": "Monday",
      "status": "rest",
      "phase": "Tri base → build",
      "is_today": false,
      "rest_suggestion": "Optional mobility + easy walk; rest if you feel beat up."
    },
    {
      "date": "2026-04-21",
      "dow": "Tuesday",
      "status": "workout",
      "phase": "Tri base → build",
      "is_today": false,
      "workout": {
        "type": [
          "swim"
        ],
        "title": "Pool swim: aerobic development + pacing",
        "duration_min": 45,
        "intensity_overall": {
          "rpe": "2-6",
          "zones": "Mostly Z1-Z3"
        },
        "segments": [
          {
            "name": "Warm-up",
            "duration_min": 8,
            "details": "300m easy + 4×25m build, 15s rest"
          },
          {
            "name": "Drills",
            "duration_min": 8,
            "details": "4×50m drill/swim, 20s rest"
          },
          {
            "name": "Main set",
            "duration_min": 22,
            "details": "8×100m steady, 20–25s rest. Negative split last 2 reps."
          },
          {
            "name": "Cool-down",
            "duration_min": 7,
            "details": "200m easy"
          }
        ],
        "target_volume": "1400-1800m",
        "substitution_ids": [
          "swim_no_access"
        ],
        "equipment_group_ids": [
          "swim"
        ]
      }
    },
    {
      "date": "2026-04-22",
      "dow": "Wednesday",
      "status": "rest",
      "phase": "Tri base → build",
      "is_today": false,
      "rest_suggestion": "Optional mobility + easy walk; rest if you feel beat up."
    },
    {
      "date": "2026-04-23",
      "dow": "Thursday",
      "status": "workout",
      "phase": "Tri base → build",
      "is_today": false,
      "workout": {
        "type": [
          "bike",
          "run_brick"
        ],
        "title": "Bike: tempo development + brick",
        "duration_min": 45,
        "intensity_overall": {
          "rpe": "2-8",
          "zones": "Mostly Z1-Z3; quality reps Z4-Z5 when scheduled"
        },
        "segments": [
          {
            "name": "Warm-up",
            "duration_min": 8,
            "details": "Easy spin + 2×20s fast legs"
          },
          {
            "name": "Main set",
            "duration_min": 22,
            "details": "3×5 min tempo/race-effort (RPE 6–7) / 2 min easy"
          },
          {
            "name": "Brick run",
            "duration_min": 10,
            "details": "Easy jog; focus on relaxed cadence"
          },
          {
            "name": "Cool-down",
            "duration_min": 5,
            "details": "Easy spin/walk"
          }
        ],
        "substitution_ids": [
          "bike_bad_weather",
          "run_bad_weather"
        ],
        "equipment_group_ids": [
          "bike",
          "run"
        ]
      }
    },
    {
      "date": "2026-04-24",
      "dow": "Friday",
      "status": "rest",
      "phase": "Tri base → build",
      "is_today": false,
      "rest_suggestion": "Optional mobility + easy walk; rest if you feel beat up."
    },
    {
      "date": "2026-04-25",
      "dow": "Saturday",
      "status": "workout",
      "phase": "Tri base → build",
      "is_today": false,
      "workout": {
        "type": [
          "bike"
        ],
        "title": "Bike: endurance + race-effort blocks",
        "duration_min": 75,
        "intensity_overall": {
          "rpe": "2-8",
          "zones": "Mostly Z2; controlled Z3-Z4 blocks; brief Z5 surges when scheduled"
        },
        "segments": [
          {
            "name": "Warm-up",
            "duration_min": 10,
            "details": "Easy spin"
          },
          {
            "name": "Main set",
            "duration_min": 55,
            "details": "3×10 min at steady race effort (RPE 6–7) / 3 min easy; remainder Z2"
          },
          {
            "name": "Cool-down",
            "duration_min": 10,
            "details": "Easy spin"
          }
        ],
        "substitution_ids": [
          "bike_bad_weather"
        ],
        "equipment_group_ids": [
          "bike"
        ]
      }
    },
    {
      "date": "2026-04-26",
      "dow": "Sunday",
      "status": "workout",
      "phase": "Tri base → build",
      "is_today": true,
      "workout": {
        "type": [
          "run",
          "strength"
        ],
        "title": "Run: tempo option + strength B",
        "duration_min": 75,
        "intensity_overall": {
          "rpe": "2-7",
          "zones": "Mostly Z2; tempo segments Z3-Z4 when scheduled"
        },
        "segments": [
          {
            "name": "Warm-up",
            "duration_min": 12,
            "details": "Easy jog"
          },
          {
            "name": "Tempo blocks",
            "duration_min": 24,
            "details": "2×10 min tempo (RPE 6) / 3 min easy"
          },
          {
            "name": "Easy",
            "duration_min": 19,
            "details": "Easy jog"
          },
          {
            "name": "Strength block B",
            "duration_min": 20,
            "details": "See strength_exercises list; keep 1–2 reps in reserve (no grinding)."
          }
        ],
        "substitution_ids": [
          "run_bad_weather"
        ],
        "equipment_group_ids": [
          "gym",
          "run"
        ],
        "strength": {
          "block_id": "B",
          "sets_rule": "meta.strength_blocks.progression"
        }
      }
    }
  ]
}

Endpoint 2

Daily habits weekly window

GET

https://discipline.nomoonshots.com/api/daily-habits/weekly

Returns a rolling 7-day window that includes today and the previous 6 calendar days. The payload includes stable task definitions plus per-day summaries and per-task completion state.

Top-level fields

  • today, start_date, end_date: date range for the window.
  • tasks: ordered task definitions shared across all days.
  • days: seven day records in ascending date order.

Day object fields

  • mode and mode_locked: standard vs minimum-day state.
  • required_count, completed_count, day_complete.
  • planned_minutes and completed_minutes: computed using the day mode.
  • tasks: per-task entries with explicit completed status and minutes_for_day_mode.
Minimum mode rule: the required count is min(3, task_count). If no day mode row exists, the API defaults to standard and unlocked.

Example response

Open endpoint
{
  "today": "2026-04-26",
  "start_date": "2026-04-20",
  "end_date": "2026-04-26",
  "tasks": [
    {
      "id": 1,
      "slug": "shipped-proof-unit",
      "label": "Marketing - 100days experiment added",
      "position": 1,
      "target_minutes": 20,
      "minimum_target_minutes": 10
    },
    {
      "id": 2,
      "slug": "sales-outbound",
      "label": "Sales - 30 DMs",
      "position": 2,
      "target_minutes": 60,
      "minimum_target_minutes": 20
    },
    {
      "id": 3,
      "slug": "social-replies",
      "label": "Social - 30 replies",
      "position": 3,
      "target_minutes": 45,
      "minimum_target_minutes": 15
    },
    {
      "id": 4,
      "slug": "job-applications",
      "label": "Job Search - 3 application",
      "position": 4,
      "target_minutes": 45,
      "minimum_target_minutes": 20
    },
    {
      "id": 5,
      "slug": "course-progress",
      "label": "Course - 30 minutes on a new chapter",
      "position": 5,
      "target_minutes": 30,
      "minimum_target_minutes": 15
    },
    {
      "id": 6,
      "slug": "marketing-build-post",
      "label": "Build in Public - summary post of the day",
      "position": 6,
      "target_minutes": 15,
      "minimum_target_minutes": 10
    }
  ],
  "days": [
    {
      "date": "2026-04-20",
      "is_today": false,
      "mode": "standard",
      "mode_locked": false,
      "required_count": 6,
      "completed_count": 0,
      "planned_minutes": 215,
      "completed_minutes": 0,
      "day_complete": false,
      "tasks": [
        {
          "task_id": 1,
          "slug": "shipped-proof-unit",
          "label": "Marketing - 100days experiment added",
          "completed": false,
          "target_minutes": 20,
          "minimum_target_minutes": 10,
          "minutes_for_day_mode": 20
        },
        {
          "task_id": 2,
          "slug": "sales-outbound",
          "label": "Sales - 30 DMs",
          "completed": false,
          "target_minutes": 60,
          "minimum_target_minutes": 20,
          "minutes_for_day_mode": 60
        },
        {
          "task_id": 3,
          "slug": "social-replies",
          "label": "Social - 30 replies",
          "completed": false,
          "target_minutes": 45,
          "minimum_target_minutes": 15,
          "minutes_for_day_mode": 45
        },
        {
          "task_id": 4,
          "slug": "job-applications",
          "label": "Job Search - 3 application",
          "completed": false,
          "target_minutes": 45,
          "minimum_target_minutes": 20,
          "minutes_for_day_mode": 45
        },
        {
          "task_id": 5,
          "slug": "course-progress",
          "label": "Course - 30 minutes on a new chapter",
          "completed": false,
          "target_minutes": 30,
          "minimum_target_minutes": 15,
          "minutes_for_day_mode": 30
        },
        {
          "task_id": 6,
          "slug": "marketing-build-post",
          "label": "Build in Public - summary post of the day",
          "completed": false,
          "target_minutes": 15,
          "minimum_target_minutes": 10,
          "minutes_for_day_mode": 15
        }
      ]
    },
    {
      "date": "2026-04-21",
      "is_today": false,
      "mode": "standard",
      "mode_locked": false,
      "required_count": 6,
      "completed_count": 0,
      "planned_minutes": 215,
      "completed_minutes": 0,
      "day_complete": false,
      "tasks": [
        {
          "task_id": 1,
          "slug": "shipped-proof-unit",
          "label": "Marketing - 100days experiment added",
          "completed": false,
          "target_minutes": 20,
          "minimum_target_minutes": 10,
          "minutes_for_day_mode": 20
        },
        {
          "task_id": 2,
          "slug": "sales-outbound",
          "label": "Sales - 30 DMs",
          "completed": false,
          "target_minutes": 60,
          "minimum_target_minutes": 20,
          "minutes_for_day_mode": 60
        },
        {
          "task_id": 3,
          "slug": "social-replies",
          "label": "Social - 30 replies",
          "completed": false,
          "target_minutes": 45,
          "minimum_target_minutes": 15,
          "minutes_for_day_mode": 45
        },
        {
          "task_id": 4,
          "slug": "job-applications",
          "label": "Job Search - 3 application",
          "completed": false,
          "target_minutes": 45,
          "minimum_target_minutes": 20,
          "minutes_for_day_mode": 45
        },
        {
          "task_id": 5,
          "slug": "course-progress",
          "label": "Course - 30 minutes on a new chapter",
          "completed": false,
          "target_minutes": 30,
          "minimum_target_minutes": 15,
          "minutes_for_day_mode": 30
        },
        {
          "task_id": 6,
          "slug": "marketing-build-post",
          "label": "Build in Public - summary post of the day",
          "completed": false,
          "target_minutes": 15,
          "minimum_target_minutes": 10,
          "minutes_for_day_mode": 15
        }
      ]
    },
    {
      "date": "2026-04-22",
      "is_today": false,
      "mode": "standard",
      "mode_locked": false,
      "required_count": 6,
      "completed_count": 0,
      "planned_minutes": 215,
      "completed_minutes": 0,
      "day_complete": false,
      "tasks": [
        {
          "task_id": 1,
          "slug": "shipped-proof-unit",
          "label": "Marketing - 100days experiment added",
          "completed": false,
          "target_minutes": 20,
          "minimum_target_minutes": 10,
          "minutes_for_day_mode": 20
        },
        {
          "task_id": 2,
          "slug": "sales-outbound",
          "label": "Sales - 30 DMs",
          "completed": false,
          "target_minutes": 60,
          "minimum_target_minutes": 20,
          "minutes_for_day_mode": 60
        },
        {
          "task_id": 3,
          "slug": "social-replies",
          "label": "Social - 30 replies",
          "completed": false,
          "target_minutes": 45,
          "minimum_target_minutes": 15,
          "minutes_for_day_mode": 45
        },
        {
          "task_id": 4,
          "slug": "job-applications",
          "label": "Job Search - 3 application",
          "completed": false,
          "target_minutes": 45,
          "minimum_target_minutes": 20,
          "minutes_for_day_mode": 45
        },
        {
          "task_id": 5,
          "slug": "course-progress",
          "label": "Course - 30 minutes on a new chapter",
          "completed": false,
          "target_minutes": 30,
          "minimum_target_minutes": 15,
          "minutes_for_day_mode": 30
        },
        {
          "task_id": 6,
          "slug": "marketing-build-post",
          "label": "Build in Public - summary post of the day",
          "completed": false,
          "target_minutes": 15,
          "minimum_target_minutes": 10,
          "minutes_for_day_mode": 15
        }
      ]
    },
    {
      "date": "2026-04-23",
      "is_today": false,
      "mode": "standard",
      "mode_locked": false,
      "required_count": 6,
      "completed_count": 0,
      "planned_minutes": 215,
      "completed_minutes": 0,
      "day_complete": false,
      "tasks": [
        {
          "task_id": 1,
          "slug": "shipped-proof-unit",
          "label": "Marketing - 100days experiment added",
          "completed": false,
          "target_minutes": 20,
          "minimum_target_minutes": 10,
          "minutes_for_day_mode": 20
        },
        {
          "task_id": 2,
          "slug": "sales-outbound",
          "label": "Sales - 30 DMs",
          "completed": false,
          "target_minutes": 60,
          "minimum_target_minutes": 20,
          "minutes_for_day_mode": 60
        },
        {
          "task_id": 3,
          "slug": "social-replies",
          "label": "Social - 30 replies",
          "completed": false,
          "target_minutes": 45,
          "minimum_target_minutes": 15,
          "minutes_for_day_mode": 45
        },
        {
          "task_id": 4,
          "slug": "job-applications",
          "label": "Job Search - 3 application",
          "completed": false,
          "target_minutes": 45,
          "minimum_target_minutes": 20,
          "minutes_for_day_mode": 45
        },
        {
          "task_id": 5,
          "slug": "course-progress",
          "label": "Course - 30 minutes on a new chapter",
          "completed": false,
          "target_minutes": 30,
          "minimum_target_minutes": 15,
          "minutes_for_day_mode": 30
        },
        {
          "task_id": 6,
          "slug": "marketing-build-post",
          "label": "Build in Public - summary post of the day",
          "completed": false,
          "target_minutes": 15,
          "minimum_target_minutes": 10,
          "minutes_for_day_mode": 15
        }
      ]
    },
    {
      "date": "2026-04-24",
      "is_today": false,
      "mode": "standard",
      "mode_locked": false,
      "required_count": 6,
      "completed_count": 0,
      "planned_minutes": 215,
      "completed_minutes": 0,
      "day_complete": false,
      "tasks": [
        {
          "task_id": 1,
          "slug": "shipped-proof-unit",
          "label": "Marketing - 100days experiment added",
          "completed": false,
          "target_minutes": 20,
          "minimum_target_minutes": 10,
          "minutes_for_day_mode": 20
        },
        {
          "task_id": 2,
          "slug": "sales-outbound",
          "label": "Sales - 30 DMs",
          "completed": false,
          "target_minutes": 60,
          "minimum_target_minutes": 20,
          "minutes_for_day_mode": 60
        },
        {
          "task_id": 3,
          "slug": "social-replies",
          "label": "Social - 30 replies",
          "completed": false,
          "target_minutes": 45,
          "minimum_target_minutes": 15,
          "minutes_for_day_mode": 45
        },
        {
          "task_id": 4,
          "slug": "job-applications",
          "label": "Job Search - 3 application",
          "completed": false,
          "target_minutes": 45,
          "minimum_target_minutes": 20,
          "minutes_for_day_mode": 45
        },
        {
          "task_id": 5,
          "slug": "course-progress",
          "label": "Course - 30 minutes on a new chapter",
          "completed": false,
          "target_minutes": 30,
          "minimum_target_minutes": 15,
          "minutes_for_day_mode": 30
        },
        {
          "task_id": 6,
          "slug": "marketing-build-post",
          "label": "Build in Public - summary post of the day",
          "completed": false,
          "target_minutes": 15,
          "minimum_target_minutes": 10,
          "minutes_for_day_mode": 15
        }
      ]
    },
    {
      "date": "2026-04-25",
      "is_today": false,
      "mode": "standard",
      "mode_locked": false,
      "required_count": 6,
      "completed_count": 0,
      "planned_minutes": 215,
      "completed_minutes": 0,
      "day_complete": false,
      "tasks": [
        {
          "task_id": 1,
          "slug": "shipped-proof-unit",
          "label": "Marketing - 100days experiment added",
          "completed": false,
          "target_minutes": 20,
          "minimum_target_minutes": 10,
          "minutes_for_day_mode": 20
        },
        {
          "task_id": 2,
          "slug": "sales-outbound",
          "label": "Sales - 30 DMs",
          "completed": false,
          "target_minutes": 60,
          "minimum_target_minutes": 20,
          "minutes_for_day_mode": 60
        },
        {
          "task_id": 3,
          "slug": "social-replies",
          "label": "Social - 30 replies",
          "completed": false,
          "target_minutes": 45,
          "minimum_target_minutes": 15,
          "minutes_for_day_mode": 45
        },
        {
          "task_id": 4,
          "slug": "job-applications",
          "label": "Job Search - 3 application",
          "completed": false,
          "target_minutes": 45,
          "minimum_target_minutes": 20,
          "minutes_for_day_mode": 45
        },
        {
          "task_id": 5,
          "slug": "course-progress",
          "label": "Course - 30 minutes on a new chapter",
          "completed": false,
          "target_minutes": 30,
          "minimum_target_minutes": 15,
          "minutes_for_day_mode": 30
        },
        {
          "task_id": 6,
          "slug": "marketing-build-post",
          "label": "Build in Public - summary post of the day",
          "completed": false,
          "target_minutes": 15,
          "minimum_target_minutes": 10,
          "minutes_for_day_mode": 15
        }
      ]
    },
    {
      "date": "2026-04-26",
      "is_today": true,
      "mode": "standard",
      "mode_locked": false,
      "required_count": 6,
      "completed_count": 0,
      "planned_minutes": 215,
      "completed_minutes": 0,
      "day_complete": false,
      "tasks": [
        {
          "task_id": 1,
          "slug": "shipped-proof-unit",
          "label": "Marketing - 100days experiment added",
          "completed": false,
          "target_minutes": 20,
          "minimum_target_minutes": 10,
          "minutes_for_day_mode": 20
        },
        {
          "task_id": 2,
          "slug": "sales-outbound",
          "label": "Sales - 30 DMs",
          "completed": false,
          "target_minutes": 60,
          "minimum_target_minutes": 20,
          "minutes_for_day_mode": 60
        },
        {
          "task_id": 3,
          "slug": "social-replies",
          "label": "Social - 30 replies",
          "completed": false,
          "target_minutes": 45,
          "minimum_target_minutes": 15,
          "minutes_for_day_mode": 45
        },
        {
          "task_id": 4,
          "slug": "job-applications",
          "label": "Job Search - 3 application",
          "completed": false,
          "target_minutes": 45,
          "minimum_target_minutes": 20,
          "minutes_for_day_mode": 45
        },
        {
          "task_id": 5,
          "slug": "course-progress",
          "label": "Course - 30 minutes on a new chapter",
          "completed": false,
          "target_minutes": 30,
          "minimum_target_minutes": 15,
          "minutes_for_day_mode": 30
        },
        {
          "task_id": 6,
          "slug": "marketing-build-post",
          "label": "Build in Public - summary post of the day",
          "completed": false,
          "target_minutes": 15,
          "minimum_target_minutes": 10,
          "minutes_for_day_mode": 15
        }
      ]
    }
  ]
}