{"id":31942899,"url":"https://github.com/joefitzgerald/harvest","last_synced_at":"2025-10-14T09:46:39.544Z","repository":{"id":314625909,"uuid":"1054424525","full_name":"joefitzgerald/harvest","owner":"joefitzgerald","description":"A Go client for the Harvest API","archived":false,"fork":false,"pushed_at":"2025-09-10T20:38:25.000Z","size":62,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-09-13T18:14:47.448Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/joefitzgerald.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-10T20:16:54.000Z","updated_at":"2025-09-10T20:34:45.000Z","dependencies_parsed_at":"2025-09-13T18:24:59.982Z","dependency_job_id":null,"html_url":"https://github.com/joefitzgerald/harvest","commit_stats":null,"previous_names":["joefitzgerald/harvest"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/joefitzgerald/harvest","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joefitzgerald%2Fharvest","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joefitzgerald%2Fharvest/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joefitzgerald%2Fharvest/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joefitzgerald%2Fharvest/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/joefitzgerald","download_url":"https://codeload.github.com/joefitzgerald/harvest/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joefitzgerald%2Fharvest/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279018574,"owners_count":26086404,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-14T02:00:06.444Z","response_time":60,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-10-14T09:45:06.646Z","updated_at":"2025-10-14T09:46:39.534Z","avatar_url":"https://github.com/joefitzgerald.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Harvest API v2 Go Client [![](https://godoc.org/github.com/joefitzgerald/harvest?status.svg)](https://godoc.org/github.com/joefitzgerald/harvest)\n\n[![Go Reference](https://pkg.go.dev/badge/github.com/joefitzgerald/harvest.svg)](https://pkg.go.dev/github.com/joefitzgerald/harvest)\n[![Go Report Card](https://goreportcard.com/badge/github.com/joefitzgerald/harvest)](https://goreportcard.com/report/github.com/joefitzgerald/harvest)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA modern, comprehensive Go client library for the [Harvest API v2](https://help.getharvest.com/api-v2/). This library provides complete coverage of all Harvest API v2 endpoints with a clean, type-safe interface.\n\n## Why This Library?\n\n- **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\n- **Modern Go**: Uses Go 1.25+ generics to reduce code duplication and provide a cleaner API\n- **Complete Coverage**: Implements all 69+ endpoints from the Harvest API v2\n- **Type Safety**: Strongly typed request and response models with proper JSON marshaling\n- **Production Ready**: Automatic rate limiting, context support, and comprehensive error handling\n\n\u003e **Note**: If you're looking for a Harvest API v1 client, see [adlio/harvest](https://github.com/adlio/harvest). However, be aware that Harvest API v1 is deprecated and that library hasn't been updated since 2018.\n\n## Features\n\n- ✅ **Complete API Coverage**: All Harvest API v2 endpoints implemented\n- ✅ **Type Safety**: Strongly typed request and response models\n- ✅ **Generic CRUD Operations**: Leverages Go generics for reduced code duplication\n- ✅ **Automatic Pagination**: Built-in pagination support with iterator pattern\n- ✅ **Rate Limiting**: Automatic rate limit detection and error handling\n- ✅ **Decimal Precision**: Uses `shopspring/decimal` for accurate financial calculations\n- ✅ **Context Support**: All methods accept `context.Context` for cancellation\n- ✅ **Configurable User-Agent**: Required by Harvest API for identification\n\n## Installation\n\n```bash\ngo get github.com/joefitzgerald/harvest\n```\n\nRequires Go 1.25 or later.\n\n## Quick Start\n\n```go\npackage main\n\nimport (\n    \"context\"\n    \"fmt\"\n    \"log\"\n    \"os\"\n\n    \"github.com/joefitzgerald/harvest\"\n)\n\nfunc main() {\n    // Set environment variables:\n    // export HARVEST_ACCESS_TOKEN=\"your-token\"\n    // export HARVEST_ACCOUNT_ID=\"your-account-id\"\n\n    // Create client with required User-Agent\n    client, err := harvest.New(\"MyApp (contact@example.com)\")\n    if err != nil {\n        log.Fatal(err)\n    }\n\n    ctx := context.Background()\n\n    // Get company info\n    company, err := client.Company.Get(ctx)\n    if err != nil {\n        log.Fatal(err)\n    }\n    fmt.Printf(\"Company: %s\\n\", company.Name)\n\n    // List active projects\n    projects, err := client.Projects.List(ctx, \u0026harvest.ProjectListOptions{\n        ListOptions: harvest.ListOptions{\n            Page:    1,\n            PerPage: 100,\n        },\n        IsActive: \u0026[]bool{true}[0],\n    })\n    if err != nil {\n        log.Fatal(err)\n    }\n\n    for _, project := range projects.Projects {\n        fmt.Printf(\"Project: %s (Client: %s)\\n\", project.Name, project.Client.Name)\n    }\n}\n```\n\n## Authentication\n\nThe client requires two environment variables:\n\n- `HARVEST_ACCESS_TOKEN`: Your personal access token from Harvest\n- `HARVEST_ACCOUNT_ID`: Your Harvest account ID\n\nTo get these:\n\n1. Log in to Harvest\n2. Go to [Developers \u003e Personal Access Tokens](https://id.getharvest.com/developers)\n3. Create a new token\n4. Note your Account ID from the same page\n\nYou can also create a client with explicit credentials:\n\n```go\nclient, err := harvest.NewWithConfig(\n    \"your-access-token\",\n    \"your-account-id\",\n    \"MyApp (contact@example.com)\",\n    nil, // optional custom HTTP client\n)\n```\n\n## User-Agent Requirement\n\nHarvest requires a User-Agent header that includes:\n\n1. The name of your application\n2. A link to your application or email address\n\nExamples:\n\n- `\"MyTimeTracker (https://example.com)\"`\n- `\"John's Integration (john@example.com)\"`\n\n## Available Services\n\n### Core Resources\n\n- **Company**: Get company information\n- **Clients**: Manage clients and contacts\n- **Projects**: Manage projects and assignments\n- **Users**: Manage users and their assignments\n- **Tasks**: Manage tasks\n- **TimeEntries**: Track time entries\n\n### Financial Resources\n\n- **Invoices**: Create and manage invoices\n- **Estimates**: Create and manage estimates\n- **Expenses**: Track expenses and expense categories\n\n### Reporting\n\n- **Reports**: Access various reports\n  - Time reports\n  - Expense reports\n  - Uninvoiced reports\n  - Project budget reports\n\n### Administration\n\n- **Roles**: Manage user roles\n\n## Examples\n\n### Time Entry Management\n\n```go\n// Create time entry via duration\nentry, err := client.TimeEntries.CreateViaDuration(ctx, \u0026harvest.TimeEntryCreateViaDurationRequest{\n    ProjectID:  12345,\n    TaskID:     67890,\n    SpentDate:  \"2025-01-10\",\n    Hours:      2.5,\n    Notes:      \"Working on feature X\",\n})\n\n// Start a timer\ntimer, err := client.TimeEntries.CreateViaStartEndTime(ctx, \u0026harvest.TimeEntryCreateViaStartEndTimeRequest{\n    ProjectID: 12345,\n    TaskID:    67890,\n    SpentDate: \"2025-01-10\",\n})\n\n// Stop the timer\nstopped, err := client.TimeEntries.Stop(ctx, timer.ID)\n```\n\n### Project Management\n\n```go\n// Create a project\nproject, err := client.Projects.Create(ctx, \u0026harvest.ProjectCreateRequest{\n    ClientID:   123,\n    Name:       \"New Website\",\n    IsBillable: \u0026[]bool{true}[0],\n    BillBy:     \"project\",\n    Budget:     50000,\n})\n\n// Assign user to project\nassignment, err := client.Projects.CreateUserAssignment(ctx, project.ID,\n    \u0026harvest.UserAssignmentCreateRequest{\n        UserID:           456,\n        IsProjectManager: \u0026[]bool{true}[0],\n        HourlyRate:       150.00,\n    })\n\n// Update project budget\nupdated, err := client.Projects.Update(ctx, project.ID, \u0026harvest.ProjectUpdateRequest{\n    Budget: 75000,\n})\n```\n\n### Pagination\n\n```go\n// Manual pagination\nopts := \u0026harvest.ProjectListOptions{\n    ListOptions: harvest.ListOptions{\n        Page:    1,\n        PerPage: 50,\n    },\n}\n\nfor {\n    projects, err := client.Projects.List(ctx, opts)\n    if err != nil {\n        return err\n    }\n\n    for _, project := range projects.Projects {\n        // Process project\n    }\n\n    if !projects.HasNextPage() {\n        break\n    }\n    opts.Page = *projects.NextPage\n}\n```\n\n### Error Handling\n\n```go\nprojects, err := client.Projects.List(ctx, nil)\nif err != nil {\n    switch e := err.(type) {\n    case *harvest.RateLimitError:\n        fmt.Printf(\"Rate limit exceeded. Resets at: %s\\n\", e.Rate.Reset)\n        // Wait and retry\n    case *harvest.ErrorResponse:\n        fmt.Printf(\"API error: %s\\n\", e.Message)\n    default:\n        fmt.Printf(\"Error: %v\\n\", err)\n    }\n}\n```\n\n## API Coverage\n\nThis library provides complete coverage of the Harvest API v2. All endpoints documented in the [official API documentation](https://help.getharvest.com/api-v2/) are implemented.\n\n### Implemented Endpoints\n\n| Resource                     | Operations                                       |\n| ---------------------------- | ------------------------------------------------ |\n| **Company**                  | Get                                              |\n| **Clients**                  | List, Get, Create, Update, Delete                |\n| **Contacts**                 | List, Get, Create, Update, Delete                |\n| **Projects**                 | List, Get, Create, Update, Delete                |\n| **Project User Assignments** | List, Get, Create, Update, Delete                |\n| **Project Task Assignments** | List, Get, Create, Update, Delete                |\n| **Tasks**                    | List, Get, Create, Update, Delete                |\n| **Users**                    | List, Get, Create, Update, Delete, Get Current   |\n| **User Project Assignments** | List, Get Current                                |\n| **User Billable Rates**      | List, Get, Create, Update, Delete                |\n| **User Cost Rates**          | List, Get, Create, Update, Delete                |\n| **Time Entries**             | List, Get, Create, Update, Delete, Restart, Stop |\n| **Invoices**                 | List, Get, Create, Update, Delete, Send          |\n| **Invoice Line Items**       | Create, Update, Delete                           |\n| **Invoice Messages**         | List, Get, Create, Delete                        |\n| **Invoice Payments**         | List, Get, Create, Delete                        |\n| **Estimates**                | List, Get, Create, Update, Delete, Send          |\n| **Estimate Line Items**      | Create, Update, Delete                           |\n| **Estimate Messages**        | List, Get, Create, Delete                        |\n| **Expenses**                 | List, Get, Create, Update, Delete                |\n| **Expense Categories**       | List, Get, Create, Update, Delete                |\n| **Roles**                    | List, Get, Create, Update, Delete                |\n| **Reports**                  | Time, Expenses, Uninvoiced, Project Budget       |\n\n## Development\n\n### Building\n\n```bash\n# Download dependencies\ngo mod download\n\n# Build\ngo build ./...\n\n# Run tests\ngo test -v ./...\n\n# Lint\ngolangci-lint run ./...\n```\n\n### Contributing\n\nContributions 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.\n\nWhen adding new endpoints:\n\n1. Add types to `types.go`\n2. Add service methods following the existing pattern\n3. Use generics for standard CRUD operations\n4. Ensure proper error handling\n5. Add comprehensive tests\n\n## License\n\nMIT License - see [LICENSE](LICENSE) file for details.\n\n## Generated with Claude Code\n\nThe initial version of this client library was generated using [Claude Code (Opus 4.1)](https://claude.ai/code).\n\n## Related Projects\n\n- [adlio/harvest](https://github.com/adlio/harvest) - Harvest API v1 client (deprecated API, unmaintained)\n- [Harvest API Documentation](https://help.getharvest.com/api-v2/) - Official API documentation\n- [Harvest Postman Collection](https://www.postman.com/harvest-api) - Official Postman collection\n\n## Support\n\nFor issues, questions, or contributions, please use the [GitHub issue tracker](https://github.com/joefitzgerald/harvest/issues).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoefitzgerald%2Fharvest","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjoefitzgerald%2Fharvest","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoefitzgerald%2Fharvest/lists"}