Time Tracking

Track billable time by project and client for accurate invoicing and profitability analysis.

Dashboard

The Time Tracking dashboard gives you a complete overview of your tracked time:

  • Project sidebar - All your projects listed with colour dots and per-project time totals. Click any project to filter the dashboard to just that project's entries.
  • Live timer - Start/stop timer with project and description. Compact gradient bar at the top of the dashboard.
  • Stats cards - Today's total, this week's total, billable hours with earnings, and active project count.
  • Time per Project chart - Stacked bar chart showing hours tracked per project per day.
  • Project Breakdown donut - Visual split of time across projects.
  • Day-grouped entries - Recent entries grouped by day with per-day totals.

Projects

Manage projects from the dedicated Projects page (Time Tracking → Projects):

FieldDescription
NameProject/client name
RateHourly rate (£)
ClientAssociated client name
ColourVisual identifier across dashboard and charts
StatusActive or Archived

Projects can be created, edited, archived, and deleted. Archiving hides a project from the dashboard sidebar while preserving all linked time entries.

Logging Time

Each time entry records:

  • Date and duration (hours:minutes)
  • Project association
  • Description of work performed
  • Billable flag (included on invoices)

Timing App Import

Import time entries from the macOS Timing app with full preview and selection before anything touches your database.

Import Flow

  1. Click Import on the Time Tracking dashboard
  2. Choose your source: Web API (with optional date range) or CSV Export (drag-drop file)
  3. Click Preview to see all projects and entries that would be imported
  4. Select or deselect individual projects and entries - duplicates are automatically flagged and disabled
  5. Click Import to bring in only your selected items

API Mode (Cloud)

Connect via the Timing Web API for importing from any device:

  1. Go to web.timingapp.com → Account → API Keys
  2. Generate a new API token
  3. In TaxMTD, click ImportConnect Timing API
  4. Paste your token and click Connect

CSV Export (Any Timing User)

For users who don't sync Timing data to the cloud - export directly from the app:

  1. In the Timing app, select the date range you want to export
  2. Go to File → Export Report and save as CSV
  3. In TaxMTD, click Import → drop the CSV file → Preview

How It Works

  • Preview before import - See exactly what will be imported. Select only the projects and entries you want.
  • Project mapping - Timing projects are automatically created as TaxMTD projects on first import. Subsequent imports reuse the mapped project.
  • Deduplication - Each imported entry is tagged with a unique provider_reference. Already-imported entries are flagged as duplicates in the preview and cannot be re-imported.
  • Date range filtering - Optionally specify start/end dates to import a specific period.
  • Entry mapping - Timing's title and notes become the description, duration is converted to hours, and entries are marked as billable by default.

API

JavaScript
// List projects
const projects = await $fetch('https://taxmtd.uk/api/projects')

// Create time entry
await $fetch('https://taxmtd.uk/api/time-entries', {
  method: 'POST',
  body: {
    projectId: 1,
    date: '2026-03-01',
    duration: 3.5,
    description: 'Frontend development',
    billable: true
  }
})

// Get all time entries
const entries = await $fetch('https://taxmtd.uk/api/time-entries')
Python
# List projects
projects = requests.get(
    "https://taxmtd.uk/api/projects",
    cookies=session_cookies,
).json()["data"]

# Create time entry
requests.post(
    "https://taxmtd.uk/api/time-entries",
    json={
        "projectId": 1,
        "date": "2026-03-01",
        "duration": 3.5,
        "description": "Frontend development",
        "billable": True,
    },
    cookies=session_cookies,
)

# Get all time entries
entries = requests.get(
    "https://taxmtd.uk/api/time-entries",
    cookies=session_cookies,
).json()["data"]
PHP
// List projects
$projects = Http::withCookies($session)
    ->get('https://taxmtd.uk/api/projects')
    ->json()['data'];

// Create time entry
Http::withCookies($session)
    ->post('https://taxmtd.uk/api/time-entries', [
        'projectId' => 1,
        'date' => '2026-03-01',
        'duration' => 3.5,
        'description' => 'Frontend development',
        'billable' => true,
    ]);

// Get all time entries
$entries = Http::withCookies($session)
    ->get('https://taxmtd.uk/api/time-entries')
    ->json()['data'];
Rust
// List projects
let projects = client
    .get("https://taxmtd.uk/api/projects")
    .send().await?
    .json::<serde_json::Value>().await?;

// Create time entry
client.post("https://taxmtd.uk/api/time-entries")
    .json(&serde_json::json!({
        "projectId": 1,
        "date": "2026-03-01",
        "duration": 3.5,
        "description": "Frontend development",
        "billable": true
    }))
    .send().await?;

// Get all time entries
let entries = client
    .get("https://taxmtd.uk/api/time-entries")
    .send().await?
    .json::<serde_json::Value>().await?;
cURL
# List projects
curl https://taxmtd.uk/api/projects

# Create time entry
curl -X POST https://taxmtd.uk/api/time-entries \
  -H "Content-Type: application/json" \
  -d '{"projectId":1,"date":"2026-03-01","duration":3.5,"description":"Frontend dev","billable":true}'