- Brand
- Unknown
- Category
- Pending
- Primary Subcategory
- Pending
Integration details
Description
Track time, run timers, review and submit timesheets, and understand where project hours go. eHour connects ChatGPT to your eHour workspace so you can work with projects, assignments, users, teams, and reports while respecting your existing permissions.
- Integration type
- Plugin
- Verification status
- Not applicable
- Platform
- ChatGPT
- Category
- Pending
- Primary Subcategory
- Pending
- Secondary Subcategories
- None listed
- Brand
- Unknown
- Access
- Account required
- First tracked
- 2026-10-15
- Tool count
- 43
- Geography
- US
The broad Category that contains the Primary Subcategory.
The Primary Subcategory used for this profile’s headline score.
Other Subcategories where the Integration is listed.
Your score is coming
ChatGPT now suggests Plugins on its own when they match a user's request.Your Plugin Discovery Score measures how often yours appears, and it will show here as soon as it’s ready.
What discovery looks like

Get alerts for eHour
Get updates when eHour’s Discoverability Score or category rank changes.
Competitive lineup
43 tools agents can invoke
Add or subtract time on one assignment and date without replacing the existing total. Call this tool directly; do not call getTimesheet or getAssignments first. Use this for additive requests such as 'add another 30 minutes'; otherwise use trackTime to set the day's total. Supply signed hours, or supply startTime and endTime to derive a positive duration. This appends a detail entry atomically and preserves existing time-entry comments, tags, sources, and start/end windows. If all three time fields are supplied, the hours must match the window. Start and end use HH:mm in the workspace time zone; an end earlier than the start is on the next day. Times that occur twice during a daylight-saving transition are rejected as ambiguous. Supply a stable operationId UUID and reuse it when retrying the same logical adjustment; repeated calls with that ID update the same manual entry instead of adding it twice. Omit both window fields to preserve that entry's existing window, or pass both as empty strings to clear it. Identify the assignment by ID, project code, or project name. Resolution precedence: assignmentId > projectCode > projectName. Narrow with taskName, clientCode, or clientName.
Add a user to a team. Identify both the team and the user by ID, code/email, or name.
Archive (deactivate) or restore a user. Identify by userId, userEmail, or userName. Archived users are hidden from default queries but can be restored.
Assign a user or team to a project. Identify the project by ID, code, or name. Specify exactly one assignee (user or team).
Assign a user or team to a task. Identify the task by ID or name (with optional project disambiguation). Specify exactly one assignee (user or team).
Cancel a single pending (or still-cancellable auto-approved) timesheet submission belonging to the caller. The approvalId is obtained from getTimesheet.approvals[].approvalId. Returns the refreshed approval entry (state=NOT_SUBMITTED, approvalId absent) on success. A foreign or non-existent approvalId returns not_found; a submission that is no longer cancellable returns not_cancelable.
Create a new client. Requires a client name. When code is omitted or empty, a unique code is generated from the name.
Create a new project. Requires a client (by ID, code, or name) and a project name. When project code is omitted or empty, a unique code is generated from the name.
Create a new task within a project. Identify the project by ID, code, or name.
Create a new team with a name and optional code.
Create and invite a new user. Sends an invitation email for password setup.
Discard the current user's running timer without recording any time. Call this tool directly; do not call getTimerStatus first. Use this only when the user asks to cancel or discard the timer; use stopTimer to save the elapsed time.
List the current user's active assignments for discovery or disambiguation. When an assignment ID, project code, or project name is already known, do not use this as a prerequisite for timer, trackTime, or addTime calls because those tools resolve those selectors directly. Use assignment discovery when the request supplies only narrower details such as task or client. Self-only convenience; use listAssignments for cross-user queries.
Get the current authenticated user's profile information. Use only when profile details are requested or needed; self-scoped tools already infer the current user and do not require this as a prerequisite.
Get a specific saved report by ID or by name. Call this tool directly when either is known; do not call listReports first. Provide reportId (takes precedence) or reportName (case-insensitive exact match). Only the caller's own saved reports are visible; reports belonging to other users are reported as not found. If multiple saved reports share the same name, an error listing the matches is returned.
Get the status of the current user's timer. Use only when the user asks whether a timer is running or requests its details, or after a timer tool reports that the running timer changed. Do not use as a routine prerequisite for startTimer, updateTimer, stopTimer, or discardTimer. Returns the current state and elapsed time.
Get a timesheet for a date range, grouped by assignment. Call this tool directly for tracked-time totals and details; do not call getAssignments or listProjects first. Defaults to the current user; supply userId or userEmail to fetch another user's timesheet (caller must have management rights).
List assignments scoped to the caller's role with optional filters (AND-combined). All filters are optional; when none of userId/userEmail/teamId/teamCode/teamName is provided the caller's own assignments are returned. Providing both a user and a team filter is an error.
List active clients for discovery. Do not use as a prerequisite for createProject or other tools that already accept client ID, code, or name. Results are scoped to the user's role.
List projects visible to the caller for discovery. Do not use as a prerequisite for tools that already accept project ID, code, or name. Optionally filter by client (id/code/name; id wins, then code, then name) and include archived projects. Results are role-scoped.
List the report columns the caller is allowed to select for runReport. Returns the same shape as the React report UI's column picker: a categories list and a columns list, with each column object containing at least 'column' (the identifier to pass to runReport), 'title' (localized label), 'category' (entity it belongs to), and optionally 'type' / 'unit'. The set is filtered by tenant configuration (custom fields, approval, expenses, external rates) and by the caller's roles (financial columns like HOURS_TURNOVER and ASSIGNMENT_RATE are only returned when the role grants turnover visibility). Use this only when custom, financial, or otherwise uncommon columns must be discovered; runReport has useful default columns for ordinary tracked-time summaries.
List all saved reports for the current user. Use for discovery when the report name is unknown; getReport resolves a known name directly.
List per-user timesheet submission/approval status for a period. Canonical tool for 'who (didn't) submit time' queries — prefer this over fanning out per-user calls from listUsers. Defaults to the caller; supply userId/userEmail for one person, or teamId/teamCode/teamName to return a row per team member (user and team filters are mutually exclusive). For org-wide coverage iterate teams from listTeams and call this tool per team. Role-scoped: targets outside the caller's management scope are filtered out, or the call returns forbidden if the explicit target is out of scope.
List tasks for discovery. Do not use as a prerequisite for tools that already resolve task or project identifiers. Provide a project ID to limit the results, or omit it to list tasks across the user's visible projects.
List active teams for discovery. Do not use as a prerequisite for tools that already accept team ID, code, or name. Admins and managers see all teams; other users see teams they belong to.
List users within the caller's role scope for discovery (Admin/Manager: all; Team Manager: team members; Line Manager: direct reports). All filters are optional and AND-combined. Use role to filter by eHour role (friendly names like 'consultant' or internal names like 'ROLE_CONSULTANT' are accepted, case-insensitive). Use teamId / teamCode / teamName to filter to a specific team (teamId wins, then teamCode, then teamName). active=true returns active only (default when omitted), active=false returns archived only. Do not use this tool as a pre-step when the destination tool accepts the user identifier already supplied, or to fan out per-user submission or assignment queries — listSubmissionStatus (per team) and listAssignments already aggregate across users. Use discovery when, for example, only a name is known but the destination requires an ID or email.
Move existing time entries from one assignment to another over an optional date range, atomically. Prefer explicit startDate and endDate. If the intended date scope is unclear, ask before calling. Omitting either bound leaves that side unbounded; omitting both moves all recorded entries from the source assignment. Before an unbounded move, explain the affected date scope and confirm the source and target assignments with the user. Both assignments must belong to the same user (caller, or a target user when userId/userEmail is supplied and the caller has management rights). Locked dates cause the whole call to fail with date_locked; an invalid target window fails with invalid_target_assignment.
Remove a user from a team. Identify both the team and the user by ID, code/email, or name.
Resubmit a rejected timesheet submission belonging to the caller, optionally with a new comment. Use after correcting time entries in response to a rejection. A foreign or non-existent approvalId returns not_found; an approval that is not in REJECTED state returns not_rejected.
Run an ad-hoc report on tracked time. Call this tool directly for ordinary summaries and omit columns to use date, client, project, user, hours, and comment defaults. Use listReportColumns only to discover custom, financial, or otherwise uncommon columns available to the caller for the current tenant configuration. Aggregation options: NONE (one row per entry), DAILY (default, grouped by day), WEEKLY, MONTHLY, QUARTERLY, YEARLY. Returns rows of key-value pairs. Time values are in hours. Filter by project (projectId or projectCode), client (clientId, clientCode, or clientName), or user (userId or userEmail). ID takes precedence over code/name/email. Pass billableOnly=true to restrict to billable hours (same rule as the report UI). Pass approvalStatus to filter by approval lifecycle: APPROVED, PENDING, REJECTED, NOT_REQUESTED, or UNAPPROVED (the union of PENDING + REJECTED + NOT_REQUESTED). This tool reports tracked hours only; it does NOT return per-user timesheet submission or approval state. For 'who (didn't) submit time' or 'submission/approval status' queries use listSubmissionStatus instead.
Start a timer for the current user. Call this tool directly; do not call getTimerStatus first. Starting while a timer is already running never resets its start time: it returns action already_running, or attaches a supplied assignment when the running timer is unassigned. When no assignment is provided, a new timer starts unassigned. Identify the assignment by ID, project code, or project name. Resolution precedence: assignmentId > projectCode > projectName. Narrow with taskName, clientCode (exact), or clientName. A comment can be stored with a newly started timer.
Stop the running timer and record the tracked time to an assignment. Call this tool directly; do not call getTimerStatus first. When the timer already has an assignment, omit assignment selectors to reuse it. Identify the assignment by ID, project code, or project name. Resolution precedence: assignmentId > projectCode > projectName. Narrow with taskName, clientCode (exact), or clientName. Omitting the comment reuses the timer's stored comment; an empty comment clears it.
Report friction back to the eHour team when an MCP tool blocked you from helping the user. Call this when: (a) a parameter you needed is missing from a tool, (b) a tool description was unclear or misleading, (c) a tool returned an unexpected error, or (d) any other gap kept you from completing a reasonable request. The feedback is logged for the team to review — it does not affect the current user's data. Be specific: name the tool, the operation you were trying, and the missing capability.
Submit the caller's own timesheet for approval over a date range. When the user explicitly asks to submit a known range, call this tool directly; a getTimesheet preflight is unnecessary. Self-only. Creates one approval record per weekly or monthly timeframe intersecting the range, per tenant configuration. Partial timeframes are snapped to the full timeframe (consistent with the web UI). Fails atomically: if any date in the range is locked, if any overlapping timeframe already has a pending or approved record, or if the range contains zero tracked hours, no approval records are created.
Set or replace the tracked total on a specific assignment and date. Call this tool directly; do not call getTimesheet or getAssignments first. Use addTime instead only when the user asks to add or subtract an amount from existing time. Defaults to the current user; supply userId or userEmail to log on behalf of another user (caller must have management rights). Supply hours, or supply startTime and endTime to derive the hours. If all three are supplied, the hours must match the time window. Start and end use HH:mm in the workspace time zone; an end earlier than the start is on the next day. Times that occur twice during a daylight-saving transition are rejected as ambiguous. Logging 0 hours deletes the entry. Resolution precedence: assignmentId > projectCode > projectName. Narrow with taskName, clientCode, or clientName.
Remove a user or team assignment from a project. Use the assignment ID returned by assignToProject (e.g. ASG42 for user assignments, TSG7 for team assignments). The assignment is either deleted or archived depending on whether time has been tracked against it.
Update an existing assignment (user or team). Only provided fields are updated (patch semantics). Identify the assignment by its prefixed ID (ASG... for user, TSG... for team).
Update an existing client. Identify the client by ID, code, or name. Only provided fields are updated (patch semantics).
Update an existing project. Identify the project by ID, code, or name. Only provided fields are updated (patch semantics).
Update an existing task. Identify the task by ID or name (with optional project disambiguation). Only provided fields are updated (patch semantics).
Update an existing team. Identify the team by ID, code, or name. Only provided fields are updated (patch semantics).
Update the current user's running timer without resetting its start time. Call this tool directly; do not call getTimerStatus first. Change its assignment by ID, project code, or project name, and/or replace its comment. A task name without a project selector is resolved within the timer's current project. Resolution precedence: assignmentId > projectCode > projectName. Omitting the assignment preserves it; omitting the comment preserves it; an empty comment clears it.
Update an existing user. Identify by userId, userEmail, or userName (userId wins, then userEmail, then userName). Only provided fields are changed. Use archiveUser to change active status. Line manager can be supplied by lineManagerId (prefixed user ID) or lineManagerEmail (case-insensitive); lineManagerId wins if both are provided.
eHour ChatGPT Plugin FAQ
How the directory, categories and Discoverability Score work.
Read the methodologyHow do I improve eHour's ChatGPT Plugin discoverability?
The levers are the listing surface agents actually read: names, descriptions, keywords, tool metadata, and registry health. Which lever matters depends on where discovery breaks, which is what continuous measurement shows.
Where is this profile measured?
This profile uses the geography attached to the latest public registry snapshot: US. Locale tags are intentionally omitted.