harvest

package module
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Nov 5, 2025 License: MIT Imports: 12 Imported by: 0

README

Harvest API v2 Go Client

Go Reference Go Report Card

A modern, comprehensive Go client library for the Harvest API v2. This library provides complete coverage of all Harvest API v2 endpoints with a clean, type-safe interface.

Why This Library?

  • Full API v2 Support: Unlike older libraries that only support Harvest API v1 (deprecated), this library is built exclusively for the current Harvest API v2
  • Modern Go: Uses Go 1.25+ generics to reduce code duplication and provide a cleaner API
  • Complete Coverage: Implements all 69+ endpoints from the Harvest API v2
  • Type Safety: Strongly typed request and response models with proper JSON marshaling
  • Production Ready: Automatic rate limiting, context support, and comprehensive error handling

Note: If you're looking for a Harvest API v1 client, see adlio/harvest. However, be aware that Harvest API v1 is deprecated and that library hasn't been updated since 2018.

Features

  • Complete API Coverage: All Harvest API v2 endpoints implemented
  • Type Safety: Strongly typed request and response models
  • Generic CRUD Operations: Leverages Go generics for reduced code duplication
  • Automatic Pagination: Built-in pagination support with iterator pattern
  • Rate Limiting: Automatic rate limit detection and error handling
  • Decimal Precision: Uses shopspring/decimal for accurate financial calculations
  • Context Support: All methods accept context.Context for cancellation
  • Configurable User-Agent: Required by Harvest API for identification

Installation

go get github.com/joefitzgerald/harvest

Requires Go 1.25 or later.

Quick Start

package main

import (
    "context"
    "fmt"
    "log"
    "os"

    "github.com/joefitzgerald/harvest"
)

func main() {
    // Set environment variables:
    // export HARVEST_ACCESS_TOKEN="your-token"
    // export HARVEST_ACCOUNT_ID="your-account-id"

    // Create client with required User-Agent
    client, err := harvest.New("MyApp (contact@example.com)")
    if err != nil {
        log.Fatal(err)
    }

    ctx := context.Background()

    // Get company info
    company, err := client.Company.Get(ctx)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("Company: %s\n", company.Name)

    // List active projects
    projects, err := client.Projects.List(ctx, &harvest.ProjectListOptions{
        ListOptions: harvest.ListOptions{
            Page:    1,
            PerPage: 100,
        },
        IsActive: &[]bool{true}[0],
    })
    if err != nil {
        log.Fatal(err)
    }

    for _, project := range projects.Projects {
        fmt.Printf("Project: %s (Client: %s)\n", project.Name, project.Client.Name)
    }
}

Authentication

The client requires two environment variables:

  • HARVEST_ACCESS_TOKEN: Your personal access token from Harvest
  • HARVEST_ACCOUNT_ID: Your Harvest account ID

To get these:

  1. Log in to Harvest
  2. Go to Developers > Personal Access Tokens
  3. Create a new token
  4. Note your Account ID from the same page

You can also create a client with explicit credentials:

client, err := harvest.NewWithConfig(
    "your-access-token",
    "your-account-id",
    "MyApp (contact@example.com)",
    nil, // optional custom HTTP client
)

User-Agent Requirement

Harvest requires a User-Agent header that includes:

  1. The name of your application
  2. A link to your application or email address

Examples:

  • "MyTimeTracker (https://example.com)"
  • "John's Integration (john@example.com)"

Available Services

Core Resources
  • Company: Get company information
  • Clients: Manage clients and contacts
  • Projects: Manage projects and assignments
  • Users: Manage users and their assignments
  • Tasks: Manage tasks
  • TimeEntries: Track time entries
Financial Resources
  • Invoices: Create and manage invoices
  • Estimates: Create and manage estimates
  • Expenses: Track expenses and expense categories
Reporting
  • Reports: Access various reports
    • Time reports
    • Expense reports
    • Uninvoiced reports
    • Project budget reports
Administration
  • Roles: Manage user roles

Examples

Time Entry Management
// Create time entry via duration
entry, err := client.TimeEntries.CreateViaDuration(ctx, &harvest.TimeEntryCreateViaDurationRequest{
    ProjectID:  12345,
    TaskID:     67890,
    SpentDate:  "2025-01-10",
    Hours:      2.5,
    Notes:      "Working on feature X",
})

// Start a timer
timer, err := client.TimeEntries.CreateViaStartEndTime(ctx, &harvest.TimeEntryCreateViaStartEndTimeRequest{
    ProjectID: 12345,
    TaskID:    67890,
    SpentDate: "2025-01-10",
})

// Stop the timer
stopped, err := client.TimeEntries.Stop(ctx, timer.ID)
Project Management
// Create a project
project, err := client.Projects.Create(ctx, &harvest.ProjectCreateRequest{
    ClientID:   123,
    Name:       "New Website",
    IsBillable: &[]bool{true}[0],
    BillBy:     "project",
    Budget:     50000,
})

// Assign user to project
assignment, err := client.Projects.CreateUserAssignment(ctx, project.ID,
    &harvest.UserAssignmentCreateRequest{
        UserID:           456,
        IsProjectManager: &[]bool{true}[0],
        HourlyRate:       150.00,
    })

// Update project budget
updated, err := client.Projects.Update(ctx, project.ID, &harvest.ProjectUpdateRequest{
    Budget: 75000,
})
Pagination
// Manual pagination
opts := &harvest.ProjectListOptions{
    ListOptions: harvest.ListOptions{
        Page:    1,
        PerPage: 50,
    },
}

for {
    projects, err := client.Projects.List(ctx, opts)
    if err != nil {
        return err
    }

    for _, project := range projects.Projects {
        // Process project
    }

    if !projects.HasNextPage() {
        break
    }
    opts.Page = *projects.NextPage
}
Error Handling
projects, err := client.Projects.List(ctx, nil)
if err != nil {
    switch e := err.(type) {
    case *harvest.RateLimitError:
        fmt.Printf("Rate limit exceeded. Resets at: %s\n", e.Rate.Reset)
        // Wait and retry
    case *harvest.ErrorResponse:
        fmt.Printf("API error: %s\n", e.Message)
    default:
        fmt.Printf("Error: %v\n", err)
    }
}

API Coverage

This library provides complete coverage of the Harvest API v2. All endpoints documented in the official API documentation are implemented.

Implemented Endpoints
Resource Operations
Company Get
Clients List, Get, Create, Update, Delete
Contacts List, Get, Create, Update, Delete
Projects List, Get, Create, Update, Delete
Project User Assignments List, Get, Create, Update, Delete
Project Task Assignments List, Get, Create, Update, Delete
Tasks List, Get, Create, Update, Delete
Users List, Get, Create, Update, Delete, Get Current
User Project Assignments List, Get Current
User Billable Rates List, Get, Create, Update, Delete
User Cost Rates List, Get, Create, Update, Delete
Time Entries List, Get, Create, Update, Delete, Restart, Stop
Invoices List, Get, Create, Update, Delete, Send
Invoice Line Items Create, Update, Delete
Invoice Messages List, Get, Create, Delete
Invoice Payments List, Get, Create, Delete
Estimates List, Get, Create, Update, Delete, Send
Estimate Line Items Create, Update, Delete
Estimate Messages List, Get, Create, Delete
Expenses List, Get, Create, Update, Delete
Expense Categories List, Get, Create, Update, Delete
Roles List, Get, Create, Update, Delete
Reports Time, Expenses, Uninvoiced, Project Budget

Development

Building
# Download dependencies
go mod download

# Build
go build ./...

# Run tests
go test -v ./...

# Lint
golangci-lint run ./...
Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

When adding new endpoints:

  1. Add types to types.go
  2. Add service methods following the existing pattern
  3. Use generics for standard CRUD operations
  4. Ensure proper error handling
  5. Add comprehensive tests

License

MIT License - see LICENSE file for details.

Generated with Claude Code

The initial version of this client library was generated using Claude Code (Opus 4.1).

Support

For issues, questions, or contributions, please use the GitHub issue tracker.

Documentation

Index

Constants

View Source
const (

	// DefaultPerPage is the default number of items to request per page for list operations.
	DefaultPerPage = 2000
)

Variables

This section is empty.

Functions

func CheckResponse

func CheckResponse(r *http.Response) error

CheckResponse checks the API response for errors.

func Create

func Create[T any](ctx context.Context, c *API, path string, body any) (*T, error)

Create performs a POST request to create a new resource.

func Delete

func Delete(ctx context.Context, c *API, path string) error

Delete performs a DELETE request to remove a resource.

func Get

func Get[T any](ctx context.Context, c *API, path string) (*T, error)

Get performs a GET request to retrieve a single resource.

func List

func List[T any](ctx context.Context, c *API, path string, opts *ListOptions) ([]T, error)

List performs a GET request to list all resources across all pages. Supports both page-based and cursor-based pagination.

func Update

func Update[T any](ctx context.Context, c *API, path string, body any) (*T, error)

Update performs a PATCH request to update an existing resource.

Types

type API

type API struct {

	// Service endpoints
	Company     *CompanyService
	Clients     *ClientsService
	Contacts    *ContactsService
	Projects    *ProjectsService
	TimeEntries *TimeEntriesService
	Users       *UsersService
	Tasks       *TasksService
	Invoices    *InvoicesService
	Estimates   *EstimatesService
	Expenses    *ExpensesService
	Reports     *ReportsService
	Roles       *RolesService
	// contains filtered or unexported fields
}

func New

func New(userAgent string) (*API, error)

New creates a new Harvest API client with the given User-Agent. It reads HARVEST_ACCESS_TOKEN and HARVEST_ACCOUNT_ID from environment variables.

func NewWithConfig

func NewWithConfig(accessToken, accountID, userAgent string, httpClient *http.Client) (*API, error)

NewWithConfig creates a new Harvest API client with custom configuration.

func (*API) Do

func (c *API) Do(ctx context.Context, req *http.Request, v any) (*http.Response, error)

Do sends an API request and returns the API response.

func (*API) NewRequest

func (c *API) NewRequest(ctx context.Context, method, urlStr string, body any) (*http.Request, error)

NewRequest creates an API request.

type Client

type Client struct {
	ID        int64     `json:"id"`
	Name      string    `json:"name"`
	IsActive  bool      `json:"is_active"`
	Address   string    `json:"address,omitempty"`
	Currency  string    `json:"currency,omitempty"`
	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updated_at"`
}

Client represents a client in Harvest.

type ClientCreateRequest

type ClientCreateRequest struct {
	Name     string `json:"name"`
	IsActive *bool  `json:"is_active,omitempty"`
	Address  string `json:"address,omitempty"`
	Currency string `json:"currency,omitempty"`
}

ClientCreateRequest represents a request to create a client.

type ClientList

type ClientList struct {
	Clients []Client `json:"clients"`
	Paginated[Client]
}

ClientList represents a list of clients.

type ClientListOptions

type ClientListOptions struct {
	ListOptions
	IsActive     *bool  `url:"is_active,omitempty"`
	UpdatedSince string `url:"updated_since,omitempty"`
}

ClientListOptions specifies optional parameters to the List method.

type ClientUpdateRequest

type ClientUpdateRequest struct {
	Name     string `json:"name,omitempty"`
	IsActive *bool  `json:"is_active,omitempty"`
	Address  string `json:"address,omitempty"`
	Currency string `json:"currency,omitempty"`
}

ClientUpdateRequest represents a request to update a client.

type ClientsService

type ClientsService struct {
	// contains filtered or unexported fields
}

ClientsService handles communication with the client related methods of the Harvest API.

func (*ClientsService) Create

func (s *ClientsService) Create(ctx context.Context, client *ClientCreateRequest) (*Client, error)

Create creates a new client.

func (*ClientsService) Delete

func (s *ClientsService) Delete(ctx context.Context, clientID int64) error

Delete deletes a client.

func (*ClientsService) Get

func (s *ClientsService) Get(ctx context.Context, clientID int64) (*Client, error)

Get retrieves a specific client.

func (*ClientsService) List

func (s *ClientsService) List(ctx context.Context, opts *ClientListOptions) ([]Client, error)

List returns all clients across all pages.

func (*ClientsService) ListPage added in v0.1.1

func (s *ClientsService) ListPage(ctx context.Context, opts *ClientListOptions) (*ClientList, error)

ListPage returns a single page of clients.

func (*ClientsService) Update

func (s *ClientsService) Update(ctx context.Context, clientID int64, client *ClientUpdateRequest) (*Client, error)

Update updates a client.

type Company

type Company struct {
	BaseURI              string `json:"base_uri"`
	FullDomain           string `json:"full_domain"`
	Name                 string `json:"name"`
	IsActive             bool   `json:"is_active"`
	WeekStartDay         string `json:"week_start_day"`
	WantsTimestampTimers bool   `json:"wants_timestamp_timers"`
	TimeFormat           string `json:"time_format"`
	DateFormat           string `json:"date_format"`
	PlanType             string `json:"plan_type"`
	Clock                string `json:"clock"`
	DecimalSymbol        string `json:"decimal_symbol"`
	ThousandsSeparator   string `json:"thousands_separator"`
	ColorScheme          string `json:"color_scheme"`
	WeeklyCapacity       int    `json:"weekly_capacity"`
	ExpenseFeature       bool   `json:"expense_feature"`
	InvoiceFeature       bool   `json:"invoice_feature"`
	EstimateFeature      bool   `json:"estimate_feature"`
	ApprovalFeature      bool   `json:"approval_feature"`
}

Company represents a company in Harvest.

type CompanyService

type CompanyService struct {
	// contains filtered or unexported fields
}

CompanyService handles communication with the company related methods of the Harvest API.

func (*CompanyService) Get

func (s *CompanyService) Get(ctx context.Context) (*Company, error)

Get retrieves the company for the currently authenticated user.

type Contact

type Contact struct {
	ID          int64     `json:"id"`
	ClientID    int64     `json:"client_id"`
	Client      *Client   `json:"client,omitempty"`
	Title       string    `json:"title,omitempty"`
	FirstName   string    `json:"first_name"`
	LastName    string    `json:"last_name,omitempty"`
	Email       string    `json:"email,omitempty"`
	PhoneOffice string    `json:"phone_office,omitempty"`
	PhoneMobile string    `json:"phone_mobile,omitempty"`
	Fax         string    `json:"fax,omitempty"`
	CreatedAt   time.Time `json:"created_at"`
	UpdatedAt   time.Time `json:"updated_at"`
}

Contact represents a client contact in Harvest.

type ContactCreateRequest

type ContactCreateRequest struct {
	ClientID    int64  `json:"client_id"`
	FirstName   string `json:"first_name"`
	LastName    string `json:"last_name,omitempty"`
	Title       string `json:"title,omitempty"`
	Email       string `json:"email,omitempty"`
	PhoneOffice string `json:"phone_office,omitempty"`
	PhoneMobile string `json:"phone_mobile,omitempty"`
	Fax         string `json:"fax,omitempty"`
}

ContactCreateRequest represents a request to create a contact.

type ContactList

type ContactList struct {
	Contacts []Contact `json:"contacts"`
	Paginated[Contact]
}

ContactList represents a list of contacts.

type ContactListOptions

type ContactListOptions struct {
	ListOptions
	ClientID     int64  `url:"client_id,omitempty"`
	UpdatedSince string `url:"updated_since,omitempty"`
}

ContactListOptions specifies optional parameters to the List method.

type ContactUpdateRequest

type ContactUpdateRequest struct {
	ClientID    int64  `json:"client_id,omitempty"`
	FirstName   string `json:"first_name,omitempty"`
	LastName    string `json:"last_name,omitempty"`
	Title       string `json:"title,omitempty"`
	Email       string `json:"email,omitempty"`
	PhoneOffice string `json:"phone_office,omitempty"`
	PhoneMobile string `json:"phone_mobile,omitempty"`
	Fax         string `json:"fax,omitempty"`
}

ContactUpdateRequest represents a request to update a contact.

type ContactsService

type ContactsService struct {
	// contains filtered or unexported fields
}

ContactsService handles communication with the contact related methods of the Harvest API.

func (*ContactsService) Create

func (s *ContactsService) Create(ctx context.Context, contact *ContactCreateRequest) (*Contact, error)

CreateContact creates a new contact.

func (*ContactsService) Delete

func (s *ContactsService) Delete(ctx context.Context, contactID int64) error

DeleteContact deletes a contact.

func (*ContactsService) Get

func (s *ContactsService) Get(ctx context.Context, contactID int64) (*Contact, error)

GetContact retrieves a specific contact.

func (*ContactsService) List

List returns all contacts across all pages.

func (*ContactsService) ListPage added in v0.1.1

func (s *ContactsService) ListPage(ctx context.Context, opts *ContactListOptions) (*ContactList, error)

ListPage returns a single page of contacts.

func (*ContactsService) Update

func (s *ContactsService) Update(ctx context.Context, contactID int64, contact *ContactUpdateRequest) (*Contact, error)

UpdateContact updates a contact.

type Date

type Date struct {
	time.Time
}

Date represents a date in YYYY-MM-DD format.

func (Date) MarshalJSON

func (d Date) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler for Date.

func (Date) String

func (d Date) String() string

String returns the date as a string in YYYY-MM-DD format.

func (*Date) UnmarshalJSON

func (d *Date) UnmarshalJSON(b []byte) error

UnmarshalJSON implements json.Unmarshaler for Date.

type ErrorResponse

type ErrorResponse struct {
	Response *http.Response
	Message  string `json:"error"`
	Errors   []struct {
		Field   string `json:"field"`
		Message string `json:"message"`
	} `json:"error_description,omitempty"`
}

ErrorResponse represents an error response from the Harvest API.

func (*ErrorResponse) Error

func (e *ErrorResponse) Error() string

type Estimate

type Estimate struct {
	ID             int64            `json:"id"`
	Client         *Client          `json:"client"`
	LineItems      []EstimateItem   `json:"line_items"`
	Number         string           `json:"number"`
	PurchaseOrder  string           `json:"purchase_order,omitempty"`
	Amount         decimal.Decimal  `json:"amount"`
	Tax            *decimal.Decimal `json:"tax,omitempty"`
	TaxAmount      *decimal.Decimal `json:"tax_amount,omitempty"`
	Tax2           *decimal.Decimal `json:"tax2,omitempty"`
	Tax2Amount     *decimal.Decimal `json:"tax2_amount,omitempty"`
	Discount       *decimal.Decimal `json:"discount,omitempty"`
	DiscountAmount *decimal.Decimal `json:"discount_amount,omitempty"`
	Subject        string           `json:"subject,omitempty"`
	Notes          string           `json:"notes,omitempty"`
	Currency       string           `json:"currency"`
	State          string           `json:"state"`
	IssueDate      Date             `json:"issue_date"`
	SentAt         *time.Time       `json:"sent_at,omitempty"`
	AcceptedAt     *time.Time       `json:"accepted_at,omitempty"`
	DeclinedAt     *time.Time       `json:"declined_at,omitempty"`
	CreatedAt      time.Time        `json:"created_at"`
	UpdatedAt      time.Time        `json:"updated_at"`
}

Estimate represents an estimate in Harvest.

type EstimateCreateRequest

type EstimateCreateRequest struct {
	ClientID      int64                     `json:"client_id"`
	Number        string                    `json:"number,omitempty"`
	PurchaseOrder string                    `json:"purchase_order,omitempty"`
	Tax           float64                   `json:"tax,omitempty"`
	Tax2          float64                   `json:"tax2,omitempty"`
	Discount      float64                   `json:"discount,omitempty"`
	Subject       string                    `json:"subject,omitempty"`
	Notes         string                    `json:"notes,omitempty"`
	Currency      string                    `json:"currency,omitempty"`
	IssueDate     string                    `json:"issue_date,omitempty"`
	LineItems     []EstimateLineItemRequest `json:"line_items,omitempty"`
}

EstimateCreateRequest represents a request to create an estimate.

type EstimateItem

type EstimateItem struct {
	ID          int64           `json:"id"`
	Project     *Project        `json:"project,omitempty"`
	Kind        string          `json:"kind"`
	Description string          `json:"description"`
	Quantity    decimal.Decimal `json:"quantity"`
	UnitPrice   decimal.Decimal `json:"unit_price"`
	Amount      decimal.Decimal `json:"amount"`
	Taxed       bool            `json:"taxed"`
	Taxed2      bool            `json:"taxed2"`
}

EstimateItem represents a line item on an estimate.

type EstimateItemCategory added in v0.1.1

type EstimateItemCategory struct {
	ID        int64     `json:"id"`
	Name      string    `json:"name"`
	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updated_at"`
}

EstimateItemCategory represents a category for estimate line items.

type EstimateItemCategoryCreateRequest added in v0.1.1

type EstimateItemCategoryCreateRequest struct {
	Name string `json:"name"`
}

EstimateItemCategoryCreateRequest represents a request to create an estimate item category.

type EstimateItemCategoryList added in v0.1.1

type EstimateItemCategoryList struct {
	EstimateItemCategories []EstimateItemCategory `json:"estimate_item_categories"`
	Paginated[EstimateItemCategory]
}

EstimateItemCategoryList represents a list of estimate item categories.

type EstimateItemCategoryListOptions added in v0.1.1

type EstimateItemCategoryListOptions struct {
	ListOptions
	UpdatedSince string `url:"updated_since,omitempty"`
}

EstimateItemCategoryListOptions specifies optional parameters for listing estimate item categories.

type EstimateItemCategoryUpdateRequest added in v0.1.1

type EstimateItemCategoryUpdateRequest struct {
	Name string `json:"name,omitempty"`
}

EstimateItemCategoryUpdateRequest represents a request to update an estimate item category.

type EstimateLineItemRequest

type EstimateLineItemRequest struct {
	Kind        string  `json:"kind"`
	Description string  `json:"description"`
	Quantity    float64 `json:"quantity"`
	UnitPrice   float64 `json:"unit_price"`
	Taxed       *bool   `json:"taxed,omitempty"`
	Taxed2      *bool   `json:"taxed2,omitempty"`
}

EstimateLineItemRequest represents a line item in an estimate request.

type EstimateList

type EstimateList struct {
	Estimates []Estimate `json:"estimates"`
	Paginated[Estimate]
}

EstimateList represents a list of estimates.

type EstimateListOptions

type EstimateListOptions struct {
	ListOptions
	ClientID     int64  `url:"client_id,omitempty"`
	State        string `url:"state,omitempty"`
	UpdatedSince string `url:"updated_since,omitempty"`
	From         string `url:"from,omitempty"`
	To           string `url:"to,omitempty"`
}

EstimateListOptions specifies optional parameters to the List method.

type EstimateUpdateRequest

type EstimateUpdateRequest struct {
	ClientID      int64                     `json:"client_id,omitempty"`
	Number        string                    `json:"number,omitempty"`
	PurchaseOrder string                    `json:"purchase_order,omitempty"`
	Tax           float64                   `json:"tax,omitempty"`
	Tax2          float64                   `json:"tax2,omitempty"`
	Discount      float64                   `json:"discount,omitempty"`
	Subject       string                    `json:"subject,omitempty"`
	Notes         string                    `json:"notes,omitempty"`
	Currency      string                    `json:"currency,omitempty"`
	IssueDate     string                    `json:"issue_date,omitempty"`
	LineItems     []EstimateLineItemRequest `json:"line_items,omitempty"`
}

EstimateUpdateRequest represents a request to update an estimate.

type EstimatesService

type EstimatesService struct {
	// contains filtered or unexported fields
}

EstimatesService handles communication with the estimate related methods of the Harvest API.

func (*EstimatesService) Create

func (s *EstimatesService) Create(ctx context.Context, estimate *EstimateCreateRequest) (*Estimate, error)

Create creates a new estimate.

func (*EstimatesService) CreateItemCategory added in v0.1.1

CreateItemCategory creates a new estimate item category.

func (*EstimatesService) Delete

func (s *EstimatesService) Delete(ctx context.Context, estimateID int64) error

Delete deletes an estimate.

func (*EstimatesService) DeleteItemCategory added in v0.1.1

func (s *EstimatesService) DeleteItemCategory(ctx context.Context, categoryID int64) error

DeleteItemCategory deletes an estimate item category.

func (*EstimatesService) Get

func (s *EstimatesService) Get(ctx context.Context, estimateID int64) (*Estimate, error)

Get retrieves a specific estimate.

func (*EstimatesService) GetItemCategory added in v0.1.1

func (s *EstimatesService) GetItemCategory(ctx context.Context, categoryID int64) (*EstimateItemCategory, error)

GetItemCategory retrieves a specific estimate item category.

func (*EstimatesService) List

List returns all estimates across all pages.

func (*EstimatesService) ListItemCategories added in v0.1.1

ListItemCategories returns all estimate item categories across all pages. This endpoint uses cursor-based pagination.

func (*EstimatesService) ListItemCategoriesPage added in v0.1.1

ListItemCategoriesPage returns a single page of estimate item categories.

func (*EstimatesService) ListPage added in v0.1.1

ListPage returns a single page of estimates.

func (*EstimatesService) MarkAsAccepted

func (s *EstimatesService) MarkAsAccepted(ctx context.Context, estimateID int64) (*Estimate, error)

MarkAsAccepted marks an estimate as accepted.

func (*EstimatesService) MarkAsDeclined

func (s *EstimatesService) MarkAsDeclined(ctx context.Context, estimateID int64) (*Estimate, error)

MarkAsDeclined marks an estimate as declined.

func (*EstimatesService) MarkAsSent

func (s *EstimatesService) MarkAsSent(ctx context.Context, estimateID int64) (*Estimate, error)

MarkAsSent marks an estimate as sent.

func (*EstimatesService) Reopen

func (s *EstimatesService) Reopen(ctx context.Context, estimateID int64) (*Estimate, error)

Reopen reopens a closed estimate.

func (*EstimatesService) Update

func (s *EstimatesService) Update(ctx context.Context, estimateID int64, estimate *EstimateUpdateRequest) (*Estimate, error)

Update updates an estimate.

func (*EstimatesService) UpdateItemCategory added in v0.1.1

func (s *EstimatesService) UpdateItemCategory(ctx context.Context, categoryID int64, category *EstimateItemCategoryUpdateRequest) (*EstimateItemCategory, error)

UpdateItemCategory updates an estimate item category.

type Expense

type Expense struct {
	ID              int64                  `json:"id"`
	Client          *Client                `json:"client"`
	Project         *Project               `json:"project"`
	ExpenseCategory *ExpenseCategory       `json:"expense_category"`
	User            *User                  `json:"user"`
	UserAssignment  *ProjectUserAssignment `json:"user_assignment"`
	Invoice         *Invoice               `json:"invoice,omitempty"`
	Receipt         *Receipt               `json:"receipt,omitempty"`
	Notes           string                 `json:"notes,omitempty"`
	IsLocked        bool                   `json:"is_locked"`
	LockedReason    string                 `json:"locked_reason,omitempty"`
	IsClosed        bool                   `json:"is_closed"`
	IsBilled        bool                   `json:"is_billed"`
	Billable        bool                   `json:"billable"`
	SpentDate       Date                   `json:"spent_date"`
	TotalCost       decimal.Decimal        `json:"total_cost"`
	Units           *decimal.Decimal       `json:"units,omitempty"`
	CreatedAt       time.Time              `json:"created_at"`
	UpdatedAt       time.Time              `json:"updated_at"`
}

Expense represents an expense in Harvest.

type ExpenseCategory

type ExpenseCategory struct {
	ID        int64            `json:"id"`
	Name      string           `json:"name"`
	UnitName  string           `json:"unit_name,omitempty"`
	UnitPrice *decimal.Decimal `json:"unit_price,omitempty"`
	IsActive  bool             `json:"is_active"`
	CreatedAt time.Time        `json:"created_at"`
	UpdatedAt time.Time        `json:"updated_at"`
}

ExpenseCategory represents an expense category.

type ExpenseCategoryCreateRequest

type ExpenseCategoryCreateRequest struct {
	Name      string  `json:"name"`
	UnitName  string  `json:"unit_name,omitempty"`
	UnitPrice float64 `json:"unit_price,omitempty"`
	IsActive  *bool   `json:"is_active,omitempty"`
}

ExpenseCategoryCreateRequest represents a request to create an expense category.

type ExpenseCategoryList

type ExpenseCategoryList struct {
	ExpenseCategories []ExpenseCategory `json:"expense_categories"`
	Paginated[ExpenseCategory]
}

ExpenseCategoryList represents a list of expense categories.

type ExpenseCategoryListOptions

type ExpenseCategoryListOptions struct {
	ListOptions
	IsActive     *bool  `url:"is_active,omitempty"`
	UpdatedSince string `url:"updated_since,omitempty"`
}

ExpenseCategoryListOptions specifies optional parameters for listing expense categories.

type ExpenseCategoryUpdateRequest

type ExpenseCategoryUpdateRequest struct {
	Name      string  `json:"name,omitempty"`
	UnitName  string  `json:"unit_name,omitempty"`
	UnitPrice float64 `json:"unit_price,omitempty"`
	IsActive  *bool   `json:"is_active,omitempty"`
}

ExpenseCategoryUpdateRequest represents a request to update an expense category.

type ExpenseCreateRequest

type ExpenseCreateRequest struct {
	ProjectID         int64   `json:"project_id"`
	ExpenseCategoryID int64   `json:"expense_category_id"`
	SpentDate         string  `json:"spent_date"`
	UserID            int64   `json:"user_id,omitempty"`
	Notes             string  `json:"notes,omitempty"`
	Units             float64 `json:"units,omitempty"`
	TotalCost         float64 `json:"total_cost,omitempty"`
	Billable          *bool   `json:"billable,omitempty"`
}

ExpenseCreateRequest represents a request to create an expense.

type ExpenseList

type ExpenseList struct {
	Expenses []Expense `json:"expenses"`
	Paginated[Expense]
}

ExpenseList represents a list of expenses.

type ExpenseListOptions

type ExpenseListOptions struct {
	ListOptions
	UserID         int64  `url:"user_id,omitempty"`
	ClientID       int64  `url:"client_id,omitempty"`
	ProjectID      int64  `url:"project_id,omitempty"`
	IsBilled       *bool  `url:"is_billed,omitempty"`
	ApprovalStatus string `url:"approval_status,omitempty"`
	UpdatedSince   string `url:"updated_since,omitempty"`
	From           string `url:"from,omitempty"`
	To             string `url:"to,omitempty"`
}

ExpenseListOptions specifies optional parameters to the List method.

type ExpenseReport

type ExpenseReport struct {
	ClientID            int64           `json:"client_id"`
	ClientName          string          `json:"client_name"`
	ProjectID           int64           `json:"project_id"`
	ProjectName         string          `json:"project_name"`
	ExpenseCategoryID   int64           `json:"expense_category_id"`
	ExpenseCategoryName string          `json:"expense_category_name"`
	UserID              int64           `json:"user_id"`
	UserName            string          `json:"user_name"`
	IsContractor        bool            `json:"is_contractor"`
	TotalAmount         decimal.Decimal `json:"total_amount"`
	BillableAmount      decimal.Decimal `json:"billable_amount"`
	Currency            string          `json:"currency"`
}

ExpenseReport represents an expense report entry.

type ExpenseReportResults

type ExpenseReportResults struct {
	Results      []ExpenseReport  `json:"results"`
	PerPage      int              `json:"per_page"`
	TotalPages   int              `json:"total_pages"`
	TotalEntries int              `json:"total_entries"`
	NextPage     *int             `json:"next_page"`
	PreviousPage *int             `json:"previous_page"`
	Page         int              `json:"page"`
	Links        *PaginationLinks `json:"links"`
}

ExpenseReportResults represents expense report results.

type ExpenseReportsOptions

type ExpenseReportsOptions struct {
	From      string `url:"from"`
	To        string `url:"to"`
	ClientID  int64  `url:"client_id,omitempty"`
	ProjectID int64  `url:"project_id,omitempty"`
	UserID    int64  `url:"user_id,omitempty"`
	IsBilled  *bool  `url:"is_billed,omitempty"`
	Page      int    `url:"page,omitempty"`
	PerPage   int    `url:"per_page,omitempty"`
}

ExpenseReportsOptions specifies optional parameters for expense reports.

type ExpenseUpdateRequest

type ExpenseUpdateRequest struct {
	ProjectID         int64   `json:"project_id,omitempty"`
	ExpenseCategoryID int64   `json:"expense_category_id,omitempty"`
	SpentDate         string  `json:"spent_date,omitempty"`
	Notes             string  `json:"notes,omitempty"`
	Units             float64 `json:"units,omitempty"`
	TotalCost         float64 `json:"total_cost,omitempty"`
	Billable          *bool   `json:"billable,omitempty"`
}

ExpenseUpdateRequest represents a request to update an expense.

type ExpensesService

type ExpensesService struct {
	// contains filtered or unexported fields
}

ExpensesService handles communication with the expense related methods of the Harvest API.

func (*ExpensesService) Create

func (s *ExpensesService) Create(ctx context.Context, expense *ExpenseCreateRequest) (*Expense, error)

Create creates a new expense.

func (*ExpensesService) CreateCategory

func (s *ExpensesService) CreateCategory(ctx context.Context, category *ExpenseCategoryCreateRequest) (*ExpenseCategory, error)

CreateCategory creates a new expense category.

func (*ExpensesService) Delete

func (s *ExpensesService) Delete(ctx context.Context, expenseID int64) error

Delete deletes an expense.

func (*ExpensesService) DeleteCategory

func (s *ExpensesService) DeleteCategory(ctx context.Context, categoryID int64) error

DeleteCategory deletes an expense category.

func (*ExpensesService) Get

func (s *ExpensesService) Get(ctx context.Context, expenseID int64) (*Expense, error)

Get retrieves a specific expense.

func (*ExpensesService) GetCategory

func (s *ExpensesService) GetCategory(ctx context.Context, categoryID int64) (*ExpenseCategory, error)

GetCategory retrieves a specific expense category.

func (*ExpensesService) List

List returns all expenses across all pages.

func (*ExpensesService) ListCategories

ListCategories returns all expense categories across all pages.

func (*ExpensesService) ListCategoriesPage added in v0.1.1

ListCategoriesPage returns a single page of expense categories.

func (*ExpensesService) ListPage added in v0.1.1

func (s *ExpensesService) ListPage(ctx context.Context, opts *ExpenseListOptions) (*ExpenseList, error)

ListPage returns a single page of expenses.

func (*ExpensesService) Update

func (s *ExpensesService) Update(ctx context.Context, expenseID int64, expense *ExpenseUpdateRequest) (*Expense, error)

Update updates an expense.

func (*ExpensesService) UpdateCategory

func (s *ExpensesService) UpdateCategory(ctx context.Context, categoryID int64, category *ExpenseCategoryUpdateRequest) (*ExpenseCategory, error)

UpdateCategory updates an expense category.

type ExternalReference

type ExternalReference struct {
	ID             string `json:"id"`
	GroupID        string `json:"group_id"`
	AccountID      string `json:"account_id"`
	Permalink      string `json:"permalink"`
	Service        string `json:"service"`
	ServiceIconURL string `json:"service_icon_url"`
}

ExternalReference represents an external reference for a time entry.

type ExternalReferenceRequest

type ExternalReferenceRequest struct {
	ID        string `json:"id"`
	GroupID   string `json:"group_id"`
	AccountID string `json:"account_id"`
	Permalink string `json:"permalink"`
}

ExternalReferenceRequest represents an external reference in a request.

type Invoice

type Invoice struct {
	ID                 int64            `json:"id"`
	Client             *Client          `json:"client"`
	LineItems          []InvoiceItem    `json:"line_items"`
	Estimate           *Estimate        `json:"estimate,omitempty"`
	Number             string           `json:"number"`
	PurchaseOrder      string           `json:"purchase_order,omitempty"`
	Amount             decimal.Decimal  `json:"amount"`
	DueAmount          decimal.Decimal  `json:"due_amount"`
	Tax                *decimal.Decimal `json:"tax,omitempty"`
	TaxAmount          *decimal.Decimal `json:"tax_amount,omitempty"`
	Tax2               *decimal.Decimal `json:"tax2,omitempty"`
	Tax2Amount         *decimal.Decimal `json:"tax2_amount,omitempty"`
	Discount           *decimal.Decimal `json:"discount,omitempty"`
	DiscountAmount     *decimal.Decimal `json:"discount_amount,omitempty"`
	Subject            string           `json:"subject,omitempty"`
	Notes              string           `json:"notes,omitempty"`
	Currency           string           `json:"currency"`
	State              string           `json:"state"`
	PeriodStart        *Date            `json:"period_start,omitempty"`
	PeriodEnd          *Date            `json:"period_end,omitempty"`
	IssueDate          Date             `json:"issue_date"`
	DueDate            *Date            `json:"due_date,omitempty"`
	PaymentTerm        string           `json:"payment_term,omitempty"`
	SentAt             *time.Time       `json:"sent_at,omitempty"`
	PaidAt             *time.Time       `json:"paid_at,omitempty"`
	ClosedAt           *time.Time       `json:"closed_at,omitempty"`
	RecurringInvoiceID *int64           `json:"recurring_invoice_id,omitempty"`
	CreatedAt          time.Time        `json:"created_at"`
	UpdatedAt          time.Time        `json:"updated_at"`
}

Invoice represents an invoice in Harvest.

type InvoiceCreateRequest

type InvoiceCreateRequest struct {
	ClientID      int64                    `json:"client_id"`
	EstimateID    int64                    `json:"estimate_id,omitempty"`
	Number        string                   `json:"number,omitempty"`
	PurchaseOrder string                   `json:"purchase_order,omitempty"`
	Tax           float64                  `json:"tax,omitempty"`
	Tax2          float64                  `json:"tax2,omitempty"`
	Discount      float64                  `json:"discount,omitempty"`
	Subject       string                   `json:"subject,omitempty"`
	Notes         string                   `json:"notes,omitempty"`
	Currency      string                   `json:"currency,omitempty"`
	IssueDate     string                   `json:"issue_date,omitempty"`
	DueDate       string                   `json:"due_date,omitempty"`
	PaymentTerm   string                   `json:"payment_term,omitempty"`
	LineItems     []InvoiceLineItemRequest `json:"line_items,omitempty"`
}

InvoiceCreateRequest represents a request to create an invoice.

type InvoiceItem

type InvoiceItem struct {
	ID          int64           `json:"id"`
	Project     *Project        `json:"project,omitempty"`
	Kind        string          `json:"kind"`
	Description string          `json:"description"`
	Quantity    decimal.Decimal `json:"quantity"`
	UnitPrice   decimal.Decimal `json:"unit_price"`
	Amount      decimal.Decimal `json:"amount"`
	Taxed       bool            `json:"taxed"`
	Taxed2      bool            `json:"taxed2"`
}

InvoiceItem represents a line item on an invoice.

type InvoiceItemCategory added in v0.1.1

type InvoiceItemCategory struct {
	ID           int64     `json:"id"`
	Name         string    `json:"name"`
	UseAsService bool      `json:"use_as_service"`
	UseAsExpense bool      `json:"use_as_expense"`
	CreatedAt    time.Time `json:"created_at"`
	UpdatedAt    time.Time `json:"updated_at"`
}

InvoiceItemCategory represents a category for invoice line items.

type InvoiceItemCategoryCreateRequest added in v0.1.1

type InvoiceItemCategoryCreateRequest struct {
	Name string `json:"name"`
}

InvoiceItemCategoryCreateRequest represents a request to create an invoice item category.

type InvoiceItemCategoryList added in v0.1.1

type InvoiceItemCategoryList struct {
	InvoiceItemCategories []InvoiceItemCategory `json:"invoice_item_categories"`
	Paginated[InvoiceItemCategory]
}

InvoiceItemCategoryList represents a list of invoice item categories.

type InvoiceItemCategoryListOptions added in v0.1.1

type InvoiceItemCategoryListOptions struct {
	ListOptions
	UpdatedSince string `url:"updated_since,omitempty"`
}

InvoiceItemCategoryListOptions specifies optional parameters for listing invoice item categories.

type InvoiceItemCategoryUpdateRequest added in v0.1.1

type InvoiceItemCategoryUpdateRequest struct {
	Name string `json:"name,omitempty"`
}

InvoiceItemCategoryUpdateRequest represents a request to update an invoice item category.

type InvoiceLineItemRequest

type InvoiceLineItemRequest struct {
	ProjectID   int64   `json:"project_id,omitempty"`
	Kind        string  `json:"kind"`
	Description string  `json:"description"`
	Quantity    float64 `json:"quantity"`
	UnitPrice   float64 `json:"unit_price"`
	Taxed       *bool   `json:"taxed,omitempty"`
	Taxed2      *bool   `json:"taxed2,omitempty"`
}

InvoiceLineItemRequest represents a line item in an invoice request.

type InvoiceList

type InvoiceList struct {
	Invoices []Invoice `json:"invoices"`
	Paginated[Invoice]
}

InvoiceList represents a list of invoices.

type InvoiceListOptions

type InvoiceListOptions struct {
	ListOptions
	ClientID     int64  `url:"client_id,omitempty"`
	ProjectID    int64  `url:"project_id,omitempty"`
	State        string `url:"state,omitempty"`
	UpdatedSince string `url:"updated_since,omitempty"`
	From         string `url:"from,omitempty"`
	To           string `url:"to,omitempty"`
}

InvoiceListOptions specifies optional parameters to the List method.

type InvoiceMessage added in v0.1.1

type InvoiceMessage struct {
	ID                         int64     `json:"id"`
	SentBy                     string    `json:"sent_by"`
	SentByEmail                string    `json:"sent_by_email"`
	SentFrom                   string    `json:"sent_from"`
	SentFromEmail              string    `json:"sent_from_email"`
	IncludeLinkToClientInvoice bool      `json:"include_link_to_client_invoice"`
	SendMeACopy                bool      `json:"send_me_a_copy"`
	ThankYou                   bool      `json:"thank_you"`
	Reminder                   bool      `json:"reminder"`
	SendReminderOn             *Date     `json:"send_reminder_on"`
	CreatedAt                  time.Time `json:"created_at"`
	UpdatedAt                  time.Time `json:"updated_at"`
	AttachPDF                  bool      `json:"attach_pdf"`
	EventType                  string    `json:"event_type"`
	Recipients                 []string  `json:"recipients"`
	Subject                    *string   `json:"subject"`
	Body                       *string   `json:"body"`
}

InvoiceMessage represents a message associated with an invoice.

type InvoiceMessageList added in v0.1.1

type InvoiceMessageList struct {
	InvoiceMessages []InvoiceMessage `json:"invoice_messages"`
	Paginated[InvoiceMessage]
}

InvoiceMessageList represents a list of invoice messages.

type InvoiceMessageListOptions added in v0.1.1

type InvoiceMessageListOptions struct {
	ListOptions
	UpdatedSince string `url:"updated_since,omitempty"`
}

InvoiceMessageListOptions specifies optional parameters for listing invoice messages.

type InvoiceMessageRequest added in v0.1.1

type InvoiceMessageRequest struct {
	EventType string `json:"event_type"`
}

InvoiceMessageRequest represents a request to create an invoice message.

type InvoiceUpdateRequest

type InvoiceUpdateRequest struct {
	ClientID      int64                    `json:"client_id,omitempty"`
	EstimateID    int64                    `json:"estimate_id,omitempty"`
	Number        string                   `json:"number,omitempty"`
	PurchaseOrder string                   `json:"purchase_order,omitempty"`
	Tax           float64                  `json:"tax,omitempty"`
	Tax2          float64                  `json:"tax2,omitempty"`
	Discount      float64                  `json:"discount,omitempty"`
	Subject       string                   `json:"subject,omitempty"`
	Notes         string                   `json:"notes,omitempty"`
	Currency      string                   `json:"currency,omitempty"`
	IssueDate     string                   `json:"issue_date,omitempty"`
	DueDate       string                   `json:"due_date,omitempty"`
	PaymentTerm   string                   `json:"payment_term,omitempty"`
	LineItems     []InvoiceLineItemRequest `json:"line_items,omitempty"`
}

InvoiceUpdateRequest represents a request to update an invoice.

type InvoicesService

type InvoicesService struct {
	// contains filtered or unexported fields
}

InvoicesService handles communication with the invoice related methods of the Harvest API.

func (*InvoicesService) Create

func (s *InvoicesService) Create(ctx context.Context, invoice *InvoiceCreateRequest) (*Invoice, error)

Create creates a new invoice.

func (*InvoicesService) CreateItemCategory added in v0.1.1

CreateItemCategory creates a new invoice item category.

func (*InvoicesService) Delete

func (s *InvoicesService) Delete(ctx context.Context, invoiceID int64) error

Delete deletes an invoice.

func (*InvoicesService) DeleteItemCategory added in v0.1.1

func (s *InvoicesService) DeleteItemCategory(ctx context.Context, categoryID int64) error

DeleteItemCategory deletes an invoice item category.

func (*InvoicesService) Get

func (s *InvoicesService) Get(ctx context.Context, invoiceID int64) (*Invoice, error)

Get retrieves a specific invoice.

func (*InvoicesService) GetItemCategory added in v0.1.1

func (s *InvoicesService) GetItemCategory(ctx context.Context, categoryID int64) (*InvoiceItemCategory, error)

GetItemCategory retrieves a specific invoice item category.

func (*InvoicesService) List

List returns all invoices across all pages.

func (*InvoicesService) ListItemCategories added in v0.1.1

ListItemCategories returns all invoice item categories across all pages. This endpoint uses cursor-based pagination.

func (*InvoicesService) ListItemCategoriesPage added in v0.1.1

ListItemCategoriesPage returns a single page of invoice item categories.

func (*InvoicesService) ListMessages added in v0.1.1

func (s *InvoicesService) ListMessages(ctx context.Context, invoiceID int64, opts *InvoiceMessageListOptions) ([]InvoiceMessage, error)

ListMessages returns all messages for an invoice across all pages.

func (*InvoicesService) ListMessagesPage added in v0.1.1

func (s *InvoicesService) ListMessagesPage(ctx context.Context, invoiceID int64, opts *InvoiceMessageListOptions) (*InvoiceMessageList, error)

ListMessagesPage returns a single page of messages for an invoice.

func (*InvoicesService) ListPage added in v0.1.1

func (s *InvoicesService) ListPage(ctx context.Context, opts *InvoiceListOptions) (*InvoiceList, error)

ListPage returns a single page of invoices.

func (*InvoicesService) MarkAsClosed

func (s *InvoicesService) MarkAsClosed(ctx context.Context, invoiceID int64) (*Invoice, error)

MarkAsClosed marks an invoice as closed.

func (*InvoicesService) MarkAsDraft

func (s *InvoicesService) MarkAsDraft(ctx context.Context, invoiceID int64) (*InvoiceMessage, error)

MarkAsDraft marks an open invoice as a draft.

func (*InvoicesService) MarkAsSent

func (s *InvoicesService) MarkAsSent(ctx context.Context, invoiceID int64) (*InvoiceMessage, error)

MarkAsSent marks a draft invoice as sent.

func (*InvoicesService) Reopen

func (s *InvoicesService) Reopen(ctx context.Context, invoiceID int64) (*Invoice, error)

Reopen reopens a closed invoice.

func (*InvoicesService) Update

func (s *InvoicesService) Update(ctx context.Context, invoiceID int64, invoice *InvoiceUpdateRequest) (*Invoice, error)

Update updates an invoice.

func (*InvoicesService) UpdateItemCategory added in v0.1.1

func (s *InvoicesService) UpdateItemCategory(ctx context.Context, categoryID int64, category *InvoiceItemCategoryUpdateRequest) (*InvoiceItemCategory, error)

UpdateItemCategory updates an invoice item category.

type Iterator

type Iterator[T any] struct {
	// contains filtered or unexported fields
}

Iterator provides iteration over paginated results.

func NewIterator

func NewIterator[T any](ctx context.Context, client *API, path string, opts *ListOptions,
	fetcher func(context.Context, *API, string, *ListOptions) (*Paginated[T], error)) *Iterator[T]

NewIterator creates a new iterator for paginated results.

func (*Iterator[T]) All

func (it *Iterator[T]) All() ([]T, error)

All fetches all pages and returns all items.

func (*Iterator[T]) Next

func (it *Iterator[T]) Next() (*T, error)

Next returns the next item in the iteration.

type ListOptions

type ListOptions struct {
	Page         int        `url:"page,omitempty"`
	PerPage      int        `url:"per_page,omitempty"`
	UpdatedSince *time.Time `url:"updated_since,omitempty"`
}

ListOptions specifies optional parameters to List methods.

type Paginated

type Paginated[T any] struct {
	Items        []T              `json:"-"`
	Links        *PaginationLinks `json:"links"`
	PerPage      int              `json:"per_page"`
	TotalPages   int              `json:"total_pages"`
	TotalEntries int              `json:"total_entries"`
	NextPage     *int             `json:"next_page"`
	PreviousPage *int             `json:"previous_page"`
	Page         int              `json:"page"`
}

Paginated represents a paginated response from the Harvest API.

func ListPage added in v0.1.1

func ListPage[T any](ctx context.Context, c *API, path string, opts *ListOptions) (*Paginated[T], error)

ListPage performs a GET request to list resources with pagination, returning a single page.

func ListPageFromURL added in v0.1.1

func ListPageFromURL[T any](ctx context.Context, c *API, fullURL string) (*Paginated[T], error)

ListPageFromURL performs a GET request using a full pagination URL. This is used for cursor-based pagination where the API provides full URLs in the links section.

func (*Paginated[T]) GetNextPageURL added in v0.1.1

func (p *Paginated[T]) GetNextPageURL() string

GetNextPageURL returns the URL for the next page. Returns empty string if there is no next page.

func (*Paginated[T]) HasNextPage

func (p *Paginated[T]) HasNextPage() bool

HasNextPage returns true if there is a next page of results. This works for both page-based and cursor-based pagination.

func (*Paginated[T]) HasPreviousPage

func (p *Paginated[T]) HasPreviousPage() bool

HasPreviousPage returns true if there is a previous page of results.

type PaginationLinks struct {
	First    string `json:"first"`
	Next     string `json:"next,omitempty"`
	Previous string `json:"previous,omitempty"`
	Last     string `json:"last"`
}

PaginationLinks represents pagination links in API responses.

type Project

type Project struct {
	ID                               int64            `json:"id"`
	Client                           *Client          `json:"client"`
	Name                             string           `json:"name"`
	Code                             string           `json:"code,omitempty"`
	IsActive                         bool             `json:"is_active"`
	IsBillable                       bool             `json:"is_billable"`
	IsFixedFee                       bool             `json:"is_fixed_fee"`
	BillBy                           string           `json:"bill_by"`
	Budget                           *decimal.Decimal `json:"budget,omitempty"`
	BudgetBy                         string           `json:"budget_by,omitempty"`
	BudgetIsMonthly                  bool             `json:"budget_is_monthly"`
	NotifyWhenOverBudget             bool             `json:"notify_when_over_budget"`
	OverBudgetNotificationPercentage decimal.Decimal  `json:"over_budget_notification_percentage,omitempty"`
	ShowBudgetToAll                  bool             `json:"show_budget_to_all"`
	CostBudget                       *decimal.Decimal `json:"cost_budget,omitempty"`
	CostBudgetIncludeExpenses        bool             `json:"cost_budget_include_expenses"`
	HourlyRate                       *decimal.Decimal `json:"hourly_rate,omitempty"`
	Fee                              *decimal.Decimal `json:"fee,omitempty"`
	Notes                            string           `json:"notes,omitempty"`
	StartsOn                         *Date            `json:"starts_on,omitempty"`
	EndsOn                           *Date            `json:"ends_on,omitempty"`
	CreatedAt                        time.Time        `json:"created_at"`
	UpdatedAt                        time.Time        `json:"updated_at"`
}

Project represents a project in Harvest.

type ProjectBudgetReport

type ProjectBudgetReport struct {
	ClientID         int64            `json:"client_id"`
	ClientName       string           `json:"client_name"`
	ProjectID        int64            `json:"project_id"`
	ProjectName      string           `json:"project_name"`
	ProjectCode      string           `json:"project_code"`
	ProjectStartDate *Date            `json:"project_start_date"`
	ProjectEndDate   *Date            `json:"project_end_date"`
	IsBillable       bool             `json:"is_billable"`
	IsActive         bool             `json:"is_active"`
	BudgetBy         string           `json:"budget_by"`
	Budget           *decimal.Decimal `json:"budget"`
	BudgetSpent      decimal.Decimal  `json:"budget_spent"`
	BudgetRemaining  *decimal.Decimal `json:"budget_remaining"`
}

ProjectBudgetReport represents a project budget report entry.

type ProjectBudgetReportOptions

type ProjectBudgetReportOptions struct {
	Page         int    `url:"page,omitempty"`
	PerPage      int    `url:"per_page,omitempty"`
	IsActive     *bool  `url:"is_active,omitempty"`
	ClientID     int64  `url:"client_id,omitempty"`
	UpdatedSince string `url:"updated_since,omitempty"`
}

ProjectBudgetReportOptions specifies optional parameters for project budget reports.

type ProjectBudgetReportResults

type ProjectBudgetReportResults struct {
	Results      []ProjectBudgetReport `json:"results"`
	PerPage      int                   `json:"per_page"`
	TotalPages   int                   `json:"total_pages"`
	TotalEntries int                   `json:"total_entries"`
	NextPage     *int                  `json:"next_page"`
	PreviousPage *int                  `json:"previous_page"`
	Page         int                   `json:"page"`
	Links        *PaginationLinks      `json:"links"`
}

ProjectBudgetReportResults represents project budget report results.

type ProjectCreateRequest

type ProjectCreateRequest struct {
	ClientID                         int64   `json:"client_id"`
	Name                             string  `json:"name"`
	Code                             string  `json:"code,omitempty"`
	IsActive                         *bool   `json:"is_active,omitempty"`
	IsBillable                       *bool   `json:"is_billable,omitempty"`
	IsFixedFee                       *bool   `json:"is_fixed_fee,omitempty"`
	BillBy                           string  `json:"bill_by,omitempty"`
	Budget                           float64 `json:"budget,omitempty"`
	BudgetBy                         string  `json:"budget_by,omitempty"`
	BudgetIsMonthly                  *bool   `json:"budget_is_monthly,omitempty"`
	NotifyWhenOverBudget             *bool   `json:"notify_when_over_budget,omitempty"`
	OverBudgetNotificationPercentage float64 `json:"over_budget_notification_percentage,omitempty"`
	ShowBudgetToAll                  *bool   `json:"show_budget_to_all,omitempty"`
	CostBudget                       float64 `json:"cost_budget,omitempty"`
	CostBudgetIncludeExpenses        *bool   `json:"cost_budget_include_expenses,omitempty"`
	HourlyRate                       float64 `json:"hourly_rate,omitempty"`
	Fee                              float64 `json:"fee,omitempty"`
	Notes                            string  `json:"notes,omitempty"`
	StartsOn                         string  `json:"starts_on,omitempty"`
	EndsOn                           string  `json:"ends_on,omitempty"`
}

ProjectCreateRequest represents a request to create a project.

type ProjectList

type ProjectList struct {
	Projects []Project `json:"projects"`
	Paginated[Project]
}

ProjectList represents a list of projects.

type ProjectListOptions

type ProjectListOptions struct {
	ListOptions
	IsActive     *bool  `url:"is_active,omitempty"`
	ClientID     int64  `url:"client_id,omitempty"`
	UpdatedSince string `url:"updated_since,omitempty"`
}

ProjectListOptions specifies optional parameters to the List method.

type ProjectTaskAssignment

type ProjectTaskAssignment struct {
	ID         int64            `json:"id"`
	Project    *Project         `json:"project"`
	Task       *Task            `json:"task"`
	IsActive   bool             `json:"is_active"`
	Billable   bool             `json:"billable"`
	HourlyRate *decimal.Decimal `json:"hourly_rate,omitempty"`
	Budget     *decimal.Decimal `json:"budget,omitempty"`
	CreatedAt  time.Time        `json:"created_at"`
	UpdatedAt  time.Time        `json:"updated_at"`
}

ProjectTaskAssignment represents a task assignment to a project.

type ProjectUpdateRequest

type ProjectUpdateRequest struct {
	ClientID                         int64   `json:"client_id,omitempty"`
	Name                             string  `json:"name,omitempty"`
	Code                             string  `json:"code,omitempty"`
	IsActive                         *bool   `json:"is_active,omitempty"`
	IsBillable                       *bool   `json:"is_billable,omitempty"`
	IsFixedFee                       *bool   `json:"is_fixed_fee,omitempty"`
	BillBy                           string  `json:"bill_by,omitempty"`
	Budget                           float64 `json:"budget,omitempty"`
	BudgetBy                         string  `json:"budget_by,omitempty"`
	BudgetIsMonthly                  *bool   `json:"budget_is_monthly,omitempty"`
	NotifyWhenOverBudget             *bool   `json:"notify_when_over_budget,omitempty"`
	OverBudgetNotificationPercentage float64 `json:"over_budget_notification_percentage,omitempty"`
	ShowBudgetToAll                  *bool   `json:"show_budget_to_all,omitempty"`
	CostBudget                       float64 `json:"cost_budget,omitempty"`
	CostBudgetIncludeExpenses        *bool   `json:"cost_budget_include_expenses,omitempty"`
	HourlyRate                       float64 `json:"hourly_rate,omitempty"`
	Fee                              float64 `json:"fee,omitempty"`
	Notes                            string  `json:"notes,omitempty"`
	StartsOn                         string  `json:"starts_on,omitempty"`
	EndsOn                           string  `json:"ends_on,omitempty"`
}

ProjectUpdateRequest represents a request to update a project.

type ProjectUserAssignment

type ProjectUserAssignment struct {
	ID               int64            `json:"id"`
	Project          *Project         `json:"project"`
	User             *User            `json:"user"`
	IsActive         bool             `json:"is_active"`
	IsProjectManager bool             `json:"is_project_manager"`
	UseDefaultRates  bool             `json:"use_default_rates"`
	HourlyRate       *decimal.Decimal `json:"hourly_rate,omitempty"`
	Budget           *decimal.Decimal `json:"budget,omitempty"`
	CreatedAt        time.Time        `json:"created_at"`
	UpdatedAt        time.Time        `json:"updated_at"`
}

ProjectUserAssignment represents a user assignment to a project.

type ProjectsService

type ProjectsService struct {
	// contains filtered or unexported fields
}

ProjectsService handles communication with the project related methods of the Harvest API.

func (*ProjectsService) Create

func (s *ProjectsService) Create(ctx context.Context, project *ProjectCreateRequest) (*Project, error)

Create creates a new project.

func (*ProjectsService) CreateTaskAssignment

func (s *ProjectsService) CreateTaskAssignment(ctx context.Context, projectID int64, assignment *TaskAssignmentCreateRequest) (*ProjectTaskAssignment, error)

CreateTaskAssignment creates a new task assignment for a project.

func (*ProjectsService) CreateUserAssignment

func (s *ProjectsService) CreateUserAssignment(ctx context.Context, projectID int64, assignment *UserAssignmentCreateRequest) (*ProjectUserAssignment, error)

CreateUserAssignment creates a new user assignment for a project.

func (*ProjectsService) Delete

func (s *ProjectsService) Delete(ctx context.Context, projectID int64) error

Delete deletes a project.

func (*ProjectsService) DeleteTaskAssignment

func (s *ProjectsService) DeleteTaskAssignment(ctx context.Context, projectID, taskAssignmentID int64) error

DeleteTaskAssignment deletes a task assignment.

func (*ProjectsService) DeleteUserAssignment

func (s *ProjectsService) DeleteUserAssignment(ctx context.Context, projectID, userAssignmentID int64) error

DeleteUserAssignment deletes a user assignment.

func (*ProjectsService) Get

func (s *ProjectsService) Get(ctx context.Context, projectID int64) (*Project, error)

Get retrieves a specific project.

func (*ProjectsService) GetTaskAssignment

func (s *ProjectsService) GetTaskAssignment(ctx context.Context, projectID, taskAssignmentID int64) (*ProjectTaskAssignment, error)

GetTaskAssignment retrieves a specific task assignment.

func (*ProjectsService) GetUserAssignment

func (s *ProjectsService) GetUserAssignment(ctx context.Context, projectID, userAssignmentID int64) (*ProjectUserAssignment, error)

GetUserAssignment retrieves a specific user assignment.

func (*ProjectsService) List

List returns all projects across all pages.

func (*ProjectsService) ListPage added in v0.1.1

func (s *ProjectsService) ListPage(ctx context.Context, opts *ProjectListOptions) (*ProjectList, error)

ListPage returns a single page of projects.

func (*ProjectsService) ListTaskAssignments

func (s *ProjectsService) ListTaskAssignments(ctx context.Context, projectID int64, opts *TaskAssignmentListOptions) ([]ProjectTaskAssignment, error)

ListTaskAssignments returns all task assignments for a project across all pages. This endpoint uses cursor-based pagination.

func (*ProjectsService) ListTaskAssignmentsPage added in v0.1.1

func (s *ProjectsService) ListTaskAssignmentsPage(ctx context.Context, projectID int64, opts *TaskAssignmentListOptions) (*TaskAssignmentList, error)

ListTaskAssignmentsPage returns a single page of task assignments for a project.

func (*ProjectsService) ListUserAssignments

func (s *ProjectsService) ListUserAssignments(ctx context.Context, projectID int64, opts *UserAssignmentListOptions) ([]ProjectUserAssignment, error)

ListUserAssignments returns all user assignments for a project across all pages. This endpoint uses cursor-based pagination.

func (*ProjectsService) ListUserAssignmentsPage added in v0.1.1

func (s *ProjectsService) ListUserAssignmentsPage(ctx context.Context, projectID int64, opts *UserAssignmentListOptions) (*UserAssignmentList, error)

ListUserAssignmentsPage returns a single page of user assignments for a project.

func (*ProjectsService) Update

func (s *ProjectsService) Update(ctx context.Context, projectID int64, project *ProjectUpdateRequest) (*Project, error)

Update updates a project.

func (*ProjectsService) UpdateTaskAssignment

func (s *ProjectsService) UpdateTaskAssignment(ctx context.Context, projectID, taskAssignmentID int64, assignment *TaskAssignmentUpdateRequest) (*ProjectTaskAssignment, error)

UpdateTaskAssignment updates a task assignment.

func (*ProjectsService) UpdateUserAssignment

func (s *ProjectsService) UpdateUserAssignment(ctx context.Context, projectID, userAssignmentID int64, assignment *UserAssignmentUpdateRequest) (*ProjectUserAssignment, error)

UpdateUserAssignment updates a user assignment.

type Rate

type Rate struct {
	Limit     int       `json:"limit"`
	Remaining int       `json:"remaining"`
	Reset     Timestamp `json:"reset"`
}

Rate represents the rate limit for the Harvest API.

func ParseRate

func ParseRate(r *http.Response) Rate

ParseRate parses the rate limit headers from an HTTP response.

type RateLimitError

type RateLimitError struct {
	Rate     Rate
	Response *http.Response
	Message  string
}

RateLimitError occurs when the API rate limit is exceeded.

func (*RateLimitError) Error

func (e *RateLimitError) Error() string

type Receipt

type Receipt struct {
	URL         string `json:"url"`
	FileName    string `json:"file_name"`
	FileSize    int    `json:"file_size"`
	ContentType string `json:"content_type"`
}

Receipt represents a receipt attachment.

type ReportsService

type ReportsService struct {
	// contains filtered or unexported fields
}

ReportsService handles communication with the report related methods of the Harvest API.

func (*ReportsService) ExpenseReports

ExpenseReports retrieves expense reports.

func (*ReportsService) ProjectBudgetReports

ProjectBudgetReports retrieves project budget reports.

func (*ReportsService) TimeReports

TimeReports retrieves time reports.

func (*ReportsService) UninvoicedReports

UninvoicedReports retrieves uninvoiced reports.

type RestartRequest

type RestartRequest struct {
	ID int64 `json:"id"`
}

RestartRequest represents a request to restart a time entry.

type Role

type Role struct {
	ID        int64     `json:"id"`
	Name      string    `json:"name"`
	UserIDs   []int64   `json:"user_ids"`
	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updated_at"`
}

Role represents a role in Harvest.

type RoleCreateRequest

type RoleCreateRequest struct {
	Name    string  `json:"name"`
	UserIDs []int64 `json:"user_ids,omitempty"`
}

RoleCreateRequest represents a request to create a role.

type RoleList

type RoleList struct {
	Roles []Role `json:"roles"`
	Paginated[Role]
}

RoleList represents a list of roles.

type RoleListOptions

type RoleListOptions struct {
	ListOptions
}

RoleListOptions specifies optional parameters to the List method.

type RoleUpdateRequest

type RoleUpdateRequest struct {
	Name    string  `json:"name,omitempty"`
	UserIDs []int64 `json:"user_ids,omitempty"`
}

RoleUpdateRequest represents a request to update a role.

type RolesService

type RolesService struct {
	// contains filtered or unexported fields
}

RolesService handles communication with the role related methods of the Harvest API.

func (*RolesService) Create

func (s *RolesService) Create(ctx context.Context, role *RoleCreateRequest) (*Role, error)

Create creates a new role.

func (*RolesService) Delete

func (s *RolesService) Delete(ctx context.Context, roleID int64) error

Delete deletes a role.

func (*RolesService) Get

func (s *RolesService) Get(ctx context.Context, roleID int64) (*Role, error)

Get retrieves a specific role.

func (*RolesService) List

func (s *RolesService) List(ctx context.Context, opts *RoleListOptions) ([]Role, error)

List returns all roles across all pages.

func (*RolesService) ListPage added in v0.1.1

func (s *RolesService) ListPage(ctx context.Context, opts *RoleListOptions) (*RoleList, error)

ListPage returns a single page of roles.

func (*RolesService) Update

func (s *RolesService) Update(ctx context.Context, roleID int64, role *RoleUpdateRequest) (*Role, error)

Update updates a role.

type Task

type Task struct {
	ID                int64            `json:"id"`
	Name              string           `json:"name"`
	BillableByDefault bool             `json:"billable_by_default"`
	DefaultHourlyRate *decimal.Decimal `json:"default_hourly_rate,omitempty"`
	IsDefault         bool             `json:"is_default"`
	IsActive          bool             `json:"is_active"`
	CreatedAt         time.Time        `json:"created_at"`
	UpdatedAt         time.Time        `json:"updated_at"`
}

Task represents a task in Harvest.

type TaskAssignmentCreateRequest

type TaskAssignmentCreateRequest struct {
	TaskID     int64   `json:"task_id"`
	IsActive   *bool   `json:"is_active,omitempty"`
	Billable   *bool   `json:"billable,omitempty"`
	HourlyRate float64 `json:"hourly_rate,omitempty"`
	Budget     float64 `json:"budget,omitempty"`
}

TaskAssignmentCreateRequest represents a request to create a task assignment.

type TaskAssignmentList

type TaskAssignmentList struct {
	TaskAssignments []ProjectTaskAssignment `json:"task_assignments"`
	Paginated[ProjectTaskAssignment]
}

TaskAssignmentList represents a list of task assignments.

type TaskAssignmentListOptions

type TaskAssignmentListOptions struct {
	ListOptions
	IsActive     *bool  `url:"is_active,omitempty"`
	UpdatedSince string `url:"updated_since,omitempty"`
}

TaskAssignmentListOptions specifies optional parameters for listing task assignments.

type TaskAssignmentUpdateRequest

type TaskAssignmentUpdateRequest struct {
	IsActive   *bool   `json:"is_active,omitempty"`
	Billable   *bool   `json:"billable,omitempty"`
	HourlyRate float64 `json:"hourly_rate,omitempty"`
	Budget     float64 `json:"budget,omitempty"`
}

TaskAssignmentUpdateRequest represents a request to update a task assignment.

type TaskCreateRequest

type TaskCreateRequest struct {
	Name              string  `json:"name"`
	BillableByDefault *bool   `json:"billable_by_default,omitempty"`
	DefaultHourlyRate float64 `json:"default_hourly_rate,omitempty"`
	IsDefault         *bool   `json:"is_default,omitempty"`
	IsActive          *bool   `json:"is_active,omitempty"`
}

TaskCreateRequest represents a request to create a task.

type TaskList

type TaskList struct {
	Tasks []Task `json:"tasks"`
	Paginated[Task]
}

TaskList represents a list of tasks.

type TaskListOptions

type TaskListOptions struct {
	ListOptions
	IsActive     *bool  `url:"is_active,omitempty"`
	UpdatedSince string `url:"updated_since,omitempty"`
}

TaskListOptions specifies optional parameters to the List method.

type TaskUpdateRequest

type TaskUpdateRequest struct {
	Name              string  `json:"name,omitempty"`
	BillableByDefault *bool   `json:"billable_by_default,omitempty"`
	DefaultHourlyRate float64 `json:"default_hourly_rate,omitempty"`
	IsDefault         *bool   `json:"is_default,omitempty"`
	IsActive          *bool   `json:"is_active,omitempty"`
}

TaskUpdateRequest represents a request to update a task.

type TasksService

type TasksService struct {
	// contains filtered or unexported fields
}

TasksService handles communication with the task related methods of the Harvest API.

func (*TasksService) Create

func (s *TasksService) Create(ctx context.Context, task *TaskCreateRequest) (*Task, error)

Create creates a new task.

func (*TasksService) Delete

func (s *TasksService) Delete(ctx context.Context, taskID int64) error

Delete deletes a task.

func (*TasksService) Get

func (s *TasksService) Get(ctx context.Context, taskID int64) (*Task, error)

Get retrieves a specific task.

func (*TasksService) List

func (s *TasksService) List(ctx context.Context, opts *TaskListOptions) ([]Task, error)

List returns all tasks across all pages.

func (*TasksService) ListPage added in v0.1.1

func (s *TasksService) ListPage(ctx context.Context, opts *TaskListOptions) (*TaskList, error)

ListPage returns a single page of tasks.

func (*TasksService) Update

func (s *TasksService) Update(ctx context.Context, taskID int64, task *TaskUpdateRequest) (*Task, error)

Update updates a task.

type TimeEntriesService

type TimeEntriesService struct {
	// contains filtered or unexported fields
}

TimeEntriesService handles communication with the time entry related methods of the Harvest API.

func (*TimeEntriesService) CreateViaDuration

CreateViaDuration creates a new time entry via duration.

func (*TimeEntriesService) CreateViaStartEnd

CreateViaStartEnd creates a new time entry via start and end time.

func (*TimeEntriesService) Delete

func (s *TimeEntriesService) Delete(ctx context.Context, timeEntryID int64) error

Delete deletes a time entry.

func (*TimeEntriesService) DeleteExternalReference

func (s *TimeEntriesService) DeleteExternalReference(ctx context.Context, timeEntryID int64) error

DeleteExternalReference deletes an external reference from a time entry.

func (*TimeEntriesService) Get

func (s *TimeEntriesService) Get(ctx context.Context, timeEntryID int64) (*TimeEntry, error)

Get retrieves a specific time entry.

func (*TimeEntriesService) List

List returns all time entries across all pages.

func (*TimeEntriesService) ListPage added in v0.1.1

ListPage returns a single page of time entries.

func (*TimeEntriesService) Restart

func (s *TimeEntriesService) Restart(ctx context.Context, timeEntryID int64) (*TimeEntry, error)

Restart restarts a stopped time entry.

func (*TimeEntriesService) Stop

func (s *TimeEntriesService) Stop(ctx context.Context, timeEntryID int64) (*TimeEntry, error)

Stop stops a running time entry.

func (*TimeEntriesService) Update

func (s *TimeEntriesService) Update(ctx context.Context, timeEntryID int64, entry *TimeEntryUpdateRequest) (*TimeEntry, error)

Update updates a time entry.

type TimeEntry

type TimeEntry struct {
	ID                int64                  `json:"id"`
	SpentDate         Date                   `json:"spent_date"`
	User              *User                  `json:"user"`
	Client            *Client                `json:"client"`
	Project           *Project               `json:"project"`
	Task              *Task                  `json:"task"`
	UserAssignment    *ProjectUserAssignment `json:"user_assignment"`
	TaskAssignment    *ProjectTaskAssignment `json:"task_assignment"`
	Invoice           *Invoice               `json:"invoice,omitempty"`
	Hours             decimal.Decimal        `json:"hours"`
	RoundedHours      decimal.Decimal        `json:"rounded_hours"`
	Notes             string                 `json:"notes,omitempty"`
	IsLocked          bool                   `json:"is_locked"`
	LockedReason      string                 `json:"locked_reason,omitempty"`
	IsClosed          bool                   `json:"is_closed"`
	IsBilled          bool                   `json:"is_billed"`
	TimerStartedAt    *time.Time             `json:"timer_started_at,omitempty"`
	StartedTime       string                 `json:"started_time,omitempty"`
	EndedTime         string                 `json:"ended_time,omitempty"`
	IsRunning         bool                   `json:"is_running"`
	Billable          bool                   `json:"billable"`
	Budgeted          bool                   `json:"budgeted"`
	BillableRate      *decimal.Decimal       `json:"billable_rate,omitempty"`
	CostRate          *decimal.Decimal       `json:"cost_rate,omitempty"`
	CreatedAt         time.Time              `json:"created_at"`
	UpdatedAt         time.Time              `json:"updated_at"`
	ExternalReference *ExternalReference     `json:"external_reference,omitempty"`
}

TimeEntry represents a time entry in Harvest.

type TimeEntryCreateViaDurationRequest

type TimeEntryCreateViaDurationRequest struct {
	ProjectID         int64                     `json:"project_id"`
	TaskID            int64                     `json:"task_id"`
	SpentDate         string                    `json:"spent_date"`
	Hours             float64                   `json:"hours"`
	UserID            int64                     `json:"user_id,omitempty"`
	Notes             string                    `json:"notes,omitempty"`
	ExternalReference *ExternalReferenceRequest `json:"external_reference,omitempty"`
}

TimeEntryCreateViaDurationRequest represents a request to create a time entry via duration.

type TimeEntryCreateViaStartEndRequest

type TimeEntryCreateViaStartEndRequest struct {
	ProjectID         int64                     `json:"project_id"`
	TaskID            int64                     `json:"task_id"`
	SpentDate         string                    `json:"spent_date"`
	StartedTime       string                    `json:"started_time"`
	EndedTime         string                    `json:"ended_time"`
	UserID            int64                     `json:"user_id,omitempty"`
	Notes             string                    `json:"notes,omitempty"`
	ExternalReference *ExternalReferenceRequest `json:"external_reference,omitempty"`
}

TimeEntryCreateViaStartEndRequest represents a request to create a time entry via start and end time.

type TimeEntryList

type TimeEntryList struct {
	TimeEntries []TimeEntry `json:"time_entries"`
	Paginated[TimeEntry]
}

TimeEntryList represents a list of time entries.

type TimeEntryListOptions

type TimeEntryListOptions struct {
	ListOptions
	UserID              int64  `url:"user_id,omitempty"`
	ClientID            int64  `url:"client_id,omitempty"`
	ProjectID           int64  `url:"project_id,omitempty"`
	TaskID              int64  `url:"task_id,omitempty"`
	ExternalReferenceID string `url:"external_reference_id,omitempty"`
	IsBilled            *bool  `url:"is_billed,omitempty"`
	IsRunning           *bool  `url:"is_running,omitempty"`
	ApprovalStatus      string `url:"approval_status,omitempty"`
	UpdatedSince        string `url:"updated_since,omitempty"`
	From                string `url:"from,omitempty"`
	To                  string `url:"to,omitempty"`
}

TimeEntryListOptions specifies optional parameters to the List method.

type TimeEntryUpdateRequest

type TimeEntryUpdateRequest struct {
	ProjectID         int64                     `json:"project_id,omitempty"`
	TaskID            int64                     `json:"task_id,omitempty"`
	SpentDate         string                    `json:"spent_date,omitempty"`
	StartedTime       string                    `json:"started_time,omitempty"`
	EndedTime         string                    `json:"ended_time,omitempty"`
	Hours             float64                   `json:"hours,omitempty"`
	Notes             string                    `json:"notes,omitempty"`
	ExternalReference *ExternalReferenceRequest `json:"external_reference,omitempty"`
}

TimeEntryUpdateRequest represents a request to update a time entry.

type TimeReport

type TimeReport struct {
	ClientID       int64           `json:"client_id"`
	ClientName     string          `json:"client_name"`
	ProjectID      int64           `json:"project_id"`
	ProjectName    string          `json:"project_name"`
	TaskID         int64           `json:"task_id"`
	TaskName       string          `json:"task_name"`
	UserID         int64           `json:"user_id"`
	UserName       string          `json:"user_name"`
	WeeklyCapacity int             `json:"weekly_capacity"`
	AvatarURL      string          `json:"avatar_url"`
	IsContractor   bool            `json:"is_contractor"`
	TotalHours     decimal.Decimal `json:"total_hours"`
	BillableHours  decimal.Decimal `json:"billable_hours"`
	Currency       string          `json:"currency"`
	BillableAmount decimal.Decimal `json:"billable_amount"`
}

TimeReport represents a time report entry.

type TimeReportResults

type TimeReportResults struct {
	Results      []TimeReport     `json:"results"`
	PerPage      int              `json:"per_page"`
	TotalPages   int              `json:"total_pages"`
	TotalEntries int              `json:"total_entries"`
	NextPage     *int             `json:"next_page"`
	PreviousPage *int             `json:"previous_page"`
	Page         int              `json:"page"`
	Links        *PaginationLinks `json:"links"`
}

TimeReportResults represents time report results.

type TimeReportsOptions

type TimeReportsOptions struct {
	From           string `url:"from"`
	To             string `url:"to"`
	ClientID       int64  `url:"client_id,omitempty"`
	ProjectID      int64  `url:"project_id,omitempty"`
	TaskID         int64  `url:"task_id,omitempty"`
	UserID         int64  `url:"user_id,omitempty"`
	IsBilled       *bool  `url:"is_billed,omitempty"`
	IsRunning      *bool  `url:"is_running,omitempty"`
	OnlyBillable   *bool  `url:"only_billable,omitempty"`
	OnlyUnbillable *bool  `url:"only_unbillable,omitempty"`
	Page           int    `url:"page,omitempty"`
	PerPage        int    `url:"per_page,omitempty"`
}

TimeReportsOptions specifies optional parameters for time reports.

type Timestamp

type Timestamp struct {
	time.Time
}

Timestamp represents a time that can be unmarshalled from a JSON number.

func (*Timestamp) UnmarshalJSON

func (t *Timestamp) UnmarshalJSON(data []byte) error

UnmarshalJSON implements the json.Unmarshaler interface.

type UninvoicedReport

type UninvoicedReport struct {
	ClientID           int64           `json:"client_id"`
	ClientName         string          `json:"client_name"`
	ProjectID          int64           `json:"project_id"`
	ProjectName        string          `json:"project_name"`
	Currency           string          `json:"currency"`
	TotalHours         decimal.Decimal `json:"total_hours"`
	UninvoicedHours    decimal.Decimal `json:"uninvoiced_hours"`
	UninvoicedExpenses decimal.Decimal `json:"uninvoiced_expenses"`
	UninvoicedAmount   decimal.Decimal `json:"uninvoiced_amount"`
}

UninvoicedReport represents an uninvoiced report entry.

type UninvoicedReportOptions

type UninvoicedReportOptions struct {
	From      string `url:"from"`
	To        string `url:"to"`
	ClientID  int64  `url:"client_id,omitempty"`
	ProjectID int64  `url:"project_id,omitempty"`
	Page      int    `url:"page,omitempty"`
	PerPage   int    `url:"per_page,omitempty"`
}

UninvoicedReportOptions specifies optional parameters for uninvoiced reports.

type UninvoicedReportResults

type UninvoicedReportResults struct {
	Results      []UninvoicedReport `json:"results"`
	PerPage      int                `json:"per_page"`
	TotalPages   int                `json:"total_pages"`
	TotalEntries int                `json:"total_entries"`
	NextPage     *int               `json:"next_page"`
	PreviousPage *int               `json:"previous_page"`
	Page         int                `json:"page"`
	Links        *PaginationLinks   `json:"links"`
}

UninvoicedReportResults represents uninvoiced report results.

type User

type User struct {
	ID                           int64            `json:"id"`
	FirstName                    string           `json:"first_name"`
	LastName                     string           `json:"last_name"`
	Email                        string           `json:"email"`
	Telephone                    string           `json:"telephone,omitempty"`
	Timezone                     string           `json:"timezone"`
	HasAccessToAllFutureProjects bool             `json:"has_access_to_all_future_projects"`
	IsContractor                 bool             `json:"is_contractor"`
	IsActive                     bool             `json:"is_active"`
	WeeklyCapacity               int              `json:"weekly_capacity"`
	DefaultHourlyRate            *decimal.Decimal `json:"default_hourly_rate,omitempty"`
	CostRate                     *decimal.Decimal `json:"cost_rate,omitempty"`
	Roles                        []string         `json:"roles"`
	AvatarURL                    string           `json:"avatar_url"`
	CreatedAt                    time.Time        `json:"created_at"`
	UpdatedAt                    time.Time        `json:"updated_at"`
}

User represents a user in Harvest.

type UserAssignmentCreateRequest

type UserAssignmentCreateRequest struct {
	UserID           int64   `json:"user_id"`
	IsActive         *bool   `json:"is_active,omitempty"`
	IsProjectManager *bool   `json:"is_project_manager,omitempty"`
	UseDefaultRates  *bool   `json:"use_default_rates,omitempty"`
	HourlyRate       float64 `json:"hourly_rate,omitempty"`
	Budget           float64 `json:"budget,omitempty"`
}

UserAssignmentCreateRequest represents a request to create a user assignment.

type UserAssignmentList

type UserAssignmentList struct {
	UserAssignments []ProjectUserAssignment `json:"user_assignments"`
	Paginated[ProjectUserAssignment]
}

UserAssignmentList represents a list of user assignments.

type UserAssignmentListOptions

type UserAssignmentListOptions struct {
	ListOptions
	UserID       int64  `url:"user_id,omitempty"`
	IsActive     *bool  `url:"is_active,omitempty"`
	UpdatedSince string `url:"updated_since,omitempty"`
}

UserAssignmentListOptions specifies optional parameters for listing user assignments.

type UserAssignmentUpdateRequest

type UserAssignmentUpdateRequest struct {
	IsActive         *bool   `json:"is_active,omitempty"`
	IsProjectManager *bool   `json:"is_project_manager,omitempty"`
	UseDefaultRates  *bool   `json:"use_default_rates,omitempty"`
	HourlyRate       float64 `json:"hourly_rate,omitempty"`
	Budget           float64 `json:"budget,omitempty"`
}

UserAssignmentUpdateRequest represents a request to update a user assignment.

type UserCreateRequest

type UserCreateRequest struct {
	FirstName                    string   `json:"first_name"`
	LastName                     string   `json:"last_name"`
	Email                        string   `json:"email"`
	Telephone                    string   `json:"telephone,omitempty"`
	Timezone                     string   `json:"timezone,omitempty"`
	HasAccessToAllFutureProjects *bool    `json:"has_access_to_all_future_projects,omitempty"`
	IsContractor                 *bool    `json:"is_contractor,omitempty"`
	IsActive                     *bool    `json:"is_active,omitempty"`
	WeeklyCapacity               int      `json:"weekly_capacity,omitempty"`
	DefaultHourlyRate            float64  `json:"default_hourly_rate,omitempty"`
	CostRate                     float64  `json:"cost_rate,omitempty"`
	Roles                        []string `json:"roles,omitempty"`
}

UserCreateRequest represents a request to create a user.

type UserList

type UserList struct {
	Users []User `json:"users"`
	Paginated[User]
}

UserList represents a list of users.

type UserListOptions

type UserListOptions struct {
	ListOptions
	IsActive     *bool  `url:"is_active,omitempty"`
	UpdatedSince string `url:"updated_since,omitempty"`
}

UserListOptions specifies optional parameters to the List method.

type UserProjectAssignmentList

type UserProjectAssignmentList struct {
	ProjectAssignments []ProjectUserAssignment `json:"project_assignments"`
	Paginated[ProjectUserAssignment]
}

UserProjectAssignmentList represents a list of user project assignments.

type UserProjectAssignmentListOptions

type UserProjectAssignmentListOptions struct {
	ListOptions
	UpdatedSince string `url:"updated_since,omitempty"`
}

UserProjectAssignmentListOptions specifies optional parameters for listing user project assignments.

type UserUpdateRequest

type UserUpdateRequest struct {
	FirstName                    string   `json:"first_name,omitempty"`
	LastName                     string   `json:"last_name,omitempty"`
	Email                        string   `json:"email,omitempty"`
	Telephone                    string   `json:"telephone,omitempty"`
	Timezone                     string   `json:"timezone,omitempty"`
	HasAccessToAllFutureProjects *bool    `json:"has_access_to_all_future_projects,omitempty"`
	IsContractor                 *bool    `json:"is_contractor,omitempty"`
	IsActive                     *bool    `json:"is_active,omitempty"`
	WeeklyCapacity               int      `json:"weekly_capacity,omitempty"`
	DefaultHourlyRate            float64  `json:"default_hourly_rate,omitempty"`
	CostRate                     float64  `json:"cost_rate,omitempty"`
	Roles                        []string `json:"roles,omitempty"`
}

UserUpdateRequest represents a request to update a user.

type UsersService

type UsersService struct {
	// contains filtered or unexported fields
}

UsersService handles communication with the user related methods of the Harvest API.

func (*UsersService) Create

func (s *UsersService) Create(ctx context.Context, user *UserCreateRequest) (*User, error)

Create creates a new user.

func (*UsersService) Delete

func (s *UsersService) Delete(ctx context.Context, userID int64) error

Delete archives a user.

func (*UsersService) Get

func (s *UsersService) Get(ctx context.Context, userID int64) (*User, error)

Get retrieves a specific user.

func (*UsersService) List

func (s *UsersService) List(ctx context.Context, opts *UserListOptions) ([]User, error)

List returns all users across all pages. This endpoint uses cursor-based pagination.

func (*UsersService) ListMyProjectAssignments

func (s *UsersService) ListMyProjectAssignments(ctx context.Context, opts *UserProjectAssignmentListOptions) ([]ProjectUserAssignment, error)

ListMyProjectAssignments returns all project assignments for the currently authenticated user across all pages.

func (*UsersService) ListMyProjectAssignmentsPage added in v0.1.1

func (s *UsersService) ListMyProjectAssignmentsPage(ctx context.Context, opts *UserProjectAssignmentListOptions) (*UserProjectAssignmentList, error)

ListMyProjectAssignmentsPage returns a single page of project assignments for the currently authenticated user.

func (*UsersService) ListPage added in v0.1.1

func (s *UsersService) ListPage(ctx context.Context, opts *UserListOptions) (*UserList, error)

ListPage returns a single page of users.

func (*UsersService) ListProjectAssignments

func (s *UsersService) ListProjectAssignments(ctx context.Context, userID int64, opts *UserProjectAssignmentListOptions) ([]ProjectUserAssignment, error)

ListProjectAssignments returns all project assignments for a user across all pages. This endpoint uses cursor-based pagination.

func (*UsersService) ListProjectAssignmentsPage added in v0.1.1

func (s *UsersService) ListProjectAssignmentsPage(ctx context.Context, userID int64, opts *UserProjectAssignmentListOptions) (*UserProjectAssignmentList, error)

ListProjectAssignmentsPage returns a single page of project assignments for a user.

func (*UsersService) Me

func (s *UsersService) Me(ctx context.Context) (*User, error)

Me retrieves the currently authenticated user.

func (*UsersService) Update

func (s *UsersService) Update(ctx context.Context, userID int64, user *UserUpdateRequest) (*User, error)

Update updates a user.

Jump to

Keyboard shortcuts

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