Skip to main content
Skip to Content

Time Entries API

Time entries record work performed for clients. They can be logged against clients, projects, tickets, or retainer agreements and form the basis for invoicing.

The Time Entry Object

{
  "id": "time_cuid123456",
  "user_id": "usr_xxxxx",
  "date": "2026-01-25",
  "hours": 2.50,
  "description": "Implemented contact form validation",
  "client_id": "cli_xxxxx",
  "project_id": "prj_xxxxx",
  "ticket_id": "tkt_xxxxx",
  "agreement_id": null,
  "period_id": null,
  "billing": {
    "billable": true,
    "billed": false,
    "rate_id": "rate_xxxxx",
    "rate_type": "standard",
    "rate_charged": 150.00,
    "rate_override": false,
    "invoice_line_id": null
  },
  "exclusion": {
    "excluded": false,
    "reason": null,
    "note": null
  },
  "timer": {
    "running": false,
    "started_at": null
  },
  "created_at": "2026-01-25T16:30:00Z",
  "updated_at": "2026-01-25T16:30:00Z"
}

Time Entry Fields

FieldTypeDescription
idstringUnique identifier (prefix: time_)
user_idstringRequired. User who logged the time
datedateRequired. Date of work (YYYY-MM-DD)
hoursdecimalRequired. Hours worked (0.01 - 24.00)
descriptionstringWork description
client_idstringAssociated client
project_idstringAssociated project
ticket_idstringAssociated ticket
agreement_idstringRetainer agreement
period_idstringSpecific retainer period
billingobjectBilling details
exclusionobjectExclusion details (if not billed)
timerobjectTimer state
created_atdatetimeWhen entry was created
updated_atdatetimeWhen entry was last updated

Billing Object

FieldTypeDescription
billablebooleanWhether this time is billable
billedbooleanWhether this has been invoiced
rate_idstringRate card ID
rate_typeenumstandard, emergency, custom
rate_chargeddecimalActual hourly rate
rate_overridebooleanWhether rate was manually set
invoice_line_idstringInvoice line (if billed)

Rate Types

TypeDescription
standardNormal hourly rate
emergencyAfter-hours/rush rate (typically 1.5x)
customManually specified rate

List Time Entries

GET/v1/time-entriesList time entries

Returns a paginated list of time entries.

Query Parameters

ParameterTypeDefaultDescription
pageinteger1Page number
per_pageinteger20Results per page (max: 100)
user_idstringFilter by user
client_idstringFilter by client
project_idstringFilter by project
ticket_idstringFilter by ticket
agreement_idstringFilter by agreement
fromdateStart date (YYYY-MM-DD)
todateEnd date (YYYY-MM-DD)
billablebooleanFilter by billable status
billedbooleanFilter by billed status
sortstringdateSort by: date, created_at, hours
orderstringdescSort order: asc, desc

Request

curl "https://api.govantage.co/v1/time-entries?from=2026-01-01&to=2026-01-31&billable=true" \
  -H "Authorization: Bearer vnt_sk_live_xxxxx"

Response

{
  "data": [
    {
      "id": "time_cuid123456",
      "user_id": "usr_xxxxx",
      "user_name": "John Smith",
      "date": "2026-01-25",
      "hours": 2.50,
      "description": "Implemented contact form validation",
      "client_id": "cli_xxxxx",
      "client_name": "Acme Corporation",
      "project_id": "prj_xxxxx",
      "project_title": "Website Redesign",
      "ticket_id": "tkt_xxxxx",
      "billing": {
        "billable": true,
        "billed": false,
        "rate_charged": 150.00
      },
      "created_at": "2026-01-25T16:30:00Z"
    }
  ],
  "pagination": {
    "page": 1,
    "per_page": 20,
    "total": 342,
    "total_pages": 18
  },
  "summary": {
    "total_hours": 485.50,
    "billable_hours": 425.25,
    "non_billable_hours": 60.25,
    "total_value": 63787.50
  }
}

The summary object provides aggregated totals for the filtered results, useful for reporting without additional API calls.


Create a Time Entry

POST/v1/time-entriesCreate a time entry

Request Body

FieldTypeRequiredDescription
user_idstringYesUser ID (defaults to authenticated user if API key is user-scoped)
datedateYesDate of work (YYYY-MM-DD)
hoursdecimalYesHours worked
descriptionstringNoWork description
client_idstringNo*Client ID
project_idstringNo*Project ID
ticket_idstringNo*Ticket ID
agreement_idstringNoRetainer agreement ID
period_idstringNoSpecific retainer period
billablebooleanNoDefault: true
rate_typestringNostandard, emergency, custom
rate_chargeddecimalNoCustom rate (when rate_type is custom)

At least one of client_id, project_id, or ticket_id must be provided. If you provide project_id or ticket_id, the client is inferred automatically.

Request

curl -X POST "https://api.govantage.co/v1/time-entries" \
  -H "Authorization: Bearer vnt_sk_live_xxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "usr_xxxxx",
    "date": "2026-01-25",
    "hours": 2.5,
    "description": "Implemented contact form validation",
    "ticket_id": "tkt_xxxxx",
    "billable": true,
    "rate_type": "standard"
  }'

Response

{
  "data": {
    "id": "time_cuid789012",
    "user_id": "usr_xxxxx",
    "date": "2026-01-25",
    "hours": 2.50,
    "description": "Implemented contact form validation",
    "client_id": "cli_xxxxx",
    "project_id": "prj_xxxxx",
    "ticket_id": "tkt_xxxxx",
    "billing": {
      "billable": true,
      "billed": false,
      "rate_id": "rate_xxxxx",
      "rate_type": "standard",
      "rate_charged": 150.00,
      "rate_override": false
    },
    "created_at": "2026-01-25T16:30:00Z",
    "updated_at": "2026-01-25T16:30:00Z"
  }
}

Get a Time Entry

GET/v1/time-entries/:idRetrieve a time entry by ID

Path Parameters

ParameterDescription
idThe time entry ID

Request

curl "https://api.govantage.co/v1/time-entries/time_cuid123456" \
  -H "Authorization: Bearer vnt_sk_live_xxxxx"

Update a Time Entry

PUT/v1/time-entries/:idUpdate a time entry

Time entries that have been billed (billed: true) cannot be modified. Void the invoice first.

Path Parameters

ParameterDescription
idThe time entry ID

Request

curl -X PUT "https://api.govantage.co/v1/time-entries/time_cuid123456" \
  -H "Authorization: Bearer vnt_sk_live_xxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "hours": 3.0,
    "description": "Implemented contact form validation and error handling"
  }'

Delete a Time Entry

DELETE/v1/time-entries/:idDelete a time entry

Billed time entries cannot be deleted. Void the associated invoice first.

Request

curl -X DELETE "https://api.govantage.co/v1/time-entries/time_cuid123456" \
  -H "Authorization: Bearer vnt_sk_live_xxxxx"

Timer Operations

Start Timer

POST/v1/time-entries/timer/startStart a timer

Creates a time entry with a running timer. The hours field will be calculated when the timer is stopped.

curl -X POST "https://api.govantage.co/v1/time-entries/timer/start" \
  -H "Authorization: Bearer vnt_sk_live_xxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "usr_xxxxx",
    "description": "Working on homepage design",
    "ticket_id": "tkt_xxxxx"
  }'

Response

{
  "data": {
    "id": "time_cuid789012",
    "user_id": "usr_xxxxx",
    "date": "2026-01-25",
    "hours": 0,
    "description": "Working on homepage design",
    "ticket_id": "tkt_xxxxx",
    "timer": {
      "running": true,
      "started_at": "2026-01-25T14:30:00Z"
    },
    "created_at": "2026-01-25T14:30:00Z"
  }
}

Stop Timer

POST/v1/time-entries/:id/timer/stopStop a running timer

Stops the timer and calculates the elapsed hours.

curl -X POST "https://api.govantage.co/v1/time-entries/time_cuid789012/timer/stop" \
  -H "Authorization: Bearer vnt_sk_live_xxxxx"

Response

{
  "data": {
    "id": "time_cuid789012",
    "hours": 2.25,
    "timer": {
      "running": false,
      "started_at": null
    }
  }
}

Get Running Timers

GET/v1/time-entries/timer/runningList all running timers
curl "https://api.govantage.co/v1/time-entries/timer/running" \
  -H "Authorization: Bearer vnt_sk_live_xxxxx"

A user can only have one running timer at a time. Starting a new timer will stop any existing timer.


Bulk Operations

Bulk Create

POST/v1/time-entries/bulkCreate multiple time entries
curl -X POST "https://api.govantage.co/v1/time-entries/bulk" \
  -H "Authorization: Bearer vnt_sk_live_xxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "entries": [
      {
        "user_id": "usr_xxxxx",
        "date": "2026-01-25",
        "hours": 2.0,
        "description": "Morning standup and planning",
        "project_id": "prj_xxxxx"
      },
      {
        "user_id": "usr_xxxxx",
        "date": "2026-01-25",
        "hours": 4.0,
        "description": "Feature development",
        "ticket_id": "tkt_xxxxx"
      }
    ]
  }'

Exclude from Billing

POST/v1/time-entries/:id/excludeExclude a time entry from billing

Mark a time entry as excluded from billing with a reason.

curl -X POST "https://api.govantage.co/v1/time-entries/time_cuid123456/exclude" \
  -H "Authorization: Bearer vnt_sk_live_xxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "reason": "internal_meeting",
    "note": "Weekly team sync - not client billable"
  }'

Exclusion Reasons

ReasonDescription
internal_meetingInternal meetings/syncs
reworkFixing our own mistakes
goodwillClient goodwill gesture
trainingTraining/learning time
adminAdministrative tasks
otherOther (specify in note)

Reporting Endpoints

Timesheet Summary

GET/v1/time-entries/summaryGet aggregated time data
curl "https://api.govantage.co/v1/time-entries/summary?from=2026-01-01&to=2026-01-31&group_by=user" \
  -H "Authorization: Bearer vnt_sk_live_xxxxx"

Response

{
  "data": {
    "period": {
      "from": "2026-01-01",
      "to": "2026-01-31"
    },
    "totals": {
      "hours": 1250.50,
      "billable_hours": 1125.25,
      "value": 168787.50,
      "utilization": 0.78
    },
    "by_user": [
      {
        "user_id": "usr_xxxxx",
        "user_name": "John Smith",
        "hours": 168.00,
        "billable_hours": 152.00,
        "utilization": 0.90
      }
    ]
  }
}

Webhooks

Subscribe to time entry events:

EventDescription
time_entry.createdNew time entry logged
time_entry.updatedTime entry modified
time_entry.deletedTime entry removed
time_entry.timer_startedTimer started
time_entry.timer_stoppedTimer stopped

Next Steps