toggl-track 0.1.0

General-purpose async Rust library for the Toggl Track API v9
Documentation

toggl-track

toggl-track is a general-purpose async Rust library for the Toggl Track API v9.

The crate is intentionally library-first: it contains no CLI, TUI, local database cache, reporting layer, or app-specific configuration storage. It provides typed request/response models around commonly used Toggl Track API operations and leaves application policy to callers.

Status

Initial development. The current implementation covers the reusable Toggl API client pieces extracted from toggl-timeguru and is not yet a complete wrapper for every Toggl Track endpoint.

Install

[dependencies]
toggl-track = "0.1"

Quick start

use toggl_track::{Result, TogglTrackClient};

#[tokio::main]
async fn main() -> Result<()> {
    let client = TogglTrackClient::new("your-api-token")?;
    let user = client.current_user().await?;

    println!("Authenticated as {}", user.email);
    Ok(())
}

Time entries

use chrono::{TimeZone, Utc};
use toggl_track::{Result, TogglTrackClient};

#[tokio::main]
async fn main() -> Result<()> {
    let client = TogglTrackClient::new("your-api-token")?;
    let start = Utc.with_ymd_and_hms(2026, 4, 1, 0, 0, 0).unwrap();
    let end = Utc.with_ymd_and_hms(2026, 4, 2, 0, 0, 0).unwrap();

    let entries = client.time_entries(start, end).await?;
    println!("loaded {} entries", entries.len());

    Ok(())
}

Starting and stopping a timer

use toggl_track::{Result, StartTimeEntry, TogglTrackClient};

#[tokio::main]
async fn main() -> Result<()> {
    let client = TogglTrackClient::new("your-api-token")?;
    let workspace_id = 123456;

    let started = client
        .start_time_entry(&StartTimeEntry::new(workspace_id, "my-app").description("Code review"))
        .await?;

    let stopped = client.stop_time_entry(workspace_id, started.id).await?;
    println!("stopped entry {}", stopped.id);

    Ok(())
}

Implemented API surface

  • GET /me
  • GET /me/time_entries
  • GET /me/time_entries/current
  • GET /me/time_entries/{time_entry_id}
  • POST /workspaces/{workspace_id}/time_entries
  • PUT /workspaces/{workspace_id}/time_entries/{time_entry_id}
  • DELETE /workspaces/{workspace_id}/time_entries/{time_entry_id}
  • PATCH /workspaces/{workspace_id}/time_entries/{time_entry_id}/stop
  • PATCH /workspaces/{workspace_id}/time_entries/{time_entry_ids} for bulk edits
  • GET /workspaces
  • GET /workspaces/{workspace_id}/projects

See docs/GAPS.md for the endpoint and feature gap review.

Design notes

  • Uses reqwest with rustls-tls.
  • Authenticates with a Toggl API token via HTTP Basic auth using api_token as the password.
  • Tracks X-Toggl-Quota-Remaining and X-Toggl-Quota-Resets-In headers.
  • Provides a configurable base URL and retry policy for tests and callers.
  • Uses a crate-specific Error type instead of anyhow.

License

MIT