# Harvest on boxd

> Harvest is a time-tracking and invoicing tool designed for teams and freelancers, helping them log billable hours, manage projects, and streamline payments.

- Page: https://boxd.sh/integrations/harvest/
- CLI: `run harvest` (57 commands, 57 marked common)
- SDK: `import { harvest } from "@boxd/run"`; every parameter and response type is at `@boxd/run/harvest`
- Triggers: none
- Connect: `run auth harvest` (Sign in with Harvest), or https://app.boxd.sh/integrations/detail/harvest
- All integrations: https://boxd.sh/integrations/ (Markdown: https://boxd.sh/integrations/index.md)

## From the shell

```sh
run auth harvest      # once: prints a link to connect your account
run harvest           # list its commands
run harvest list-tasks
```

Parameters are flags (`--flag value`); object and array parameters take a JSON string. Output is YAML, or JSON with `--json`. Calls use your own connection; `--scope <name>` uses a connection shared with your team.

## From a script

```ts
import { every, harvest } from "@boxd/run";

every("1 hour", async () => {
  const result = await harvest.listTasks({});
  console.log(result);
});
```

Run it with `run harvest.run.ts`. Harvest has no triggers; `every()` polls on a schedule, keeps the script running as a job, and wakes the machine when it is due.

## Commands

Required flags are listed; `run harvest <command> --help` lists the optional ones. "common" marks what `run harvest` shows without `--all`.

| Command | SDK method | Required flags | Optional | Description |
|---|---|---|---|---|
| `create-client` ·common | `harvest.createClient()` | `--name` | 3 | Create a new client |
| `create-client-contact` ·common | `harvest.createClientContact()` | `--client-id` `--first-name` | 6 | Create a new client contact |
| `create-estimate` ·common | `harvest.createEstimate()` | `--client-id` | 10 | Create a new estimate |
| `create-estimate-item-category` ·common | `harvest.createEstimateItemCategory()` | `--name` | 0 | Create a new estimate item category in Harvest |
| `create-estimate-message` ·common | `harvest.createEstimateMessage()` | `--estimate-id` | 5 | Create a new message for an estimate |
| `create-expense` ·common | `harvest.createExpense()` | `--expense-category-id` `--project-id` `--spent-date` | 6 | Create a new expense entry |
| `create-invoice` ·common | `harvest.createInvoice()` | `--client-id` `--line-items` | 11 | Create a new invoice |
| `create-invoice-item-category` ·common | `harvest.createInvoiceItemCategory()` | `--name` | 0 | Create a new invoice item category |
| `create-invoice-message` ·common | `harvest.createInvoiceMessage()` | `--invoice-id` | 8 | Creates a new message for an invoice in Harvest |
| `create-invoice-payment` ·common | `harvest.createInvoicePayment()` | `--amount` `--invoice-id` | 4 | Create a new payment on an invoice |
| `create-project` ·common | `harvest.createProject()` | `--bill-by` `--budget-by` `--client-id` `--is-billable` `--name` | 15 | Create a new project in Harvest |
| `create-task` ·common | `harvest.createTask()` | `--name` | 4 | Creates a new task in Harvest |
| `create-time-entry` ·common | `harvest.createTimeEntry()` | `--project-id` `--spent-date` `--task-id` | 6 | Create a new time entry |
| `create-user` ·common | `harvest.createUser()` | `--email` `--first-name` `--last-name` | 9 | Creates a new user in Harvest and sends an invitation email to the specified address |
| `delete-client` ·common | `harvest.deleteClient()` | `--client-id` | 0 | Delete a client |
| `delete-client-contact` ·common | `harvest.deleteClientContact()` | `--contact-id` | 0 | Permanently deletes a client contact from Harvest |
| `delete-estimate` ·common | `harvest.deleteEstimate()` | `--estimate-id` | 0 | Delete an estimate |
| `delete-estimate-message` ·common | `harvest.deleteEstimateMessage()` | `--estimate-id` `--message-id` | 0 | Delete an estimate message |
| `delete-invoice` ·common | `harvest.deleteInvoice()` | `--invoice-id` | 0 | Delete an invoice from Harvest |
| `delete-invoice-item-category` ·common | `harvest.deleteInvoiceItemCategory()` | `--invoice-item-category-id` | 0 | Delete an invoice item category from Harvest |
| `delete-invoice-message` ·common | `harvest.deleteInvoiceMessage()` | `--invoice-id` `--message-id` | 0 | Delete a message from an invoice |
| `delete-invoice-payment` ·common | `harvest.deleteInvoicePayment()` | `--invoice-id` `--payment-id` | 0 | Delete an invoice payment |
| `delete-project` ·common | `harvest.deleteProject()` | `--project-id` | 0 | Delete a project |
| `delete-task` ·common | `harvest.deleteTask()` | `--task-id` | 0 | Delete a task |
| `delete-time-entry` ·common | `harvest.deleteTimeEntry()` | `--time-entry-id` | 0 | Delete a time entry |
| `delete-user` ·common | `harvest.deleteUser()` | `--user-id` | 0 | Delete a user |
| `get-client` ·common | `harvest.getClient()` | `--client-id` | 0 | Retrieves a specific client by ID from Harvest |
| `get-company-info` ·common | `harvest.getCompanyInfo()` | — | 0 | Retrieves detailed information about the company associated with the authenticated Harvest account |
| `get-estimate` ·common | `harvest.getEstimate()` | `--estimate-id` | 0 | Retrieve a specific estimate by ID |
| `get-invoice` ·common | `harvest.getInvoice()` | `--invoice-id` | 0 | Retrieve a specific invoice by ID |
| `get-project` ·common | `harvest.getProject()` | `--project-id` | 0 | Retrieve a specific Harvest project by ID |
| `get-task` ·common | `harvest.getTask()` | `--task-id` | 0 | Retrieve a specific task by ID |
| `get-time-entry` ·common | `harvest.getTimeEntry()` | `--time-entry-id` | 0 | Retrieve a single time entry by ID |
| `get-user` ·common | `harvest.getUser()` | `--user-id` | 0 | Retrieve a specific user by ID |
| `list-client-contacts` ·common | `harvest.listClientContacts()` | — | 4 | List client contacts |
| `list-clients` ·common | `harvest.listClients()` | — | 4 | List clients |
| `list-estimate-messages` ·common | `harvest.listEstimateMessages()` | `--estimate-id` | 3 | Lists all messages associated with a specific estimate in Harvest |
| `list-expense-categories` ·common | `harvest.listExpenseCategories()` | — | 4 | List expense categories |
| `list-invoice-item-categories` ·common | `harvest.listInvoiceItemCategories()` | — | 3 | Retrieve invoice item categories |
| `list-invoice-messages` ·common | `harvest.listInvoiceMessages()` | `--invoice-id` | 3 | List messages associated with a given invoice |
| `list-invoice-payments` ·common | `harvest.listInvoicePayments()` | `--invoice-id` | 3 | List all payments recorded for a specific invoice |
| `list-invoices` ·common | `harvest.listInvoices()` | — | 8 | List invoices |
| `list-projects` ·common | `harvest.listProjects()` | — | 4 | List projects |
| `list-tasks` ·common | `harvest.listTasks()` | — | 5 | List tasks |
| `list-time-entries` ·common | `harvest.listTimeEntries()` | — | 12 | Retrieve a list of time entries |
| `list-users` ·common | `harvest.listUsers()` | — | 4 | List users |
| `update-client` ·common | `harvest.updateClient()` | `--client-id` | 4 | Update an existing client |
| `update-client-contact` ·common | `harvest.updateClientContact()` | `--contact-id` | 6 | Update a client contact |
| `update-company-info` ·common | `harvest.updateCompanyInfo()` | — | 2 | Updates company time tracking settings in Harvest |
| `update-estimate` ·common | `harvest.updateEstimate()` | `--estimate-id` | 11 | Update an existing estimate |
| `update-estimate-item-category` ·common | `harvest.updateEstimateItemCategory()` | `--estimate-item-category-id` | 1 | Updates an existing estimate item category's name in Harvest |
| `update-expense` ·common | `harvest.updateExpense()` | `--expense-id` | 8 | Update an existing expense |
| `update-invoice` ·common | `harvest.updateInvoice()` | `--invoice-id` | 16 | Update an existing invoice |
| `update-project` ·common | `harvest.updateProject()` | `--project-id` | 20 | Update an existing project |
| `update-task` ·common | `harvest.updateTask()` | `--task-id` | 5 | Update an existing task |
| `update-time-entry` ·common | `harvest.updateTimeEntry()` | `--time-entry-id` | 7 | Update an existing time entry |
| `update-user` ·common | `harvest.updateUser()` | `--user-id` | 10 | Update an existing user |

## Docs

- [run CLI](https://docs.boxd.sh/cli/run): Call connected integrations from the shell, connect new ones, and run automations.
- [Quickstart](https://docs.boxd.sh/guides/integrations/quickstart): Connect an integration, call it from the shell, and turn a script into an automation.
- [Connections](https://docs.boxd.sh/guides/integrations/connections): Connect an account once, for yourself or for your whole organization.
- [Scripts](https://docs.boxd.sh/guides/automations/scripts): Typed integrations, triggers, schedules and state in a .run.ts file.
- [Jobs](https://docs.boxd.sh/guides/automations/jobs): How a script becomes a background job: states, retries, sleep and wake.
- [Beyond the catalog](https://docs.boxd.sh/guides/automations/beyond-the-catalog): Reach your own APIs, databases and cloud accounts from a script.
