> ## Documentation Index
> Fetch the complete documentation index at: https://docs.comforthub.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Approve timesheets and time off

> Review what people submitted, in the app or in Zoho, and see the verdict reach the technician

export const Touches = ({systems}) => <p>
    <strong>Systems involved:</strong>{" "}
    {systems.split(",").map((s, i) => <span key={s}>
        {i > 0 ? " · " : ""}
        <a href={"/systems/" + s.trim()}>{s.trim().replace(/-/g, " ")}</a>
      </span>)}
  </p>;

<Touches systems="zoho-crm, supabase-backend, the-7am-app" />

## Before you start

* The app signed in as an admin or a super admin, or Zoho with rights to edit the **Timesheets** and **Time Off Requests** modules. Either place works; the verdict reaches the other within seconds. Admin is the rung that can approve; see [Roles and what they can do](/handbook/app/roles-and-what-they-can-do).
* The timesheet must be Submitted. A draft never reaches Zoho and does not appear in the app's approvals list.

## Steps in the app

<Steps>
  <Step title="Open Approvals">
    Under **You** on the **Search** tab (see [The app tour](/handbook/app/the-app-tour)), **Approvals** lists every submitted timesheet and every pending time off request. The row shows only for an admin or a super admin.
  </Step>

  <Step title="Approve or reject">
    Swipe the row right for **Approve**, or left for **Reject**, or open the item and use the **Decision** menu. A rejection asks for a reason, and the **Reject** button stays off until you type one: it is the only thing the technician is told, and it stays on the sheet so they can read it again later.
  </Step>

  <Step title="Let the technician fix a rejected sheet">
    Nothing more to do on your side. A rejected timesheet opens for its technician again: they change the days and submit it a second time, while the period's submit window is still open. It comes back to your list as Submitted. An approved sheet, and a sheet still waiting, stay locked to them.
  </Step>
</Steps>

## Steps in Zoho

<Steps>
  <Step title="Open the timesheet in Zoho">
    Find it under **Timesheets**. The name is the period, for example "Period 18 2026"; the **Technician** field says whose it is and the fourteen day rows show the hours.
  </Step>

  <Step title="Approve or reject">
    Change **Status** to **Approved**, or to **Rejected** and type the reason into **Rejection Reason**. Save. You do not need to fill in **Approved At**; the engine stamps its own approval time.
  </Step>

  <Step title="Do the same for time off">
    Under **Time Off Requests**, set **Status** to **Approved** or **Rejected**. A message for the technician goes in **Reviewed Message**.
  </Step>
</Steps>

## How you know it worked

* The technician's **Hours** screen shows the status you set within seconds, with the reason under it on a rejected sheet.
* The person whose sheet it is gets a push: "Timesheet Approved", or "Timesheet Rejected" followed by "Reason:" and your text. The person who asked for the time off gets "Time Off Approved", or "Time Off Rejected" followed by "Notes:" and your message. Nobody else is told; see [Notifications we send](/reference/notifications-we-send).
* A decision made in the app reaches Zoho the same way: the Zoho timesheet shows the **Status** you set, and **Approved At** or **Rejection Reason** carries what you entered.

## If it did not work

* The **Hours** screen still says Submitted after a minute: the sync failed on the sheet, and the monitor has opened a condition in Sentry. See [Act on a Sentry email](/handbook/running/act-on-a-sentry-email).
* The status changed but no push arrived: the technician may have that notification switched off on the phone.

## Related

* [How timesheets work](/handbook/hours/how-timesheets-work)
* [Zoho CRM](/systems/zoho-crm)
* [Statuses](/reference/statuses)
* [Notifications we send](/reference/notifications-we-send)
