{"openapi":"3.1.0","info":{"title":"Sumhour API","version":"1.0.0","description":"Time, projects, expenses, invoices and reports for one workspace. Authenticate with a personal API token from Settings → API tokens: `Authorization: Bearer sh_pat_…`. A token acts as its owner, never beyond their role, and only within its permissions. Writes accept an `Idempotency-Key` header. 120 requests a minute per token."},"servers":[{"url":"https://app.sumhour.com/api/v1"}],"security":[{"bearer":[]}],"tags":[{"name":"Account"},{"name":"Projects"},{"name":"Time"},{"name":"Expenses"},{"name":"Invoices"},{"name":"Reports"},{"name":"Approvals"},{"name":"Team"}],"paths":{"/me":{"get":{"operationId":"me_get","summary":"Who am I","description":"The signed-in person, the workspace, their role, timezone, week start and currency, and the scopes this caller has.","tags":["Account"],"x-sumhour-kind":"read","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{}}}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/projects":{"get":{"operationId":"projects_list","summary":"List projects","description":"Active projects the caller can log time to (everything for admins), each with its client, code, tasks and whether notes are required. Use the ids when logging time.\n\nPermission: `projects:read`.","tags":["Projects"],"x-sumhour-scope":"projects:read","x-sumhour-kind":"read","parameters":[{"name":"q","in":"query","required":false,"schema":{"description":"Filter by project, client or code","type":"string","maxLength":80},"description":"Filter by project, client or code"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{}}}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"post":{"operationId":"projects_create","summary":"Add a project","description":"Adds an hourly, fixed-fee or non-billable project for a client. Owners and admins only; retainers and budgets are set up in the app.\n\nPermission: `projects:write`.","tags":["Projects"],"x-sumhour-scope":"projects:write","x-sumhour-kind":"write","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"clientId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string","minLength":1,"maxLength":120},"code":{"type":"string","maxLength":20},"type":{"default":"hourly","type":"string","enum":["hourly","fixed_fee","non_billable"]},"hourlyRate":{"description":"One rate for the whole project, hourly projects","type":"string","pattern":"^\\d+(\\.\\d{1,2})?$"},"fixedFee":{"description":"The fee, fixed-fee projects","type":"string","pattern":"^\\d+(\\.\\d{1,2})?$"}},"required":["clientId","name"],"additionalProperties":false}}}},"responses":{"201":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{}}}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/projects/{projectId}/tasks":{"get":{"operationId":"projects_tasks","summary":"A project's tasks","description":"The tasks of one project the caller can log time to, for picking a task when logging time. Make and other tools fill their task lists from it.\n\nPermission: `projects:read`.","tags":["Projects"],"x-sumhour-scope":"projects:read","x-sumhour-kind":"read","parameters":[{"name":"projectId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{}}}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/clients":{"get":{"operationId":"clients_list","summary":"List clients","description":"Active clients with their billing currency.\n\nPermission: `projects:read`.","tags":["Projects"],"x-sumhour-scope":"projects:read","x-sumhour-kind":"read","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{}}}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"post":{"operationId":"clients_create","summary":"Add a client","description":"Adds a client with its billing currency. Owners and admins only.\n\nPermission: `projects:write`.","tags":["Projects"],"x-sumhour-scope":"projects:write","x-sumhour-kind":"write","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"currency":{"description":"Three-letter code; defaults to the workspace currency","type":"string","pattern":"^[A-Za-z]{3}$"},"billingEmail":{"anyOf":[{"type":"string","maxLength":200,"format":"email","pattern":"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},{"type":"null"}]}},"required":["name"],"additionalProperties":false}}}},"responses":{"201":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{}}}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/timer":{"get":{"operationId":"timer_get","summary":"Running timer","description":"The caller's running timer, or null when nothing runs.\n\nPermission: `time:read`.","tags":["Time"],"x-sumhour-scope":"time:read","x-sumhour-kind":"read","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{}}}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/timer/start":{"post":{"operationId":"timer_start","summary":"Start a timer","description":"Start the caller's timer on a project (stopping any running one), or resume an existing entry from today by passing entryId.\n\nPermission: `time:write`.","tags":["Time"],"x-sumhour-scope":"time:write","x-sumhour-kind":"write","parameters":[],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"projectId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"taskId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"notes":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]},"entryId":{"description":"Resume this entry instead of starting a new one","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"billable":{"description":"Override the project's billable default","type":"boolean"},"startedAt":{"description":"When the timer was started, for a start made offline (within the last 12 hours)","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"source":{"type":"object","properties":{"kind":{"type":"string","pattern":"^[a-z0-9_.:-]{1,40}$","description":"Where it started, e.g. \"extension:github\""},"ref":{"description":"The item's id there, e.g. #123","anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"url":{"description":"Link back to the item","anyOf":[{"type":"string","maxLength":2000,"format":"uri"},{"type":"null"}]}},"required":["kind"]}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{}}}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/timer/stop":{"post":{"operationId":"timer_stop","summary":"Stop the timer","description":"Stop the caller's running timer. Returns the stopped entry, or null when nothing was running.\n\nPermission: `time:write`.","tags":["Time"],"x-sumhour-scope":"time:write","x-sumhour-kind":"write","parameters":[],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"entryId":{"description":"Stop only this entry; 409 timer_not_running if it already stopped elsewhere","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"stoppedAt":{"description":"When it was stopped, for a stop made offline","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{}}}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/entries":{"get":{"operationId":"entries_list","summary":"List time entries","description":"Time entries between two dates (default: this week), newest first. Managers and admins can pass userId for someone else, or userId=all.\n\nPermission: `time:read`.","tags":["Time"],"x-sumhour-scope":"time:read","x-sumhour-kind":"read","parameters":[{"name":"from","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"userId","in":"query","required":false,"schema":{"description":"A person's id, or \"all\"; defaults to the caller","type":"string","maxLength":64},"description":"A person's id, or \"all\"; defaults to the caller"},{"name":"projectId","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"limit","in":"query","required":false,"schema":{"default":100,"type":"integer","minimum":1,"maximum":500}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string","maxLength":40}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{}},"next_cursor":{"type":["string","null"]}}}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"post":{"operationId":"entries_create","summary":"Log time","description":"Log a finished block of time for the caller. Give a duration like \"1:30\" or \"1.5h\" (or seconds). Workspace rules apply: required notes or tasks, locked weeks, project membership.\n\nPermission: `time:write`.","tags":["Time"],"x-sumhour-scope":"time:write","x-sumhour-kind":"write","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"projectId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"taskId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"date":{"description":"Defaults to today in the caller's timezone","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"duration":{"type":"string","maxLength":20},"seconds":{"type":"integer","minimum":0,"maximum":86400},"notes":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]},"billable":{"description":"Defaults to the project's setting","type":"boolean"}},"required":["projectId"],"additionalProperties":false}}}},"responses":{"201":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{}}}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/entries/{entryId}":{"patch":{"operationId":"entries_update","summary":"Change a time entry","description":"Change an entry's project, task, date, duration, notes or billable flag. Only the fields you pass change. Locked or approved time cannot change.\n\nPermission: `time:write`.","tags":["Time"],"x-sumhour-scope":"time:write","x-sumhour-kind":"write","parameters":[{"name":"entryId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"projectId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"taskId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"duration":{"type":"string","maxLength":20},"seconds":{"type":"integer","minimum":0,"maximum":86400},"notes":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]},"billable":{"type":"boolean"}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{}}}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"delete":{"operationId":"entries_delete","summary":"Delete a time entry","description":"Delete one of the caller's entries (admins: anyone's). Locked or invoiced time cannot be deleted.\n\nPermission: `time:write`.","tags":["Time"],"x-sumhour-scope":"time:write","x-sumhour-kind":"destructive","parameters":[{"name":"entryId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{}}}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/timesheets/{weekStart}":{"get":{"operationId":"timesheets_get","summary":"A week's timesheet","description":"The caller's week: status (open, submitted, approved, rejected, locked), hours per day and the total. weekStart may be any date in the week.\n\nPermission: `time:read`.","tags":["Time"],"x-sumhour-scope":"time:read","x-sumhour-kind":"read","parameters":[{"name":"weekStart","in":"path","required":true,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{}}}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/timesheets/{weekStart}/submit":{"post":{"operationId":"timesheets_submit","summary":"Submit a week","description":"Submit the caller's week for approval. Stop any running timer first.\n\nPermission: `time:write`.","tags":["Time"],"x-sumhour-scope":"time:write","x-sumhour-kind":"write","parameters":[{"name":"weekStart","in":"path","required":true,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{}}}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/expense-categories":{"get":{"operationId":"expenses_categories","summary":"Expense categories","description":"Expense categories, some with a fixed unit price (mileage and similar).\n\nPermission: `expenses:read`.","tags":["Expenses"],"x-sumhour-scope":"expenses:read","x-sumhour-kind":"read","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{}}}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/expenses":{"get":{"operationId":"expenses_list","summary":"List expenses","description":"Expenses between two dates (default: this month). People see their own; owners and admins can pass userId, or leave it out for everyone.\n\nPermission: `expenses:read`.","tags":["Expenses"],"x-sumhour-scope":"expenses:read","x-sumhour-kind":"read","parameters":[{"name":"from","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"projectId","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"userId","in":"query","required":false,"schema":{"type":"string","maxLength":64}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{}}}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"post":{"operationId":"expenses_create","summary":"Add an expense","description":"Add an expense for the caller on a project. Receipts are uploaded in the app. For a unit-priced category pass units instead of amount.\n\nPermission: `expenses:write`.","tags":["Expenses"],"x-sumhour-scope":"expenses:write","x-sumhour-kind":"write","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"projectId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"categoryId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"amount":{"type":"string","pattern":"^\\d+(\\.\\d{1,2})?$"},"units":{"type":"string","pattern":"^\\d+(\\.\\d{1,3})?$"},"notes":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]},"billable":{"default":true,"type":"boolean"},"reimbursable":{"default":false,"type":"boolean"}},"required":["projectId"],"additionalProperties":false}}}},"responses":{"201":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{}}}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/invoices":{"get":{"operationId":"invoices_list","summary":"List invoices","description":"Invoices, newest first, optionally by status (draft, sent, viewed, paid, void) or client.\n\nPermission: `invoices:read`.","tags":["Invoices"],"x-sumhour-scope":"invoices:read","x-sumhour-kind":"read","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["draft","sent","viewed","paid","void"]}},{"name":"clientId","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{}}}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"post":{"operationId":"invoices_create_draft","summary":"Draft an invoice","description":"Draft an invoice for a client from uninvoiced time (and expenses) up to a date. Nothing is sent; the draft opens in the app for review.\n\nPermission: `invoices:write`.","tags":["Invoices"],"x-sumhour-scope":"invoices:write","x-sumhour-kind":"write","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"clientId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"projectIds":{"description":"Default: all the client's projects","maxItems":50,"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"to":{"description":"Default: today","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"groupBy":{"default":"task","type":"string","enum":["task","person","date","project","entry"]},"includeExpenses":{"default":true,"type":"boolean"},"showNotes":{"default":false,"description":"Print each time entry's note on the invoice. Notes are often internal.","type":"boolean"}},"required":["clientId"],"additionalProperties":false}}}},"responses":{"201":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{}}}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/invoices/{invoiceId}":{"get":{"operationId":"invoices_get","summary":"An invoice","description":"One invoice with its lines and payments.\n\nPermission: `invoices:read`.","tags":["Invoices"],"x-sumhour-scope":"invoices:read","x-sumhour-kind":"read","parameters":[{"name":"invoiceId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{}}}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/invoices/{invoiceId}/payments":{"post":{"operationId":"invoices_record_payment","summary":"Record a payment","description":"Record a payment against a sent invoice. The invoice turns paid when fully covered.\n\nPermission: `invoices:write`.","tags":["Invoices"],"x-sumhour-scope":"invoices:write","x-sumhour-kind":"write","parameters":[{"name":"invoiceId","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"amount":{"type":"string","pattern":"^\\d+(\\.\\d{1,2})?$"},"paidOn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"method":{"default":"bank","type":"string","enum":["manual","bank","card","other"]},"reference":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}]},"notes":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}]}},"required":["amount"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{}}}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/reports/{kind}":{"get":{"operationId":"reports_run","summary":"Run a report","description":"Run a report: time, profitability, utilization, invoicing, uninvoiced. Pick a preset (this_month, last_month, this_quarter, last_quarter, this_year, last_year, last_30, last_90) or from/to. Managers see only the projects they manage.\n\nPermission: `reports:read`.","tags":["Reports"],"x-sumhour-scope":"reports:read","x-sumhour-kind":"read","parameters":[{"name":"kind","in":"path","required":true,"schema":{"type":"string","enum":["time","profitability","utilization","invoicing","uninvoiced"]}},{"name":"preset","in":"query","required":false,"schema":{"type":"string","enum":["this_month","last_month","this_quarter","last_quarter","this_year","last_year","last_30","last_90"]}},{"name":"from","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"groupBy","in":"query","required":false,"schema":{"description":"client, project, task, person, date, week or month (depends on the report)","type":"string","maxLength":20},"description":"client, project, task, person, date, week or month (depends on the report)"},{"name":"clientId","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"projectId","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"userId","in":"query","required":false,"schema":{"type":"string","maxLength":64}},{"name":"billable","in":"query","required":false,"schema":{"default":"all","type":"string","enum":["all","billable","nonbillable"]}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{}}}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/approvals":{"get":{"operationId":"approvals_list","summary":"Weeks waiting for review","description":"Submitted weeks waiting for approval, with hours, plus people who have not submitted last week.\n\nPermission: `approvals:read`.","tags":["Approvals"],"x-sumhour-scope":"approvals:read","x-sumhour-kind":"read","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{}}}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/approvals/{userId}/{weekStart}/approve":{"post":{"operationId":"approvals_approve","summary":"Approve a week","description":"Approve a person's submitted week (weekStart may be any date in the week). Approved time can be invoiced and no longer changes.\n\nPermission: `approvals:write`.","tags":["Approvals"],"x-sumhour-scope":"approvals:write","x-sumhour-kind":"write","parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":64}},{"name":"weekStart","in":"path","required":true,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"comment":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}]}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{}}}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/approvals/{userId}/{weekStart}/reject":{"post":{"operationId":"approvals_reject","summary":"Send a week back","description":"Send a submitted week back to the person with a comment saying what to change (weekStart may be any date in the week).\n\nPermission: `approvals:write`.","tags":["Approvals"],"x-sumhour-scope":"approvals:write","x-sumhour-kind":"write","parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":64}},{"name":"weekStart","in":"path","required":true,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"comment":{"type":"string","minLength":1,"maxLength":1000}},"required":["comment"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{}}}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/people":{"get":{"operationId":"people_list","summary":"List people","description":"Everyone in the workspace with their role.\n\nPermission: `team:read`.","tags":["Team"],"x-sumhour-scope":"team:read","x-sumhour-kind":"read","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{}}}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/events/subscriptions":{"post":{"operationId":"events_subscribe","summary":"Send events to a URL","description":"Subscribes a URL to one workspace event (the same events as webhooks), for apps such as Zapier. The URL gets a signed POST each time. Owners and admins only.\n\nPermission: `events:write`.","tags":["Other"],"x-sumhour-scope":"events:write","x-sumhour-kind":"write","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","maxLength":2000,"format":"uri"},"event":{"type":"string","maxLength":60,"description":"An event name, e.g. \"invoice.send\""}},"required":["url","event"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{}}}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/events/subscriptions/{id}":{"delete":{"operationId":"events_unsubscribe","summary":"Stop sending events to a URL","description":"Removes an event subscription made with events.subscribe.\n\nPermission: `events:write`.","tags":["Other"],"x-sumhour-scope":"events:write","x-sumhour-kind":"write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{}}}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}}},"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"Personal API token. Permissions: `time:read` see entries, the timer and timesheets; `time:write` log, change and delete time, run the timer, submit weeks; `projects:read` see projects, tasks and clients; `projects:write` add clients and projects (admins and owners); `expenses:read` see expenses; `expenses:write` add expenses; `invoices:read` see invoices; `invoices:write` draft invoices and record payments; `reports:read` run reports; `approvals:read` see weeks waiting for review; `approvals:write` approve and send back weeks; `team:read` see the people in the workspace; `events:write` send workspace events to apps such as zapier (admins and owners)."}},"responses":{"Error":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"type":"string"}}},"required":["code","message"]}}}}}}}}}