tools

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 19, 2026 License: MIT Imports: 30 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ApprovalAuditTrail

type ApprovalAuditTrail struct {
	State         string         `json:"state,omitempty"`
	UpdatedBy     string         `json:"updated_by,omitempty"`
	UpdatedByName string         `json:"updated_by_name,omitempty"`
	UpdatedAt     string         `json:"updated_at,omitempty"`
	Note          string         `json:"note,omitempty"`
	Creator       map[string]any `json:"creator,omitempty"`
	Source        string         `json:"source,omitempty"`
	Raw           map[string]any `json:"raw,omitempty"`
}

type ApprovalDurationTotals

type ApprovalDurationTotals struct {
	Approved *EntryDurationView `json:"approved,omitempty"`
	Pending  *EntryDurationView `json:"pending,omitempty"`
	Tracked  *EntryDurationView `json:"tracked,omitempty"`
	Billable *EntryDurationView `json:"billable,omitempty"`
	Break    *EntryDurationView `json:"break,omitempty"`
}

type ApprovalExpenseSummary

type ApprovalExpenseSummary struct {
	Count         int        `json:"count"`
	BillableCount int        `json:"billable_count,omitempty"`
	Amount        *MoneyView `json:"amount,omitempty"`
	Source        string     `json:"source"`
	Reason        string     `json:"reason,omitempty"`
}

type ApprovalMoneyTotals

type ApprovalMoneyTotals struct {
	Earned   *MoneyView `json:"earned,omitempty"`
	Cost     *MoneyView `json:"cost,omitempty"`
	Expenses *MoneyView `json:"expenses,omitempty"`
	Profit   *MoneyView `json:"profit,omitempty"`
	Source   string     `json:"source"`
	Reason   string     `json:"reason,omitempty"`
}

type ApprovalView

type ApprovalView struct {
	ID               string                          `json:"id,omitempty"`
	Request          map[string]any                  `json:"request,omitempty"`
	Owner            map[string]any                  `json:"owner,omitempty"`
	Creator          map[string]any                  `json:"creator,omitempty"`
	Status           map[string]any                  `json:"status,omitempty"`
	AuditTrail       *ApprovalAuditTrail             `json:"audit_trail,omitempty"`
	DateRange        any                             `json:"date_range,omitempty"`
	Totals           map[string]any                  `json:"totals,omitempty"`
	DurationTotals   ApprovalDurationTotals          `json:"duration_totals"`
	MoneyTotals      ApprovalMoneyTotals             `json:"money_totals"`
	Financials       EntryFinancials                 `json:"financials"`
	EntrySummary     ReportEntrySummary              `json:"entry_summary"`
	ExpenseSummary   ApprovalExpenseSummary          `json:"expense_summary"`
	ClientSummary    []ReportClientSummary           `json:"client_summary,omitempty"`
	Rollups          map[string][]ReportEntityRollup `json:"rollups,omitempty"`
	Entries          []ReportEntryView               `json:"entries,omitempty"`
	Expenses         []map[string]any                `json:"expenses,omitempty"`
	Actions          []string                        `json:"actions,omitempty"`
	SuggestedActions []ToolSuggestion                `json:"suggestedActions,omitempty"`
	Raw              map[string]any                  `json:"raw,omitempty"`
}

type AssignmentDurationView

type AssignmentDurationView struct {
	Seconds int64   `json:"seconds"`
	Hours   float64 `json:"hours"`
	Display string  `json:"display,omitempty"`
}

type AssignmentReportData

type AssignmentReportData struct {
	Range  FinancialRangeView     `json:"range"`
	Groups []string               `json:"groups"`
	Rows   []AssignmentReportRow  `json:"rows"`
	Totals AssignmentReportTotals `json:"totals"`
	Raw    map[string]any         `json:"raw,omitempty"`
}

type AssignmentReportMoney

type AssignmentReportMoney struct {
	Earned *MoneyView `json:"earned,omitempty"`
	Cost   *MoneyView `json:"cost,omitempty"`
	Profit *MoneyView `json:"profit,omitempty"`
	Source string     `json:"source"`
	Reason string     `json:"reason,omitempty"`
}

type AssignmentReportRow

type AssignmentReportRow struct {
	Title            string                 `json:"title"`
	GroupKey         map[string]string      `json:"group_key"`
	Entities         map[string]any         `json:"entities,omitempty"`
	Scheduled        AssignmentDurationView `json:"scheduled"`
	Available        AssignmentDurationView `json:"available"`
	AmountScheduled  *MoneyView             `json:"amount_scheduled,omitempty"`
	CostScheduled    *MoneyView             `json:"cost_scheduled,omitempty"`
	ExpectedProfit   *MoneyView             `json:"expected_profit,omitempty"`
	Tracked          AssignmentDurationView `json:"tracked"`
	AmountTracked    *MoneyView             `json:"amount_tracked,omitempty"`
	CostTracked      *MoneyView             `json:"cost_tracked,omitempty"`
	Difference       AssignmentDurationView `json:"difference"`
	AmountDifference *MoneyView             `json:"amount_difference,omitempty"`
	CostDifference   *MoneyView             `json:"cost_difference,omitempty"`
	RealizedProfit   *MoneyView             `json:"realized_profit,omitempty"`
	Status           string                 `json:"status,omitempty"`
	Financials       AssignmentReportMoney  `json:"financials"`
	Source           string                 `json:"source"`
	Warnings         []string               `json:"warnings,omitempty"`
	Raw              map[string]any         `json:"raw,omitempty"`
}

type AssignmentReportTotals

type AssignmentReportTotals struct {
	Scheduled        AssignmentDurationView `json:"scheduled"`
	Available        AssignmentDurationView `json:"available"`
	Tracked          AssignmentDurationView `json:"tracked"`
	Difference       AssignmentDurationView `json:"difference"`
	AmountScheduled  *MoneyView             `json:"amount_scheduled,omitempty"`
	CostScheduled    *MoneyView             `json:"cost_scheduled,omitempty"`
	ExpectedProfit   *MoneyView             `json:"expected_profit,omitempty"`
	AmountTracked    *MoneyView             `json:"amount_tracked,omitempty"`
	CostTracked      *MoneyView             `json:"cost_tracked,omitempty"`
	AmountDifference *MoneyView             `json:"amount_difference,omitempty"`
	CostDifference   *MoneyView             `json:"cost_difference,omitempty"`
	RealizedProfit   *MoneyView             `json:"realized_profit,omitempty"`
}

type AssignmentView

type AssignmentView map[string]any

type ChangeSet

type ChangeSet struct {
	Created []EntityRef `json:"created,omitempty"`
	Updated []EntityRef `json:"updated,omitempty"`
	Deleted []EntityRef `json:"deleted,omitempty"`
	Reused  []EntityRef `json:"reused,omitempty"`
}

type ClientApprovalSummary

type ClientApprovalSummary struct {
	Source                 string                       `json:"source"`
	Reason                 string                       `json:"reason,omitempty"`
	WithApprovalRequest    int                          `json:"with_approval_request,omitempty"`
	WithoutApprovalRequest int                          `json:"without_approval_request,omitempty"`
	RequestIDs             []string                     `json:"request_ids,omitempty"`
	States                 map[string]int               `json:"states,omitempty"`
	DurationsByState       map[string]EntryDurationView `json:"durations_by_state,omitempty"`
}

type ClientContactView

type ClientContactView struct {
	Email    string `json:"email,omitempty"`
	Address  string `json:"address,omitempty"`
	Note     string `json:"note,omitempty"`
	CCEmails any    `json:"ccEmails,omitempty"`
}

type ClientCurrencyView

type ClientCurrencyView struct {
	Code string `json:"code,omitempty"`
	ID   string `json:"id,omitempty"`
}

type ClientInvoiceSummary

type ClientInvoiceSummary struct {
	TotalCount    int            `json:"total_count,omitempty"`
	ReturnedCount int            `json:"returned_count,omitempty"`
	Amount        *MoneyView     `json:"amount,omitempty"`
	Balance       *MoneyView     `json:"balance,omitempty"`
	Paid          *MoneyView     `json:"paid,omitempty"`
	OverdueCount  int            `json:"overdue_count,omitempty"`
	ByStatus      map[string]int `json:"by_status,omitempty"`
	Source        string         `json:"source"`
	Reason        string         `json:"reason,omitempty"`
}

type ClientProjectSummary

type ClientProjectSummary struct {
	Count         int  `json:"count"`
	ActiveCount   int  `json:"active_count,omitempty"`
	ArchivedCount int  `json:"archived_count,omitempty"`
	BillableCount int  `json:"billable_count,omitempty"`
	TasksCount    int  `json:"tasks_count,omitempty"`
	Truncated     bool `json:"truncated,omitempty"`
}

type ClientTimeSummary

type ClientTimeSummary struct {
	TrackedDurationSeconds int64   `json:"tracked_duration_seconds,omitempty"`
	TrackedHours           float64 `json:"tracked_hours,omitempty"`
	TrackedDisplay         string  `json:"tracked_display,omitempty"`
	EntriesCount           int     `json:"entries_count,omitempty"`
	Source                 string  `json:"source"`
	Reason                 string  `json:"reason,omitempty"`
}

type ClientView

type ClientView struct {
	ID           string `json:"id"`
	Name         string `json:"name"`
	Address      string `json:"address,omitempty"`
	Archived     bool   `json:"archived,omitempty"`
	CCEmails     any    `json:"ccEmails,omitempty"`
	CurrencyCode string `json:"currencyCode,omitempty"`
	CurrencyID   string `json:"currencyId,omitempty"`
	Email        string `json:"email,omitempty"`
	Note         string `json:"note,omitempty"`
	WorkspaceID  string `json:"workspaceId,omitempty"`

	Currency        ClientCurrencyView    `json:"currency"`
	Contact         ClientContactView     `json:"contact"`
	ProjectSummary  ClientProjectSummary  `json:"project_summary"`
	Financials      ProjectFinancials     `json:"financials"`
	TimeSummary     ClientTimeSummary     `json:"time_summary"`
	InvoiceSummary  ClientInvoiceSummary  `json:"invoice_summary"`
	ApprovalSummary ClientApprovalSummary `json:"approval_summary"`
	Warnings        []string              `json:"warnings,omitempty"`
}

type CompactExpenseView

type CompactExpenseView struct {
	ID           string     `json:"id"`
	Date         string     `json:"date,omitempty"`
	Amount       *MoneyView `json:"amount,omitempty"`
	CategoryID   string     `json:"categoryId,omitempty"`
	CategoryName string     `json:"categoryName,omitempty"`
	ProjectID    string     `json:"projectId,omitempty"`
	ProjectName  string     `json:"projectName,omitempty"`
	UserID       string     `json:"userId,omitempty"`
	Billable     bool       `json:"billable,omitempty"`
	Locked       bool       `json:"locked,omitempty"`
	Notes        string     `json:"notes,omitempty"`
}

type CompactInvoiceView

type CompactInvoiceView struct {
	ID         string     `json:"id"`
	Number     string     `json:"number,omitempty"`
	Status     string     `json:"status,omitempty"`
	ClientID   string     `json:"clientId,omitempty"`
	ClientName string     `json:"clientName,omitempty"`
	IssuedDate string     `json:"issuedDate,omitempty"`
	DueDate    string     `json:"dueDate,omitempty"`
	Currency   string     `json:"currency,omitempty"`
	Amount     *MoneyView `json:"amount,omitempty"`
}

type CompactProjectView

type CompactProjectView struct {
	ID         string `json:"id"`
	Name       string `json:"name"`
	ClientID   string `json:"clientId,omitempty"`
	ClientName string `json:"clientName,omitempty"`
	Color      string `json:"color,omitempty"`
	Archived   bool   `json:"archived"`
	Billable   bool   `json:"billable,omitempty"`
	Public     bool   `json:"public,omitempty"`
	Duration   string `json:"duration,omitempty"`
}

type CompactTimeOffPolicyView

type CompactTimeOffPolicyView struct {
	ID             string `json:"id"`
	Name           string `json:"name"`
	Archived       bool   `json:"archived,omitempty"`
	TimeUnit       string `json:"timeUnit,omitempty"`
	UserCount      int    `json:"userCount"`
	UserGroupCount int    `json:"userGroupCount"`
	AssigneeCount  int    `json:"assigneeCount"`
}

type CompactUserView

type CompactUserView struct {
	ID               string `json:"id"`
	Name             string `json:"name"`
	Email            string `json:"email"`
	Status           string `json:"status,omitempty"`
	ActiveWorkspace  string `json:"activeWorkspace,omitempty"`
	DefaultWorkspace string `json:"defaultWorkspace,omitempty"`
}

CompactUserView is the per-user shape emitted by clockify_users_list. It omits the heavy memberships, settings, and custom-field payloads that made the full list overflow the transport budget. clockify_users_profile still returns the full UserView for a single user.

type CustomFieldDefinitionView

type CustomFieldDefinitionView struct {
	ID         string `json:"id,omitempty"`
	Name       string `json:"name,omitempty"`
	Type       string `json:"type,omitempty"`
	Status     string `json:"status,omitempty"`
	EntityType string `json:"entity_type,omitempty"`
	Source     string `json:"source,omitempty"`
}

type CustomFieldValueView

type CustomFieldValueView struct {
	ID            string `json:"id,omitempty"`
	CustomFieldID string `json:"custom_field_id,omitempty"`
	Name          string `json:"name,omitempty"`
	Type          string `json:"type,omitempty"`
	Status        string `json:"status,omitempty"`
	EntityType    string `json:"entity_type,omitempty"`
	Value         any    `json:"value,omitempty"`
	Source        string `json:"source"`
}

type DateRange

type DateRange struct {
	Start string `json:"start"`
	End   string `json:"end"`
}

DateRange is the inclusive [Start, End] window used by every summary / report payload to describe the period the rollup spans.

type DaySummary

type DaySummary struct {
	Date         string  `json:"date"`
	Entries      int     `json:"entries"`
	TotalSeconds int64   `json:"totalSeconds"`
	TotalHours   float64 `json:"totalHours"`
}

DaySummary is the per-day rollup row used by WeeklySummaryData. Date is RFC 3339 YYYY-MM-DD in the configured timezone.

type EffectiveRate

type EffectiveRate struct {
	Hourly      *clockify.Rate `json:"hourly,omitempty"`
	Cost        *clockify.Rate `json:"cost,omitempty"`
	HourlyScope RateScope      `json:"hourly_scope"`
	CostScope   RateScope      `json:"cost_scope"`
}

EffectiveRate is the resolved hourly + cost rate that should be applied to a given (workspace, project, task, entry, user) combination. The Scope fields tell the caller which layer of the hierarchy supplied the rate so the model can explain its answer.

func ResolveEffectiveRate

func ResolveEffectiveRate(
	ws *clockify.Workspace,
	proj *clockify.Project,
	task *clockify.Task,
	entry *clockify.TimeEntry,
	userID string,
) EffectiveRate

ResolveEffectiveRate walks the Clockify rate hierarchy:

entry > task > project-member (matched on userID) > project >
workspace-member (matched on userID) > workspace

Any of the inputs may be nil. The returned EffectiveRate.Scope is RateScopeNone when no layer supplied a rate. Hourly and Cost are resolved independently because a workspace can legitimately set a cost rate without a billable rate (and vice versa).

type EntityRef

type EntityRef struct {
	Type string `json:"type"`
	ID   string `json:"id"`
	Name string `json:"name,omitempty"`
}

type EntryApprovalView

type EntryApprovalView struct {
	RequestID string         `json:"request_id,omitempty"`
	State     string         `json:"state,omitempty"`
	Source    string         `json:"source,omitempty"`
	Raw       map[string]any `json:"raw,omitempty"`
}

type EntryAuditView

type EntryAuditView struct {
	Locked             *bool          `json:"locked,omitempty"`
	MissingDescription *bool          `json:"missing_description,omitempty"`
	MissingProject     *bool          `json:"missing_project,omitempty"`
	MissingTask        *bool          `json:"missing_task,omitempty"`
	Source             string         `json:"source,omitempty"`
	Raw                map[string]any `json:"raw,omitempty"`
}

type EntryDurationView

type EntryDurationView struct {
	Seconds int64   `json:"seconds"`
	Hours   float64 `json:"hours"`
	Display string  `json:"display"`
	Source  string  `json:"source,omitempty"`
}

EntryDurationView is the normalized duration block used by report-derived entry views and summaries.

type EntryEntitiesView

type EntryEntitiesView struct {
	User    *EntryEntityRef  `json:"user,omitempty"`
	Client  *EntryEntityRef  `json:"client,omitempty"`
	Project *EntryEntityRef  `json:"project,omitempty"`
	Task    *EntryEntityRef  `json:"task,omitempty"`
	Tags    []EntryEntityRef `json:"tags,omitempty"`
}

type EntryEntityRef

type EntryEntityRef struct {
	ID    string         `json:"id,omitempty"`
	Name  string         `json:"name,omitempty"`
	Email string         `json:"email,omitempty"`
	Color string         `json:"color,omitempty"`
	Raw   map[string]any `json:"raw,omitempty"`
}

EntryEntityRef keeps entity IDs and names close to the entry that produced them without forcing callers to understand Clockify's varying row shapes.

type EntryFinancials

type EntryFinancials struct {
	Earned *MoneyView     `json:"earned,omitempty"`
	Cost   *MoneyView     `json:"cost,omitempty"`
	Profit *MoneyView     `json:"profit,omitempty"`
	Source string         `json:"source"`
	Reason string         `json:"reason,omitempty"`
	Rate   *EntryRateView `json:"rate,omitempty"`
}

type EntryInvoicingView

type EntryInvoicingView struct {
	Invoiced      *bool          `json:"invoiced,omitempty"`
	State         string         `json:"state,omitempty"`
	InvoiceID     string         `json:"invoice_id,omitempty"`
	InvoiceNumber string         `json:"invoice_number,omitempty"`
	Source        string         `json:"source,omitempty"`
	Raw           map[string]any `json:"raw,omitempty"`
}

type EntryRateView

type EntryRateView struct {
	EntryHourly      *clockify.Rate `json:"entry_hourly,omitempty"`
	EntryCost        *clockify.Rate `json:"entry_cost,omitempty"`
	EffectiveHourly  *clockify.Rate `json:"effective_hourly,omitempty"`
	EffectiveCost    *clockify.Rate `json:"effective_cost,omitempty"`
	HourlyScope      RateScope      `json:"hourly_scope"`
	CostScope        RateScope      `json:"cost_scope"`
	DurationSeconds  int64          `json:"duration_seconds"`
	BillableEarnings MoneyView      `json:"billable_earnings,omitempty"`
	Cost             MoneyView      `json:"cost,omitempty"`
}

EntryRateView is the LLM-facing block we attach to every time-entry row across tool outputs. It bundles the raw entry-level rates (so the caller can see what Clockify itself stored) with the resolved effective rate and the derived per-entry money.

func BuildEntryRateView

func BuildEntryRateView(
	ws *clockify.Workspace,
	proj *clockify.Project,
	task *clockify.Task,
	entry *clockify.TimeEntry,
) EntryRateView

BuildEntryRateView is the canonical adapter from a (workspace, project, task, entry, user) tuple to the EntryRateView envelope. Callers pass whatever context they have; nils are tolerated.

type EntryView

type EntryView struct {
	ID                string                 `json:"id"`
	Description       string                 `json:"description"`
	ProjectID         string                 `json:"projectId"`
	ProjectName       string                 `json:"projectName,omitempty"`
	TaskID            string                 `json:"taskId,omitempty"`
	TagIDs            []string               `json:"tagIds,omitempty"`
	Billable          bool                   `json:"billable"`
	BillableState     string                 `json:"billable_state"`
	BillablePresent   bool                   `json:"billable_present"`
	CostRate          *clockify.Rate         `json:"costRate,omitempty"`
	CustomFieldValues any                    `json:"customFieldValues,omitempty"`
	CustomFields      []CustomFieldValueView `json:"custom_fields_normalized,omitempty"`
	HourlyRate        *clockify.Rate         `json:"hourlyRate,omitempty"`
	IsLocked          bool                   `json:"isLocked,omitempty"`
	KioskID           string                 `json:"kioskId,omitempty"`
	Type              string                 `json:"type,omitempty"`
	UserID            string                 `json:"userId,omitempty"`
	WorkspaceID       string                 `json:"workspaceId,omitempty"`
	TimeInterval      clockify.TimeInterval  `json:"timeInterval"`
	Financials        EntryFinancials        `json:"financials"`
	Approval          *EntryApprovalView     `json:"approval,omitempty"`
	Invoicing         *EntryInvoicingView    `json:"invoicing,omitempty"`
	Entities          *EntryEntitiesView     `json:"entities,omitempty"`
	Audit             *EntryAuditView        `json:"audit,omitempty"`
}

EntryView is the model-facing time-entry envelope used by every tool that returns entries. It intentionally keeps the original clockify.TimeEntry JSON fields at the top level and appends a financials block so old clients keep working while agents can answer money questions without a second tool call.

type ErrorInfo

type ErrorInfo struct {
	Code    string `json:"code"`
	Message string `json:"message"`
}

type EstimateProgressView

type EstimateProgressView struct {
	TrackedDurationSeconds int64    `json:"tracked_duration_seconds"`
	EstimateSeconds        *int64   `json:"estimate_seconds,omitempty"`
	RemainingSeconds       *int64   `json:"remaining_seconds,omitempty"`
	PercentUsed            *float64 `json:"percent_used,omitempty"`
	OverEstimate           *bool    `json:"over_estimate,omitempty"`
	Source                 string   `json:"source"`
	Reason                 string   `json:"reason,omitempty"`
}

type ExpenseView

type ExpenseView map[string]any

type FeatureLabel

type FeatureLabel struct {
	Key   string `json:"key"`
	Label string `json:"label"`
}

type FinancialRangeView

type FinancialRangeView struct {
	Start         string `json:"start,omitempty"`
	End           string `json:"end,omitempty"`
	DateRangeType string `json:"date_range_type,omitempty"`
	Timezone      string `json:"timezone,omitempty"`
}

type FindAndUpdateEntryData

type FindAndUpdateEntryData struct {
	Entry          EntryView               `json:"entry"`
	MatchedBy      map[string]any          `json:"matchedBy"`
	UpdatedFields  []string                `json:"updatedFields"`
	MatchedEntryID string                  `json:"matched_entry_id,omitempty"`
	Current        *TimeEntryUpdatePreview `json:"current,omitempty"`
	Proposed       map[string]any          `json:"proposed_changes,omitempty"`
	DryRun         bool                    `json:"dry_run,omitempty"`
	Note           string                  `json:"note,omitempty"`
	Validation     *ValidationView         `json:"validation,omitempty"`
}

FindAndUpdateEntryData is the structured payload for clockify_find_and_update_entry. Entry is the matched time entry; MatchedBy explains which finder predicate identified it; UpdatedFields lists the fields that actually changed. When dry_run:true is set, Current + Proposed + DryRun carry the preview-only diff so a downstream confirmation step can stage the mutation before applying.

type InvoiceItemView

type InvoiceItemView map[string]any

type InvoicePaymentView

type InvoicePaymentView map[string]any

type InvoiceReportView

type InvoiceReportView struct {
	Invoices         []InvoiceView  `json:"invoices"`
	AggregationScope string         `json:"aggregationScope"`
	PageTotalAmount  *MoneyView     `json:"pageTotalAmount,omitempty"`
	PageStatusCounts map[string]int `json:"pageStatusCounts,omitempty"`
	TotalAmount      *MoneyView     `json:"totalAmount,omitempty"`
	StatusCounts     map[string]int `json:"statusCounts,omitempty"`
	Summary          InvoiceSummary `json:"summary"`
	Raw              map[string]any `json:"raw,omitempty"`
}

type InvoiceSettingsView

type InvoiceSettingsView map[string]any

type InvoiceSummary

type InvoiceSummary struct {
	Count                 int            `json:"count"`
	ByStatus              map[string]int `json:"by_status,omitempty"`
	OverdueCount          int            `json:"overdue_count,omitempty"`
	ImportedTimeCount     int            `json:"imported_time_count,omitempty"`
	ImportedExpenseCount  int            `json:"imported_expense_count,omitempty"`
	Amount                *MoneyView     `json:"amount,omitempty"`
	Paid                  *MoneyView     `json:"paid,omitempty"`
	Balance               *MoneyView     `json:"balance,omitempty"`
	Currencies            []string       `json:"currencies,omitempty"`
	Source                string         `json:"source"`
	Reason                string         `json:"reason,omitempty"`
	SuggestedActionsCount int            `json:"suggested_actions_count,omitempty"`
}

type InvoiceView

type InvoiceView map[string]any

type MoneyByCurrencyView

type MoneyByCurrencyView struct {
	Type     string         `json:"type,omitempty"`
	Currency string         `json:"currency,omitempty"`
	Money    MoneyView      `json:"money"`
	Raw      map[string]any `json:"raw,omitempty"`
}

type MoneyView

type MoneyView struct {
	AmountCents   int64  `json:"amount_cents"`
	AmountDecimal string `json:"amount_decimal"`
	Currency      string `json:"currency,omitempty"`
	Display       string `json:"display,omitempty"`
}

MoneyView is the LLM-facing envelope for any monetary value the MCP surfaces. The model receives all four fields:

  • amount_cents: int64 minor units (authoritative).
  • amount_decimal: string, two dp, signed (audit / direct render).
  • currency: ISO code from the source.
  • display: pre-rendered symbol form (e.g. "€43.21 EUR").

Callers that have only a JSON-number from the reports host should use MoneyFromReportNumber; callers with an int-cents value (the primary API) should use MoneyFromCents.

func DerivedEarnings

func DerivedEarnings(eff EffectiveRate, durationSeconds int64) (billable, cost MoneyView)

DerivedEarnings multiplies the effective hourly + cost rates by the given duration (in seconds) and returns the per-entry billable earnings and cost as MoneyViews. Both come back zero when no rate is set for that side. Rounding is to the nearest cent.

Math: rate is cents-per-hour; duration is seconds; result is

cents = round(rateCents * durationSeconds / 3600)

We use float intermediates and math.Round for the final cent — matching `CentsFromReportNumber`'s half-away-from-zero behaviour so the MCP-derived number agrees with Clockify's own.

func MoneyFromCents

func MoneyFromCents(cents int64, currency string) MoneyView

MoneyFromCents wraps an int64 cents value into a MoneyView.

func MoneyFromRate

func MoneyFromRate(r *clockify.Rate) MoneyView

MoneyFromRate is a nil-tolerant adapter for `*clockify.Rate`. A nil rate or an inherited sentinel returns the zero MoneyView so callers can decide whether to emit the field at all.

func MoneyFromReportNumber

func MoneyFromReportNumber(v float64, currency string) MoneyView

MoneyFromReportNumber converts a JSON-number cents value coming from the reports.api host (always integer-cents-as-float in practice) to MoneyView. Banker's rounding to int64 cents.

func (MoneyView) IsZero

func (m MoneyView) IsZero() bool

IsZero reports whether the MoneyView carries no information. Used by tool envelopes to decide whether to omit a money field rather than emit "$0.00" when no rate is actually known.

type NextAction

type NextAction struct {
	Tool   string         `json:"tool"`
	Args   map[string]any `json:"args,omitempty"`
	Reason string         `json:"reason,omitempty"`
}

type ProjectEstimateView

type ProjectEstimateView struct {
	EstimateRaw         any        `json:"estimate_raw,omitempty"`
	BudgetEstimateRaw   any        `json:"budget_estimate_raw,omitempty"`
	TimeEstimateRaw     any        `json:"time_estimate_raw,omitempty"`
	EstimateResetRaw    any        `json:"estimate_reset_raw,omitempty"`
	DurationRaw         string     `json:"duration_raw,omitempty"`
	DurationSeconds     *int64     `json:"duration_seconds,omitempty"`
	EstimateSeconds     *int64     `json:"estimate_seconds,omitempty"`
	TimeEstimateSeconds *int64     `json:"time_estimate_seconds,omitempty"`
	BudgetEstimate      *MoneyView `json:"budget_estimate,omitempty"`
}

type ProjectFinancials

type ProjectFinancials struct {
	Earned *MoneyView          `json:"earned,omitempty"`
	Cost   *MoneyView          `json:"cost,omitempty"`
	Profit *MoneyView          `json:"profit,omitempty"`
	Source string              `json:"source"`
	Reason string              `json:"reason,omitempty"`
	Range  *FinancialRangeView `json:"range,omitempty"`
}

type ProjectMemberRateView

type ProjectMemberRateView struct {
	UserID           string         `json:"user_id"`
	TargetID         string         `json:"target_id,omitempty"`
	MembershipType   string         `json:"membership_type,omitempty"`
	MembershipStatus string         `json:"membership_status,omitempty"`
	HourlyRate       *clockify.Rate `json:"hourly_rate,omitempty"`
	CostRate         *clockify.Rate `json:"cost_rate,omitempty"`
	HourlyMoney      *MoneyView     `json:"hourly_money,omitempty"`
	CostMoney        *MoneyView     `json:"cost_money,omitempty"`
}

type ProjectRatesView

type ProjectRatesView struct {
	ProjectHourly      *clockify.Rate          `json:"project_hourly,omitempty"`
	ProjectCost        *clockify.Rate          `json:"project_cost,omitempty"`
	ProjectHourlyMoney *MoneyView              `json:"project_hourly_money,omitempty"`
	ProjectCostMoney   *MoneyView              `json:"project_cost_money,omitempty"`
	Members            []ProjectMemberRateView `json:"members,omitempty"`
	Tasks              []TaskRateView          `json:"tasks,omitempty"`
}

type ProjectSummary

type ProjectSummary struct {
	ProjectID    string  `json:"projectId,omitempty"`
	ProjectName  string  `json:"projectName"`
	ClientID     string  `json:"clientId,omitempty"`
	ClientName   string  `json:"clientName,omitempty"`
	Entries      int     `json:"entries"`
	TotalSeconds int64   `json:"totalSeconds"`
	TotalHours   float64 `json:"totalHours"`
}

ProjectSummary is the per-project rollup row used by WeeklySummaryData and QuickReportData. ProjectID is omitempty so entries that did not resolve to a project (e.g. tracked with no project tag) still appear in the rollup keyed only by ProjectName.

type ProjectView

type ProjectView struct {
	ID                     string                       `json:"id"`
	Name                   string                       `json:"name"`
	ClientID               string                       `json:"clientId,omitempty"`
	ClientName             string                       `json:"clientName,omitempty"`
	Client                 any                          `json:"client,omitempty"`
	Color                  string                       `json:"color,omitempty"`
	Archived               bool                         `json:"archived"`
	Billable               bool                         `json:"billable,omitempty"`
	BudgetEstimate         any                          `json:"budgetEstimate,omitempty"`
	CostRate               *clockify.Rate               `json:"costRate,omitempty"`
	Currency               any                          `json:"currency,omitempty"`
	CustomFields           any                          `json:"customFields,omitempty"`
	CustomFieldsNormalized []CustomFieldValueView       `json:"custom_fields_normalized,omitempty"`
	Duration               string                       `json:"duration,omitempty"`
	Estimate               any                          `json:"estimate,omitempty"`
	EstimateReset          any                          `json:"estimateReset,omitempty"`
	Expenses               any                          `json:"expenses,omitempty"`
	Favorite               bool                         `json:"favorite,omitempty"`
	HourlyRate             *clockify.Rate               `json:"hourlyRate,omitempty"`
	Memberships            []clockify.ProjectMembership `json:"memberships,omitempty"`
	Note                   string                       `json:"note,omitempty"`
	Public                 bool                         `json:"public,omitempty"`
	Template               bool                         `json:"template,omitempty"`
	TimeEstimate           any                          `json:"timeEstimate,omitempty"`
	WorkspaceID            string                       `json:"workspaceId,omitempty"`

	Rates            ProjectRatesView     `json:"rates"`
	Financials       ProjectFinancials    `json:"financials"`
	Estimates        ProjectEstimateView  `json:"estimates"`
	EstimateProgress EstimateProgressView `json:"estimate_progress"`
	Tasks            []TaskView           `json:"tasks,omitempty"`
	ExpensesSummary  map[string]any       `json:"expenses_summary,omitempty"`
	RawHydrated      map[string]any       `json:"raw_hydrated,omitempty"`
}

type QuickReportData

type QuickReportData struct {
	Range               DateRange        `json:"range"`
	Totals              SummaryTotals    `json:"totals"`
	TopProject          *ProjectSummary  `json:"topProject,omitempty"`
	RunningEntries      []EntryView      `json:"runningEntries,omitempty"`
	EntriesSample       []EntryView      `json:"entriesSample,omitempty"`
	ProjectsRepresented int              `json:"projectsRepresented"`
	SuggestedActions    []ToolSuggestion `json:"suggestedActions"`
}

QuickReportData powers clockify_reports_summary: a single-glance snapshot with totals, the top project, any running entries, and a short entry sample so an agent can answer "what did I just do?" without a full detailed report round-trip.

type RateScope

type RateScope string

RateScope identifies which layer of the Clockify rate hierarchy supplied the effective rate for a given time entry. Returned to the model so it can explain *why* a particular earning amount is what it is, rather than only the final number.

const (
	RateScopeEntry         RateScope = "ENTRY"
	RateScopeTask          RateScope = "TASK"
	RateScopeProjectMember RateScope = "PROJECT_MEMBER"
	RateScopeProject       RateScope = "PROJECT"
	RateScopeWorkspace     RateScope = "WORKSPACE"
	RateScopeNone          RateScope = "NONE"
)

type RecoveryHint

type RecoveryHint struct {
	Hint      string         `json:"hint"`
	Tool      string         `json:"tool,omitempty"`
	Args      map[string]any `json:"args,omitempty"`
	Retryable bool           `json:"retryable,omitempty"`
}

type ReportApprovalSummary

type ReportApprovalSummary struct {
	WithApprovalRequest    int                          `json:"with_approval_request,omitempty"`
	WithoutApprovalRequest int                          `json:"without_approval_request,omitempty"`
	RequestIDs             []string                     `json:"request_ids,omitempty"`
	States                 map[string]int               `json:"states,omitempty"`
	DurationsByState       map[string]EntryDurationView `json:"durations_by_state,omitempty"`
}

type ReportClientSummary

type ReportClientSummary struct {
	Client          EntryEntityRef        `json:"client"`
	EntrySummary    ReportEntrySummary    `json:"entry_summary"`
	Financials      EntryFinancials       `json:"financials"`
	ApprovalSummary ReportApprovalSummary `json:"approval_summary"`
}

type ReportDefaults

type ReportDefaults struct {
	Timezone              string `json:"timezone,omitempty"`
	WeekStart             string `json:"week_start,omitempty"`
	DateFormat            string `json:"date_format,omitempty"`
	TimeFormat            string `json:"time_format,omitempty"`
	SummaryReportSettings any    `json:"summary_report_settings,omitempty"`
	Source                string `json:"source,omitempty"`
}

type ReportEntityRollup

type ReportEntityRollup struct {
	ID       string            `json:"id,omitempty"`
	Name     string            `json:"name,omitempty"`
	Email    string            `json:"email,omitempty"`
	Color    string            `json:"color,omitempty"`
	Count    int               `json:"count"`
	Duration EntryDurationView `json:"duration"`
}

type ReportEntitySummary

type ReportEntitySummary struct {
	Users    []ReportEntityRollup `json:"users,omitempty"`
	Clients  []ReportEntityRollup `json:"clients,omitempty"`
	Projects []ReportEntityRollup `json:"projects,omitempty"`
	Tasks    []ReportEntityRollup `json:"tasks,omitempty"`
	Tags     []ReportEntityRollup `json:"tags,omitempty"`
}

type ReportEntrySummary

type ReportEntrySummary struct {
	Count                   int               `json:"count"`
	Duration                EntryDurationView `json:"duration"`
	BillableCount           int               `json:"billable_count,omitempty"`
	UnbillableCount         int               `json:"unbillable_count,omitempty"`
	BillableUnsetCount      int               `json:"billable_unset_count,omitempty"`
	LockedCount             int               `json:"locked_count,omitempty"`
	MissingDescriptionCount int               `json:"missing_description_count,omitempty"`
	MissingProjectCount     int               `json:"missing_project_count,omitempty"`
	MissingTaskCount        int               `json:"missing_task_count,omitempty"`
	ByType                  map[string]int    `json:"by_type,omitempty"`
}

type ReportEntryView

type ReportEntryView struct {
	ID                string                   `json:"id,omitempty"`
	Description       string                   `json:"description,omitempty"`
	Type              string                   `json:"type,omitempty"`
	Billable          *bool                    `json:"billable,omitempty"`
	BillableState     string                   `json:"billable_state,omitempty"`
	BillablePresent   bool                     `json:"billable_present,omitempty"`
	Locked            *bool                    `json:"locked,omitempty"`
	Duration          *EntryDurationView       `json:"duration,omitempty"`
	TimeInterval      map[string]any           `json:"time_interval,omitempty"`
	Entities          *EntryEntitiesView       `json:"entities,omitempty"`
	CustomFieldValues any                      `json:"customFieldValues,omitempty"`
	CustomFields      []CustomFieldValueView   `json:"custom_fields_normalized,omitempty"`
	Approval          *EntryApprovalView       `json:"approval,omitempty"`
	Invoicing         *EntryInvoicingView      `json:"invoicing,omitempty"`
	Audit             *EntryAuditView          `json:"audit,omitempty"`
	Financials        EntryFinancials          `json:"financials"`
	RateBreakdown     *ReportRateBreakdownView `json:"rate_breakdown,omitempty"`
	MoneyByCurrency   []MoneyByCurrencyView    `json:"money_by_currency,omitempty"`
}

type ReportGroupTotalsSummary

type ReportGroupTotalsSummary struct {
	Count       int               `json:"count"`
	Duration    EntryDurationView `json:"duration"`
	Financials  EntryFinancials   `json:"financials"`
	ByGroupType map[string]int    `json:"by_group_type,omitempty"`
}

type ReportRateBreakdownView

type ReportRateBreakdownView struct {
	Rate         *MoneyView     `json:"rate,omitempty"`
	Amount       *MoneyView     `json:"amount,omitempty"`
	EarnedAmount *MoneyView     `json:"earnedAmount,omitempty"`
	EarnedRate   *MoneyView     `json:"earnedRate,omitempty"`
	CostAmount   *MoneyView     `json:"costAmount,omitempty"`
	CostRate     *MoneyView     `json:"costRate,omitempty"`
	Currency     string         `json:"currency,omitempty"`
	Raw          map[string]any `json:"raw,omitempty"`
}

type ReportRollupView

type ReportRollupView struct {
	Group              string                `json:"group,omitempty"`
	Level              int                   `json:"level,omitempty"`
	ID                 string                `json:"id,omitempty"`
	Name               string                `json:"name,omitempty"`
	Duration           EntryDurationView     `json:"duration"`
	Entries            int                   `json:"entries,omitempty"`
	Financials         EntryFinancials       `json:"financials"`
	MoneyByCurrency    []MoneyByCurrencyView `json:"money_by_currency,omitempty"`
	WeeklyDayBreakdown []WeeklyDayTotalView  `json:"weekly_day_breakdown,omitempty"`
	Children           []ReportRollupView    `json:"children,omitempty"`
}

type ReportTotalsSummary

type ReportTotalsSummary struct {
	Rows              int                   `json:"rows"`
	EntriesCount      int                   `json:"entries_count,omitempty"`
	TotalTime         *EntryDurationView    `json:"total_time,omitempty"`
	TotalBillableTime *EntryDurationView    `json:"total_billable_time,omitempty"`
	Financials        EntryFinancials       `json:"financials"`
	MoneyByCurrency   []MoneyByCurrencyView `json:"money_by_currency,omitempty"`
}

type ResultEnvelope

type ResultEnvelope struct {
	OK     bool           `json:"ok"`
	Action string         `json:"action"`
	Data   any            `json:"data,omitempty"`
	Meta   map[string]any `json:"meta,omitempty"`
}

ResultEnvelope is the canonical shape every tool handler returns. OK is the boolean success flag, Action mirrors the tool name for client-side dispatch, Data carries the typed payload (struct or map) and Meta is reserved for cross-cutting metadata (pagination cursors, fingerprint hashes, etc.). Wire-locked by the per-tool outputSchemas in output_schemas.go; mutate this struct and every schemaFor[T] surface has to be reviewed for drift.

type Service

type Service struct {
	Client          *clockify.Client
	WorkspaceID     string
	DefaultTimezone *time.Location // from CLOCKIFY_TIMEZONE; nil falls back to time.Now().Location() for flexible date/time inputs.
	// WebhookValidateDNS, when true, makes CreateWebhook/UpdateWebhook
	// resolve the webhook host via the system resolver and reject any
	// reply that contains a private/reserved IP. Config defaults this
	// on for every profile so a hostname pointing at 169.254.169.254
	// (cloud-metadata) or 10.0.0.x cannot turn the Clockify webhook
	// delivery into an SSRF probe. Operators can explicitly opt out
	// for trusted air-gapped tests.
	WebhookValidateDNS bool
	// WebhookHostResolver overrides the LookupIPAddr call for tests.
	// nil = use net.DefaultResolver.
	WebhookHostResolver func(context.Context, string) ([]netip.Addr, error)
	// WebhookAllowedDomains is an optional escape-hatch list of webhook
	// hostnames that bypass the WebhookValidateDNS private-IP check.
	// Each entry is matched against the parsed URL's host (lowercased)
	// either by exact equality (`webhook.example.com`) or by suffix
	// when the entry begins with a dot (`.example.com` matches
	// `webhook.example.com` and `api.example.com` but NOT
	// `attacker.example.com.evil.com`). Empty list = no bypass; the
	// DNS check applies to every host.
	WebhookAllowedDomains []string
	// EnableRawWrites allows the raw API fallback to use mutating HTTP
	// methods. Raw GET remains available either way.
	EnableRawWrites bool
	// RawWriteDocumentedOnly restricts raw mutating methods to routes present
	// in the generated OpenAPI allowlist. Raw GET remains unaffected.
	RawWriteDocumentedOnly bool
	// Toolset selects the startup registry surface. Empty/all exposes the
	// full owner workbench; smaller values are filtered by RegistryForToolset.
	Toolset string
	// Notifier delivers server→client notifications (progress, resource updates,
	// etc.) emitted by tool handlers. nil = drop silently.
	Notifier mcp.Notifier
	// EmitResourceUpdate publishes notifications/resources/updated for a URI
	// with an optional delta envelope. Wired to Server.NotifyResourceUpdated
	// so the subscription gate lives in the protocol core rather than in
	// every mutation handler. nil = drop silently.
	EmitResourceUpdate func(uri string, delta mcp.ResourceUpdateDelta)
	// EmitResourceListChanged publishes notifications/resources/list_changed
	// when the set of available resources changes (e.g. a new demo-run
	// resource appears). nil disables the notification.
	EmitResourceListChanged func()
	// SubscriptionGate reports whether any client is currently subscribed
	// to a URI. When wired (Server.HasResourceSubscription),
	// emitResourceUpdate short-circuits before the ReadResource round-trip
	// so unsubscribed mutations don't pay for a redundant fetch.
	SubscriptionGate func(uri string) bool
	// EntryFinancialReports forces entry financial enrichment to call the
	// reports host even when the client is pointed at a non-canonical base URL.
	// Production Clockify calls auto-enable this path; tests and local proxies
	// opt in explicitly so unrelated fake handlers do not receive surprise
	// reports-api requests.
	EntryFinancialReports bool
	// contains filtered or unexported fields
}

func New

func New(client *clockify.Client, workspaceID string) *Service

func (*Service) AddUserToGroup

func (s *Service) AddUserToGroup(ctx context.Context, args map[string]any) (ResultEnvelope, error)

AddUserToGroup adds a user to a user group.

func (*Service) ArchiveProjects

func (s *Service) ArchiveProjects(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) AssignProjectMemberships

func (s *Service) AssignProjectMemberships(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) AssignmentReport

func (s *Service) AssignmentReport(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) AttendanceReport

func (s *Service) AttendanceReport(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) AuditLogsSearch

func (s *Service) AuditLogsSearch(ctx context.Context, args map[string]any) (ResultEnvelope, error)

AuditLogsSearch backs clockify_audit_logs_search. It posts an AuditLogGetRequestV1 filter to the dedicated Clockify audit-log host. The live API returns a bare JSON array of audit-log entries, not the PageableV1ListAuditLogDtoV1 envelope the OpenAPI document describes; a live probe against the sacrificial workspace confirmed the bare-array shape.

func (*Service) ClientsCreate

func (s *Service) ClientsCreate(ctx context.Context, args map[string]any) (any, error)

func (*Service) ClientsList

func (s *Service) ClientsList(ctx context.Context, args map[string]any) (any, error)

func (*Service) ClockifyCreateWorkPackage

func (s *Service) ClockifyCreateWorkPackage(ctx context.Context, args map[string]any) (any, error)

func (*Service) ClockifyDemoCleanup

func (s *Service) ClockifyDemoCleanup(ctx context.Context, args map[string]any) (any, error)

func (*Service) ClockifyDemoSeed

func (s *Service) ClockifyDemoSeed(ctx context.Context, args map[string]any) (any, error)

func (*Service) ClockifyFixEntry

func (s *Service) ClockifyFixEntry(ctx context.Context, args map[string]any) (any, error)

func (*Service) ClockifyInvoiceClientWork

func (s *Service) ClockifyInvoiceClientWork(ctx context.Context, args map[string]any) (any, error)

func (*Service) ClockifyLogWork

func (s *Service) ClockifyLogWork(ctx context.Context, args map[string]any) (any, error)

func (*Service) ClockifyRecordExpense

func (s *Service) ClockifyRecordExpense(ctx context.Context, args map[string]any) (any, error)

func (*Service) ClockifyRequestTimeOff

func (s *Service) ClockifyRequestTimeOff(ctx context.Context, args map[string]any) (any, error)

func (*Service) ClockifyReviewDay

func (s *Service) ClockifyReviewDay(ctx context.Context, args map[string]any) (any, error)

func (*Service) ClockifyReviewWeek

func (s *Service) ClockifyReviewWeek(ctx context.Context, args map[string]any) (any, error)

func (*Service) ClockifyScheduleWork

func (s *Service) ClockifyScheduleWork(ctx context.Context, args map[string]any) (any, error)

func (*Service) ClockifySetupWebhook

func (s *Service) ClockifySetupWebhook(ctx context.Context, args map[string]any) (any, error)

func (*Service) ClockifyStartWork

func (s *Service) ClockifyStartWork(ctx context.Context, args map[string]any) (any, error)

func (*Service) ClockifyStatus

func (s *Service) ClockifyStatus(ctx context.Context, _ map[string]any) (any, error)

func (*Service) ClockifyStopWork

func (s *Service) ClockifyStopWork(ctx context.Context, args map[string]any) (any, error)

func (*Service) ClockifySwitchWork

func (s *Service) ClockifySwitchWork(ctx context.Context, args map[string]any) (any, error)

func (*Service) ClockifyToolsGuide

func (s *Service) ClockifyToolsGuide(_ context.Context, _ map[string]any) (any, error)

func (*Service) CreateCustomField

func (s *Service) CreateCustomField(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) CreateHoliday

func (s *Service) CreateHoliday(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) CreateProjectFromTemplate

func (s *Service) CreateProjectFromTemplate(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) CreateProjectTemplate

func (s *Service) CreateProjectTemplate(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) CreateTag

func (s *Service) CreateTag(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) CreateUserGroup

func (s *Service) CreateUserGroup(ctx context.Context, args map[string]any) (ResultEnvelope, error)

CreateUserGroup creates a new user group.

func (*Service) CreateUserGroupAdmin

func (s *Service) CreateUserGroupAdmin(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) CreateWebhook

func (s *Service) CreateWebhook(ctx context.Context, args map[string]any) (ResultEnvelope, error)

CreateWebhook creates a new webhook with URL validation.

func (*Service) CurrentUser

func (s *Service) CurrentUser(ctx context.Context) (ResultEnvelope, error)

func (*Service) DeactivateUser

func (s *Service) DeactivateUser(ctx context.Context, args map[string]any) (ResultEnvelope, error)

DeactivateUser deactivates a user. Supports dry-run (confirm pattern).

func (*Service) DeleteClient

func (s *Service) DeleteClient(ctx context.Context, args map[string]any) (ResultEnvelope, error)

DeleteClient archives the client if it is still active, then deletes it. Clockify rejects DELETE on active clients (the active rule is the same as for projects), and the PUT archive validator additionally requires the existing name in the body. The implementation mirrors the rawArchiveAndDeleteClient cleanup helper in tests/.

func (*Service) DeleteCustomField

func (s *Service) DeleteCustomField(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) DeleteEntry

func (s *Service) DeleteEntry(ctx context.Context, args map[string]any) (ResultEnvelope, error)

DeleteEntry deletes a time entry by ID.

func (*Service) DeleteHoliday

func (s *Service) DeleteHoliday(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) DeleteProject

func (s *Service) DeleteProject(ctx context.Context, args map[string]any) (ResultEnvelope, error)

DeleteProject archives the project if still active, then deletes it. Clockify rejects DELETE on active projects (the archive validator additionally requires the existing name in the body). Mirrors clients.DeleteClient's archive-first pattern; both resources share the same upstream constraint.

func (*Service) DeleteTag

func (s *Service) DeleteTag(ctx context.Context, args map[string]any) (ResultEnvelope, error)

DeleteTag deletes a tag by ID or exact name. Clockify's DELETE /workspaces/{ws}/tags/{id} works directly on active tags — no archive step is required (unlike clients). Supports dry_run.

func (*Service) DeleteTask

func (s *Service) DeleteTask(ctx context.Context, args map[string]any) (ResultEnvelope, error)

DeleteTask deletes a task by project + task reference (ID or name). Clockify requires tasks to be DONE before DELETE, so active tasks are first updated with the existing full-replacement shape plus status=DONE.

func (*Service) DeleteUserGroup

func (s *Service) DeleteUserGroup(ctx context.Context, args map[string]any) (ResultEnvelope, error)

DeleteUserGroup deletes a user group. Supports dry-run (minimal fallback).

func (*Service) DeleteUserGroupAdmin

func (s *Service) DeleteUserGroupAdmin(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) DeleteWebhook

func (s *Service) DeleteWebhook(ctx context.Context, args map[string]any) (ResultEnvelope, error)

DeleteWebhook deletes a webhook. Supports dry-run (preview via GET).

func (*Service) DetailedReport

func (s *Service) DetailedReport(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) EmitProgress

func (s *Service) EmitProgress(ctx context.Context, progress, total float64, message string)

EmitProgress publishes a notifications/progress if a progressToken was supplied with the current tools/call and the Service has a Notifier wired. No-op otherwise. total < 0 signals an indeterminate total.

func (*Service) EntityChangesList

func (s *Service) EntityChangesList(ctx context.Context, args map[string]any) (ResultEnvelope, error)

EntityChangesList backs clockify_entity_changes_list. It reads the experimental entities/{created,updated,deleted} feed on the primary host. The live API returns a bare array of change documents; the OpenAPI envelope shape was never observed in practice, so the handler decodes a plain array and surfaces a recovery envelope if Clockify ever changes it.

func (*Service) EntriesCreate

func (s *Service) EntriesCreate(ctx context.Context, args map[string]any) (any, error)

func (*Service) EntriesList

func (s *Service) EntriesList(ctx context.Context, args map[string]any) (any, error)

func (*Service) EntriesMarkInvoiced

func (s *Service) EntriesMarkInvoiced(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) EntriesRunning

func (s *Service) EntriesRunning(ctx context.Context, _ map[string]any) (any, error)

func (*Service) EntriesTimerStart

func (s *Service) EntriesTimerStart(ctx context.Context, args map[string]any) (any, error)

func (*Service) EntriesTimerStatus

func (s *Service) EntriesTimerStatus(ctx context.Context, _ map[string]any) (any, error)

func (*Service) EntriesTimerStop

func (s *Service) EntriesTimerStop(ctx context.Context, args map[string]any) (any, error)

func (*Service) EntriesTimerSwitch

func (s *Service) EntriesTimerSwitch(ctx context.Context, args map[string]any) (any, error)

func (*Service) ExpenseReport

func (s *Service) ExpenseReport(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) FindAndUpdateEntry

func (s *Service) FindAndUpdateEntry(ctx context.Context, args map[string]any) (any, error)

func (*Service) FirstSliceRegistry

func (s *Service) FirstSliceRegistry() []mcp.ToolDescriptor

func (*Service) FullAccessRegistry

func (s *Service) FullAccessRegistry() []mcp.ToolDescriptor

FullAccessRegistry is the one-user product registry: every supported tool is visible from startup, with workflows first and raw API fallback last.

func (*Service) GetClientWithArgs

func (s *Service) GetClientWithArgs(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) GetCustomField

func (s *Service) GetCustomField(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) GetEntry

func (s *Service) GetEntry(ctx context.Context, args map[string]any) (ResultEnvelope, error)

GetEntry retrieves a single time entry by ID.

func (*Service) GetHoliday

func (s *Service) GetHoliday(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) GetMemberProfile

func (s *Service) GetMemberProfile(ctx context.Context, args map[string]any) (ResultEnvelope, error)

GetMemberProfile returns a workspace-scoped member profile for a user.

func (*Service) GetProject

func (s *Service) GetProject(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) GetProjectTemplate

func (s *Service) GetProjectTemplate(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) GetTag

func (s *Service) GetTag(ctx context.Context, args map[string]any) (ResultEnvelope, error)

GetTag fetches a single tag by ID or exact name.

func (*Service) GetTask

func (s *Service) GetTask(ctx context.Context, args map[string]any) (ResultEnvelope, error)

GetTask fetches a single task by ID or exact name within a project. project (name or ID) and task (ID or name) are both required.

func (*Service) GetUserGroup

func (s *Service) GetUserGroup(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) GetWebhook

func (s *Service) GetWebhook(ctx context.Context, args map[string]any) (ResultEnvelope, error)

GetWebhook retrieves a single webhook by ID.

func (*Service) GetWorkspace

func (s *Service) GetWorkspace(ctx context.Context) (ResultEnvelope, error)

func (*Service) InviteUser

func (s *Service) InviteUser(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) InvoicesInfo

func (s *Service) InvoicesInfo(ctx context.Context, args map[string]any) (ResultEnvelope, error)

InvoicesInfo backs clockify_invoices_info: a bulk, paged invoice query via POST /invoices/info. Unlike clockify_invoices_list it returns the workspace total (filtered by the status filter) so a caller can compute has_more; unlike clockify_invoice_report it returns raw invoice rows, not money aggregates.

func (*Service) ListCustomFields

func (s *Service) ListCustomFields(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) ListEntries

func (s *Service) ListEntries(ctx context.Context, args map[string]any) (ResultEnvelope, error)

ListEntries returns recent time entries with optional filtering by date range, project, and pagination.

func (*Service) ListHolidays

func (s *Service) ListHolidays(ctx context.Context) (ResultEnvelope, error)

func (*Service) ListHolidaysInPeriod

func (s *Service) ListHolidaysInPeriod(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) ListProjectMemberships

func (s *Service) ListProjectMemberships(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) ListProjectTemplates

func (s *Service) ListProjectTemplates(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) ListResourceTemplates

func (s *Service) ListResourceTemplates(_ context.Context) ([]mcp.ResourceTemplate, error)

ListResourceTemplates returns the parametric URI templates clients can dereference by substituting concrete IDs.

func (*Service) ListResources

func (s *Service) ListResources(ctx context.Context) ([]mcp.Resource, error)

ListResources returns a small, immediately-navigable set of concrete resources pinned to the Service's current workspace. Parametric resources (per-id entry, project, weekly report) live in ListResourceTemplates.

func (*Service) ListTags

func (s *Service) ListTags(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) ListUserGroups

func (s *Service) ListUserGroups(ctx context.Context, args map[string]any) (ResultEnvelope, error)

ListUserGroups returns user groups for the workspace.

func (*Service) ListUserGroupsAdmin

func (s *Service) ListUserGroupsAdmin(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) ListUserManagers

func (s *Service) ListUserManagers(ctx context.Context, args map[string]any) (ResultEnvelope, error)

ListUserManagers returns managers assigned to a workspace user.

func (*Service) ListUsers

func (s *Service) ListUsers(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) ListWebhookEvents

func (s *Service) ListWebhookEvents(ctx context.Context, _ map[string]any) (ResultEnvelope, error)

ListWebhookEvents returns the static enum of webhook event types the Clockify webhooks API accepts. The upstream exposes no listing endpoint — see findings/webhooks.md (#15).

func (*Service) ListWebhookLogs

func (s *Service) ListWebhookLogs(ctx context.Context, args map[string]any) (ResultEnvelope, error)

ListWebhookLogs returns delivery attempts for a webhook via the documented POST logs search route.

func (*Service) ListWebhooks

func (s *Service) ListWebhooks(ctx context.Context, args map[string]any) (ResultEnvelope, error)

ListWebhooks returns webhooks for the workspace.

func (*Service) MoneyReport

func (s *Service) MoneyReport(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) ProjectsCreate

func (s *Service) ProjectsCreate(ctx context.Context, args map[string]any) (any, error)

func (*Service) ProjectsList

func (s *Service) ProjectsList(ctx context.Context, args map[string]any) (any, error)

func (*Service) QuickReport

func (s *Service) QuickReport(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) RawAPIGet

func (s *Service) RawAPIGet(ctx context.Context, args map[string]any) (any, error)

func (*Service) RawAPIRequest

func (s *Service) RawAPIRequest(ctx context.Context, args map[string]any) (any, error)

func (*Service) ReadResource

func (s *Service) ReadResource(ctx context.Context, uri string) ([]mcp.ResourceContents, error)

ReadResource parses a clockify:// URI and fetches the underlying entity from Clockify, returning it as a single JSON-encoded ResourceContents entry. Unknown or malformed URIs return a -32602-equivalent error.

func (*Service) RegistryForToolset

func (s *Service) RegistryForToolset(toolset string) []mcp.ToolDescriptor

RegistryForToolset returns the one-user startup registry for a narrower owner-mode surface. The default "all" path is intentionally identical to FullAccessRegistry so the canonical 156-tool product contract stays intact.

func (*Service) RemoveUserFromGroup

func (s *Service) RemoveUserFromGroup(ctx context.Context, args map[string]any) (ResultEnvelope, error)

RemoveUserFromGroup removes a user from a user group. Supports dry-run (minimal fallback).

func (*Service) ResolveName

func (s *Service) ResolveName(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) ResolveWorkspaceID

func (s *Service) ResolveWorkspaceID(ctx context.Context) (string, error)

func (*Service) SchedulingPublish

func (s *Service) SchedulingPublish(ctx context.Context, args map[string]any) (ResultEnvelope, error)

SchedulingPublish backs clockify_scheduling_publish. Scheduling assignment create/update produce drafts; this is the separate step that publishes every draft assignment in the start..end window. The Clockify endpoint returns no body, so the receipt is synthesised from the request (Axiom 8).

func (*Service) SetCustomFieldValue

func (s *Service) SetCustomFieldValue(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) SetProjectMemberships

func (s *Service) SetProjectMemberships(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) StartTimer

func (s *Service) StartTimer(ctx context.Context, projectID, projectRef, description string) (ResultEnvelope, error)

func (*Service) StartTimerArgs

func (s *Service) StartTimerArgs(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) StopTimer

func (s *Service) StopTimer(ctx context.Context, args map[string]any) (any, error)

func (*Service) SummaryReport

func (s *Service) SummaryReport(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) SwitchProject

func (s *Service) SwitchProject(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) TagsCreate

func (s *Service) TagsCreate(ctx context.Context, args map[string]any) (any, error)

func (*Service) TagsList

func (s *Service) TagsList(ctx context.Context, args map[string]any) (any, error)

func (*Service) TasksCreate

func (s *Service) TasksCreate(ctx context.Context, args map[string]any) (any, error)

func (*Service) TasksList

func (s *Service) TasksList(ctx context.Context, args map[string]any) (any, error)

func (*Service) TestWebhook

func (s *Service) TestWebhook(ctx context.Context, args map[string]any) (ResultEnvelope, error)

TestWebhook reports the absence of a Clockify webhook test-send endpoint.

func (*Service) TimerStatus

func (s *Service) TimerStatus(ctx context.Context) (ResultEnvelope, error)

func (*Service) TimesheetReview

func (s *Service) TimesheetReview(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) UnbilledForClient

func (s *Service) UnbilledForClient(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) UpdateClient

func (s *Service) UpdateClient(ctx context.Context, args map[string]any) (ResultEnvelope, error)

UpdateClient performs a fetch-then-merge update of a client. Clockify's PUT /clients/{id} is a full replacement (omitted fields get nulled server-side), so we GET the existing client, layer caller-provided changes over the fetched object, and PUT the complete merged shape back. Caller-supplied empty strings are treated as "do not change" (use the dedicated `archived` boolean flag to flip archival state).

func (*Service) UpdateCustomField

func (s *Service) UpdateCustomField(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) UpdateEntry

func (s *Service) UpdateEntry(ctx context.Context, args map[string]any) (ResultEnvelope, error)

UpdateEntry performs a fetch-then-update of a time entry, merging caller fields over the existing values.

func (*Service) UpdateHoliday

func (s *Service) UpdateHoliday(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) UpdateMemberProfile

func (s *Service) UpdateMemberProfile(ctx context.Context, args map[string]any) (ResultEnvelope, error)

UpdateMemberProfile updates live-supported workspace member profile fields.

func (*Service) UpdateProject

func (s *Service) UpdateProject(ctx context.Context, args map[string]any) (ResultEnvelope, error)

UpdateProject performs a fetch-then-merge update of a project. Clockify's PUT /projects/{id} replaces the full record (omitted optional fields are nulled), so we GET the existing project, layer caller-provided changes over it, and PUT the merged shape back. Caller-supplied empty strings are treated as "do not change"; flip archival state through the dedicated `archived` boolean instead.

func (*Service) UpdateProjectEstimate

func (s *Service) UpdateProjectEstimate(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) UpdateProjectMemberships

func (s *Service) UpdateProjectMemberships(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) UpdateProjectTemplate

func (s *Service) UpdateProjectTemplate(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) UpdateProjectUserRate

func (s *Service) UpdateProjectUserRate(ctx context.Context, args map[string]any, endpoint string) (ResultEnvelope, error)

func (*Service) UpdateTag

func (s *Service) UpdateTag(ctx context.Context, args map[string]any) (ResultEnvelope, error)

UpdateTag performs a fetch-then-merge update of a tag. Clockify's PUT /workspaces/{ws}/tags/{id} is a full replacement; we GET the existing tag, layer caller changes on top, then PUT the merged shape back. The archived boolean can be toggled explicitly.

func (*Service) UpdateTask

func (s *Service) UpdateTask(ctx context.Context, args map[string]any) (ResultEnvelope, error)

UpdateTask performs a fetch-then-merge update of a task. Clockify's PUT /projects/{pid}/tasks/{tid} is a full replacement; we GET the existing task, layer caller changes on top, then PUT the merged shape back. Empty-string caller args are treated as "no change".

func (*Service) UpdateTaskRate

func (s *Service) UpdateTaskRate(ctx context.Context, args map[string]any, endpoint string) (ResultEnvelope, error)

func (*Service) UpdateUserGroup

func (s *Service) UpdateUserGroup(ctx context.Context, args map[string]any) (ResultEnvelope, error)

UpdateUserGroup updates a user group's name.

func (*Service) UpdateUserGroupAdmin

func (s *Service) UpdateUserGroupAdmin(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) UpdateUserRole

func (s *Service) UpdateUserRole(ctx context.Context, args map[string]any) (ResultEnvelope, error)

UpdateUserRole updates a user's workspace role.

func (*Service) UpdateWebhook

func (s *Service) UpdateWebhook(ctx context.Context, args map[string]any) (ResultEnvelope, error)

UpdateWebhook updates an existing webhook.

func (*Service) UsersInvite

func (s *Service) UsersInvite(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) WeeklySummary

func (s *Service) WeeklySummary(ctx context.Context, args map[string]any) (ResultEnvelope, error)

type SummaryTotals

type SummaryTotals struct {
	Entries        int     `json:"entries"`
	RunningEntries int     `json:"runningEntries"`
	TotalSeconds   int64   `json:"totalSeconds"`
	TotalHours     float64 `json:"totalHours"`
}

SummaryTotals aggregates entry counts and tracked time across the containing DateRange. RunningEntries is the subset of Entries that are still in progress (no End yet); TotalSeconds is the canonical duration, TotalHours is the convenience float derived from it.

type TaskRateView

type TaskRateView struct {
	TaskID      string         `json:"task_id,omitempty"`
	TaskName    string         `json:"task_name,omitempty"`
	HourlyRate  *clockify.Rate `json:"hourly_rate,omitempty"`
	CostRate    *clockify.Rate `json:"cost_rate,omitempty"`
	HourlyMoney *MoneyView     `json:"hourly_money,omitempty"`
	CostMoney   *MoneyView     `json:"cost_money,omitempty"`
}

type TaskView

type TaskView struct {
	ID                     string                 `json:"id"`
	Name                   string                 `json:"name"`
	ProjectID              string                 `json:"projectId"`
	AssigneeID             string                 `json:"assigneeId,omitempty"`
	AssigneeIDs            []string               `json:"assigneeIds,omitempty"`
	Billable               bool                   `json:"billable"`
	BudgetEstimate         int64                  `json:"budgetEstimate,omitempty"`
	CostRate               *clockify.Rate         `json:"costRate,omitempty"`
	Duration               string                 `json:"duration,omitempty"`
	Estimate               string                 `json:"estimate,omitempty"`
	HourlyRate             *clockify.Rate         `json:"hourlyRate,omitempty"`
	Status                 string                 `json:"status,omitempty"`
	UserGroupIDs           []string               `json:"userGroupIds,omitempty"`
	CustomFieldsNormalized []CustomFieldValueView `json:"custom_fields_normalized,omitempty"`

	Rates            TaskRateView         `json:"rates"`
	Financials       ProjectFinancials    `json:"financials"`
	Estimates        ProjectEstimateView  `json:"estimates"`
	EstimateProgress EstimateProgressView `json:"estimate_progress"`
}

type TimeEntryRef

type TimeEntryRef struct {
	ID          string `json:"id"`
	Description string `json:"description,omitempty"`
	ProjectID   string `json:"projectId,omitempty"`
	ProjectName string `json:"projectName,omitempty"`
	Start       string `json:"start,omitempty"`
	End         string `json:"end,omitempty"`
}

type TimeEntryUpdatePreview

type TimeEntryUpdatePreview struct {
	Description     string   `json:"description"`
	ProjectID       string   `json:"project_id,omitempty"`
	TaskID          string   `json:"task_id,omitempty"`
	TagIDs          []string `json:"tag_ids,omitempty"`
	Start           string   `json:"start,omitempty"`
	End             string   `json:"end,omitempty"`
	Billable        bool     `json:"billable"`
	BillableState   string   `json:"billable_state,omitempty"`
	BillablePresent bool     `json:"billable_present,omitempty"`
}

TimeEntryUpdatePreview is the projected "current" shape of a time entry shown alongside a proposed-change diff during a dry-run update.

type TimeOffBalanceView

type TimeOffBalanceView map[string]any

type TimeOffPolicyView

type TimeOffPolicyView map[string]any

type TimeOffRequestView

type TimeOffRequestView map[string]any

type TimesheetIssue

type TimesheetIssue struct {
	Type            string   `json:"type"`
	Severity        string   `json:"severity"`
	Message         string   `json:"message"`
	EntryID         string   `json:"entryId,omitempty"`
	RelatedEntryIDs []string `json:"relatedEntryIds,omitempty"`
	Start           string   `json:"start,omitempty"`
	End             string   `json:"end,omitempty"`
}

type TimesheetReviewData

type TimesheetReviewData struct {
	Range            DateRange        `json:"range"`
	Totals           SummaryTotals    `json:"totals"`
	ByDay            []DaySummary     `json:"byDay"`
	ByProject        []ProjectSummary `json:"byProject"`
	Issues           []TimesheetIssue `json:"issues"`
	SuggestedActions []ToolSuggestion `json:"suggestedActions"`
	Entries          []EntryView      `json:"entries,omitempty"`
}

type ToolError

type ToolError struct {
	OK       bool         `json:"ok"`
	Action   string       `json:"action"`
	Error    ErrorInfo    `json:"error"`
	Recovery RecoveryHint `json:"recovery"`
	Warnings []Warning    `json:"warnings,omitempty"`
}

type ToolResult

type ToolResult struct {
	OK       bool              `json:"ok"`
	Action   string            `json:"action"`
	Entity   string            `json:"entity,omitempty"`
	IDs      map[string]string `json:"ids,omitempty"`
	Data     any               `json:"data,omitempty"`
	Meta     map[string]any    `json:"meta,omitempty"`
	Changed  ChangeSet         `json:"changed"`
	Warnings []Warning         `json:"warnings,omitempty"`
	Next     []NextAction      `json:"next,omitempty"`
}

type ToolSuggestion

type ToolSuggestion struct {
	Tool        string         `json:"tool"`
	Reason      string         `json:"reason"`
	Arguments   map[string]any `json:"arguments,omitempty"`
	MissingArgs []string       `json:"missingArgs,omitempty"`
}

type UnbilledForClientView

type UnbilledForClientView struct {
	ClientID         string              `json:"client_id,omitempty"`
	Client           string              `json:"client,omitempty"`
	Range            FinancialRangeView  `json:"range"`
	Entries          []ReportEntryView   `json:"entries,omitempty"`
	EntrySummary     ReportEntrySummary  `json:"entry_summary"`
	Totals           ReportTotalsSummary `json:"totals_summary"`
	Financials       EntryFinancials     `json:"financials"`
	SuggestedActions []ToolSuggestion    `json:"suggestedActions,omitempty"`
	Warnings         []string            `json:"warnings,omitempty"`
	Raw              map[string]any      `json:"raw,omitempty"`
}

type UserFeatureFlags

type UserFeatureFlags struct {
	Scheduling bool `json:"scheduling,omitempty"`
	Approval   bool `json:"approval,omitempty"`
	PTO        bool `json:"pto,omitempty"`
}

type UserView

type UserView struct {
	ID                     string                 `json:"id"`
	Name                   string                 `json:"name"`
	Email                  string                 `json:"email"`
	ActiveWorkspace        string                 `json:"activeWorkspace,omitempty"`
	CustomFields           any                    `json:"customFields,omitempty"`
	CustomFieldsNormalized []CustomFieldValueView `json:"custom_fields_normalized,omitempty"`
	DefaultWorkspace       string                 `json:"defaultWorkspace,omitempty"`
	Memberships            any                    `json:"memberships,omitempty"`
	ProfilePicture         string                 `json:"profilePicture,omitempty"`
	Settings               any                    `json:"settings,omitempty"`
	Status                 string                 `json:"status,omitempty"`
	ReportDefaults         ReportDefaults         `json:"report_defaults"`
	FeatureFlags           UserFeatureFlags       `json:"feature_flags"`
}

UserView preserves the upstream user fields while adding compact settings blocks that agents can use for report defaults and feature-aware wording.

type ValidationProblem

type ValidationProblem struct {
	Code        string   `json:"code,omitempty"`
	Field       string   `json:"field,omitempty"`
	Message     string   `json:"message"`
	Remediation string   `json:"remediation,omitempty"`
	Refs        []string `json:"refs,omitempty"`
}

type ValidationView

type ValidationView struct {
	Status         string              `json:"status"`
	OK             *bool               `json:"ok,omitempty"`
	Errors         []ValidationProblem `json:"errors,omitempty"`
	Warnings       []ValidationProblem `json:"warnings,omitempty"`
	PreviewQuality string              `json:"preview_quality,omitempty"`
}

type Warning

type Warning struct {
	Code    string `json:"code,omitempty"`
	Message string `json:"message"`
}

type WebhookLogView

type WebhookLogView map[string]any

type WeeklyDayTotalView

type WeeklyDayTotalView struct {
	Date            string                `json:"date,omitempty"`
	IsFuture        bool                  `json:"is_future,omitempty"`
	Duration        EntryDurationView     `json:"duration"`
	Financials      EntryFinancials       `json:"financials"`
	MoneyByCurrency []MoneyByCurrencyView `json:"money_by_currency,omitempty"`
}

type WeeklySummaryData

type WeeklySummaryData struct {
	Range            DateRange            `json:"range"`
	Totals           SummaryTotals        `json:"totals"`
	ByDay            []DaySummary         `json:"byDay"`
	ByProject        []ProjectSummary     `json:"byProject"`
	SuggestedActions []ToolSuggestion     `json:"suggestedActions"`
	Entries          []clockify.TimeEntry `json:"entries,omitempty"`
	UnassignedKey    string               `json:"unassignedKey,omitempty"`
}

WeeklySummaryData is the structured payload for clockify_weekly_ summary: a date range, total counts, per-day and per-project rollups, suggested follow-up actions for the agent, and (optionally) the raw entries so callers can drill into specific records without a second round-trip.

type WorkspaceSettings

type WorkspaceSettings struct {
	Currencies                any      `json:"currencies,omitempty"`
	FeaturePlan               string   `json:"feature_plan,omitempty"`
	SubscriptionLabel         string   `json:"subscription_label,omitempty"`
	PlanCohort                string   `json:"plan_cohort,omitempty"`
	DurationFormat            string   `json:"duration_format,omitempty"`
	CurrencyFormat            any      `json:"currency_format,omitempty"`
	NumberFormat              any      `json:"number_format,omitempty"`
	ProjectLabel              string   `json:"project_label,omitempty"`
	TaskLabel                 string   `json:"task_label,omitempty"`
	WorkingDays               []string `json:"working_days,omitempty"`
	WorkingDayPattern         string   `json:"working_day_pattern,omitempty"`
	WeekendIncluded           bool     `json:"weekend_included,omitempty"`
	WorkingDayCount           int      `json:"working_day_count,omitempty"`
	LockPolicy                any      `json:"lock_policy,omitempty"`
	Rounding                  any      `json:"rounding,omitempty"`
	EntityCreationPermissions any      `json:"entity_creation_permissions,omitempty"`
	HasHourlyRate             bool     `json:"has_hourly_rate,omitempty"`
	HasCostRate               bool     `json:"has_cost_rate,omitempty"`
	MembershipsCount          int      `json:"memberships_count,omitempty"`
	Source                    string   `json:"source,omitempty"`
}

type WorkspaceView

type WorkspaceView struct {
	ID                      string            `json:"id"`
	Name                    string            `json:"name"`
	CakeOrganizationID      string            `json:"cakeOrganizationId,omitempty"`
	CostRate                *clockify.Rate    `json:"costRate,omitempty"`
	Currencies              any               `json:"currencies,omitempty"`
	FeatureSubscriptionType string            `json:"featureSubscriptionType,omitempty"`
	Features                []string          `json:"features,omitempty"`
	FeaturesHuman           []FeatureLabel    `json:"features_human,omitempty"`
	SubscriptionLabel       string            `json:"subscription_label,omitempty"`
	PlanCohort              string            `json:"plan_cohort,omitempty"`
	HourlyRate              *clockify.Rate    `json:"hourlyRate,omitempty"`
	ImageURL                string            `json:"imageUrl,omitempty"`
	Memberships             any               `json:"memberships,omitempty"`
	Subdomain               any               `json:"subdomain,omitempty"`
	WorkspaceSettings       any               `json:"workspaceSettings,omitempty"`
	SettingsSummary         WorkspaceSettings `json:"settings_summary"`
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL