Log time from an agent session

log_time records billable time against one client with a description and hours. The rate is optional, an omitted rate is stored as null rather than zero, and a request_id makes the call safe to retry.

Written and reviewed by the Billr team. Published , last reviewed .

Who this is for
Anyone whose agent should log work as it happens instead of reconstructing a timesheet later.
Billr capabilities used
log_timelist_time_entrieslist_unbilled

What you need first

  • A client to log against, identified by client_id or an exact client_name.
  • A key with the Read and draft profile, because logging is a write.
  • A stable request_id per intended entry, generated once and reused on retries.

Step by step

  1. 01Log the entry

    description and hours are required, and hours must be greater than zero and no more than 24. date defaults to today, and the entry is billable unless you pass billable: false.

    Example
    log_time  {
      "request_id": "b6f2a94c-7d31-4e58-8c09-5a1e7b3d2f64",
      "client_name": "Harbor & Lane",
      "description": "Schema markup fixes",
      "hours": 1.5,
      "rate": 150,
      "date": "2026-09-28"
    }
  2. 02Decide about the rate

    Passing rate stores the amount immediately. Omitting it stores hourly_rate: null and amount: null, which is different from a deliberate zero and is reported as a missing rate by list_unbilled.

  3. 03Read the entry back

    list_time_entries filters by client, date range, billed (billed, unbilled or all) and billable, so a session can answer "what did I log last week" without guessing.

    Example
    list_time_entries  {
      "billed": "unbilled",
      "from": "2026-09-01",
      "to": "2026-09-30"
    }
  4. 04Do not invoice from the same call

    Logging is deliberately separate from billing. Drafting an invoice attaches the entries and removes them from the unbilled list, so keep the two steps apart unless you mean it.

Worked example

Fictional account, field names as returned by the server

You say

Log 1.5 hours of schema markup fixes for Harbor & Lane at $150/hour.

Your agent calls

  • log_time { "request_id": "b6f2a94c-7d31-4e58-8c09-5a1e7b3d2f64", "client_name": "Harbor & Lane", "description": "Schema markup fixes", "hours": 1.5, "rate": 150, "date": "2026-09-28" }

Expected response, abridged

Example
{
  "summary": "Logged 1.5h for Harbor & Lane",
  "time_entry": {
    "id": "3f6c1a44-5b2d-4e71-9c08-7a1d3f5b9e22",
    "description": "Schema markup fixes",
    "date": "2026-09-28",
    "hours": 1.5,
    "rate": 150,
    "amount": 225,
    "is_billable": true
  },
  "app_url": "https://billr.cc/time"
}

Limits and gotchas

  • One entry covers at most 24 hours, so a mis-scaled value fails rather than creating a monster line.
  • Hours are stored as seconds; the amount is computed from seconds and rate, never from a rounded display value.
  • Entries logged without a rate cannot be attached to an invoice until a rate is set.
  • Non-billable time is recorded for your own reporting and never appears in list_unbilled.

Troubleshooting

Two identical entries appeared
The retry used a new request_id. Reuse the same id with the same input to get the original entry back.
The agent logged the wrong client
Correct it with update_time_entry while the entry is unbilled, passing the right client_id or exact client_name.
The entry never shows as billable
Check is_billable on the result and remember that list_unbilled only returns billable, uninvoiced entries.

Sources

Reviewed 2026-09-20 against Billr's own tool implementations and the client documentation linked above.

Logged time is only useful if it gets billed. The monthly run turns it into drafts, and the find-unbilled guide shows what the list reports first.

Bill the month