{"info":{"title":"LogQuill API","version":"1","description":"![LogQuill](https://api.logquill.com/v1/logo.svg)\n\nRead and write time in LogQuill from your own scripts and tools.\n\n## Keys\n\nMake a key in LogQuill: your menu (your name at the bottom of the sidebar), then **API keys**. Send it\nin the `Authorization` header of every request, and nowhere else:\n\n```\nAuthorization: Bearer logquill_...\n```\n\nA key acts as you. It only reaches what you ticked when you made it (its scopes), and never more\nthan your role allows in LogQuill, checked on every call. What it writes shows you as the author, in\nLogQuill and in Jira. Keep it like a password.\n\n## People, days and times\n\n- People are named by their **Jira account id** (`accountId`).\n- Days are `YYYY-MM-DD`. A worklog's `date` is the day it counts for in its author's time zone;\n  moments (`startedAt`, `updatedAt`) are ISO 8601 in UTC.\n- Durations are in seconds.\n\n## Pages\n\nLists answer `{ \"results\": [...], \"metadata\": { \"count\", \"limit\", \"next\" } }`. `next` is the full\naddress of the next page, or `null` on the last one. `limit` is 100 unless you ask for up to 1000.\nA period (`from`, `to`) covers a year at most.\n\n## Errors\n\nErrors answer `{ \"code\", \"status\", \"message\", \"data\" }`; `data.reason` says why, when there is\nmore to say.\n\n| Status | When |\n| --- | --- |\n| 400 | The request isn't valid: `message` says what's wrong, `data.issues` lists invalid fields |\n| 401 | The key is missing, unknown, expired or revoked |\n| 403 | The key or its owner may not do this (`missingScope`, `readOnly`, `apiDisabled`, `ownerInactive`...) |\n| 404 | Not found, or not yours to see |\n| 429 | A limit was reached: wait `Retry-After` seconds |\n| 503 | LogQuill can't reach Jira for your site right now: try again in a few minutes |\n\n## Limits\n\n60 requests a minute per key and 600 per site; logging, changing and deleting worklogs and plans\nis also limited to 300 an hour per site.\nEvery answer carries `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset`\n(seconds)."},"servers":[{"url":"https://api.logquill.com/v1"}],"tags":[{"name":"Me","description":"Who the key acts as. Any key."},{"name":"Worklogs","description":"Logged time: read what you may see, write your own.\n\n**Scopes:** `worklogs:read`, `worklogs:write`"},{"name":"Plans","description":"Planned time, one plan a day: read what you may see, write your own.\n\n**Scopes:** `plans:read`, `plans:write`"},{"name":"Timesheets","description":"Periods, their hours and status: yours, and those you review. Submit, approve and send back.\n\n**Scopes:** `timesheets:read`, `timesheets:write`"},{"name":"Time","description":"Totals, as in LogQuill's reports.\n\n**Scope:** `time:read`"},{"name":"Teams","description":"The teams you may see, and their members.\n\n**Scope:** `teams:read`"},{"name":"Absences","description":"Time off you may see, as on LogQuill's Absences page, with its working days; and the absence types. Read only.\n\n**Scope:** `absences:read`"}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"A LogQuill API key, `logquill_...`."}},"schemas":{"Error":{"type":"object","required":["code","status","message"],"properties":{"code":{"type":"string","description":"What went wrong, for code to test.","examples":["NOT_FOUND"]},"status":{"type":"integer","description":"The HTTP status again.","examples":[404]},"message":{"type":"string","description":"What went wrong, for people to read.","examples":["Worklog not found"]},"data":{"type":"object","description":"More detail, when there is some."}}}},"responses":{"BadRequest":{"description":"The input was refused: `data.issues` names each field (`path`) and why (`message`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"Missing, unknown or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The key lacks the scope, its owner may not do this, or the API is off for the site (`data.reason`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"Nothing with this id that the key's owner may see.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"TooManyRequests":{"description":"A limit was reached: wait `Retry-After` seconds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"openapi":"3.1.1","paths":{"/me":{"get":{"operationId":"me","summary":"Who the key acts as","description":"The key's owner, what they may do, and the key itself.\n\n**Scope:** any","tags":["Me"],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"accountId":{"type":"string","description":"Your Jira account id.","examples":["712020:4d42d4f9-1a2b-4c3d-8e9f-0a1b2c3d4e5f"]},"displayName":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Your name in Jira.","examples":["Alex Martin"]},"permissions":{"type":"array","items":{"enum":["time:log:own","time:read:all","teams:manage:all","timesheets:manage:all","settings:general","settings:holidays","settings:timesheets","settings:time-logging","settings:accounts","settings:projects","settings:absences","settings:teams","settings:api","roles:manage","audit:read","sync:manage","absences:approve","absences:read:types"],"type":"string"},"description":"What your role lets you do in LogQuill right now. A key never does more."},"key":{"type":"object","properties":{"name":{"type":"string","description":"The name you gave the key.","examples":["Payroll export"]},"prefix":{"type":"string","description":"The start of the key, to recognise it.","examples":["logquill_AbCdEfGh"]},"scopes":{"type":"array","items":{"enum":["worklogs:read","worklogs:write","plans:read","plans:write","timesheets:read","timesheets:write","time:read","teams:read","absences:read","absences:write"],"type":"string"},"description":"The parts of the API the key reaches."},"expiresAt":{"type":"string","description":"When the key stops working.","examples":["2027-01-12T10:00:00.000Z"]}},"required":["name","prefix","scopes","expiresAt"]},"site":{"type":"object","properties":{"name":{"type":"string","description":"The Jira site, as people know it.","examples":["acme.atlassian.net"]},"url":{"type":"string","description":"Its address.","examples":["https://acme.atlassian.net"]}},"required":["name","url"],"description":"The Jira site the key belongs to: a key only ever reaches that one."}},"required":["accountId","displayName","permissions","key","site"]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"security":[{"apiKey":[]}]}},"/worklogs":{"get":{"operationId":"worklogs.list","summary":"List worklogs","description":"Worklogs in a period that the key's owner may see: their own, and others' as their role allows.\n\n**Scope:** `worklogs:read`","tags":["Worklogs"],"parameters":[{"name":"from","in":"query","required":true,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The first day, YYYY-MM-DD.","examples":["2026-10-01"]},"allowEmptyValue":true,"allowReserved":true},{"name":"to","in":"query","required":true,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The last day, YYYY-MM-DD, included. At most 366 days after `from`.","examples":["2026-10-31"]},"allowEmptyValue":true,"allowReserved":true},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":1000,"default":100,"description":"How many results a page holds: 1 to 1000.","examples":[100]},"allowEmptyValue":true,"allowReserved":true},{"name":"cursor","in":"query","required":false,"schema":{"type":"string","maxLength":512,"description":"Where the page starts. Don't build it: follow the previous page's `metadata.next`, which holds it."},"allowEmptyValue":true,"allowReserved":true},{"name":"accountId","in":"query","required":false,"schema":{"type":"string","minLength":1,"maxLength":128,"description":"Only this person's; `me` for the key's owner. Left out: everyone's you may see."},"allowEmptyValue":true,"allowReserved":true},{"name":"issueId","in":"query","required":false,"schema":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"Only those on this Jira issue.","examples":[10232]},"allowEmptyValue":true,"allowReserved":true},{"name":"projectId","in":"query","required":false,"schema":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"Only those in this Jira project.","examples":[10000]},"allowEmptyValue":true,"allowReserved":true},{"name":"updatedFrom","in":"query","required":false,"schema":{"type":"string","format":"date-time","description":"Only those changed at or after this moment, ISO 8601 in UTC: to keep another system in step.","examples":["2026-10-14T06:00:00Z"]},"allowEmptyValue":true,"allowReserved":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"results":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"LogQuill's id for it.","examples":[123]},"jiraWorklogId":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Jira's id for it.","examples":["10848"]},"author":{"type":"object","properties":{"accountId":{"type":"string","description":"Their Jira account id.","examples":["712020:4d42d4f9-1a2b-4c3d-8e9f-0a1b2c3d4e5f"]},"displayName":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Their name in Jira.","examples":["Alex Martin"]}},"required":["accountId","displayName"],"description":"Whose time it is."},"issue":{"anyOf":[{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"The Jira issue's id.","examples":[10232]}},"required":["id"]},{"type":"null"}],"description":"The Jira issue it was logged on."},"projectId":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"The Jira project of its issue.","examples":[10000]},"date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The day it counts for, in its author's time zone, as on their timesheet.","examples":["2026-10-12"]},"startedAt":{"type":"string","description":"When it started, ISO 8601 in UTC.","examples":["2026-10-12T08:00:00.000Z"]},"timeSpentSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Time logged, in seconds.","examples":[5400]},"billableSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The billable part of it, in seconds.","examples":[3600]},"billableMode":{"enum":["auto","full","none","custom"],"type":"string","description":"How the billable part is worked out: `auto` from the account, `full`, `none`, or `custom`."},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"What was done.","examples":["Release checks"]},"workType":{"anyOf":[{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"The work type's id.","examples":[3]}},"required":["id"]},{"type":"null"}],"description":"Its work type, if any."},"account":{"anyOf":[{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"The account's id.","examples":[7]}},"required":["id"]},{"type":"null"}],"description":"The LogQuill account the time is for, if any."},"overtime":{"type":"boolean","description":"Marked as overtime: outside the daily hours limit."},"fields":{"type":"object","propertyNames":{"type":"string","pattern":"^\\d+$"},"additionalProperties":{"anyOf":[{"type":"string","maxLength":255},{"type":"number"},{"type":"boolean"}]},"description":"Custom worklog field values, by field id.","examples":[{"12":"Client meeting"}]},"origin":{"enum":["logquill","jira","tempo","api","mcp"],"type":"string","description":"Where it was made: `logquill` (in the app), `jira` (in Jira, by hand or by another app), `tempo` (imported from Tempo), `api` or `mcp` (an AI assistant).","examples":["logquill"]},"createdAt":{"type":"string","description":"When it was made in LogQuill.","examples":["2026-10-12T08:00:00.000Z"]},"updatedAt":{"type":"string","description":"When it last changed.","examples":["2026-10-12T08:00:00.000Z"]}},"required":["id","jiraWorklogId","author","issue","projectId","date","startedAt","timeSpentSeconds","billableSeconds","billableMode","description","workType","account","overtime","fields","origin","createdAt","updatedAt"]}},"metadata":{"type":"object","properties":{"count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"How many results this page holds.","examples":[100]},"limit":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The most a page holds, as asked.","examples":[100]},"next":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The full address of the next page, or null on the last one.","examples":["https://api.logquill.com/v1/worklogs?from=2026-10-01&to=2026-10-31&cursor=WyIyMDI2LTEwLTEyVDA4OjAwOjAwLjAwMFoiLDEyM10="]}},"required":["count","limit","next"]}},"required":["results","metadata"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"security":[{"apiKey":[]}]},"post":{"operationId":"worklogs.create","summary":"Log time","description":"Logs time as the key's owner, in LogQuill and in Jira, with the site's rules (fields, daily limits, locked timesheets).\n\n**Scope:** `worklogs:write`","tags":["Worklogs"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"issue":{"anyOf":[{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"The Jira issue's id.","examples":[10232]}},"required":["id"]},{"type":"object","properties":{"key":{"type":"string","pattern":"^[A-Za-z][A-Za-z0-9_]*-\\d+$","description":"The Jira issue's key.","examples":["ABC-123"]}},"required":["key"]}],"description":"The Jira issue, by `id` or by `key`."},"date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The day to log on, YYYY-MM-DD, in your own time zone.","examples":["2026-10-14"]},"timeSpentSeconds":{"type":"integer","minimum":60,"maximum":86400,"description":"Time to log, in seconds: 60 (1 minute) to 86400 (24 hours).","examples":[5400]},"description":{"type":"string","maxLength":100,"description":"What was done, 100 characters at most.","examples":["Release checks"]},"workType":{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"The work type's id.","examples":[3]}},"required":["id"],"description":"Its work type. Required when your site requires one."},"account":{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"The account's id.","examples":[7]}},"required":["id"],"description":"The LogQuill account. Left out: the issue's account, if any."},"billable":{"type":"object","properties":{"mode":{"enum":["auto","full","none","custom"],"type":"string","description":"`auto`: as the account says. `full`: all of it. `none`: none of it. `custom`: `seconds` of it."},"seconds":{"type":"integer","minimum":0,"maximum":9007199254740991,"description":"With `custom`: how many seconds are billable.","examples":[3600]}},"required":["mode"],"description":"Left out: the account's default."},"overtime":{"type":"boolean","description":"Mark as overtime, where your site offers it."},"fields":{"type":"object","propertyNames":{"type":"string","pattern":"^\\d+$"},"additionalProperties":{"anyOf":[{"type":"string","maxLength":255},{"type":"number"},{"type":"boolean"}]},"description":"Custom field values, by field id. Values for fields that don't apply to the issue are dropped.","examples":[{"12":"Client meeting"}]}},"required":["issue","date","timeSpentSeconds"]}}}},"responses":{"201":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"LogQuill's id for it.","examples":[123]},"jiraWorklogId":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Jira's id for it.","examples":["10848"]},"author":{"type":"object","properties":{"accountId":{"type":"string","description":"Their Jira account id.","examples":["712020:4d42d4f9-1a2b-4c3d-8e9f-0a1b2c3d4e5f"]},"displayName":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Their name in Jira.","examples":["Alex Martin"]}},"required":["accountId","displayName"],"description":"Whose time it is."},"issue":{"anyOf":[{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"The Jira issue's id.","examples":[10232]}},"required":["id"]},{"type":"null"}],"description":"The Jira issue it was logged on."},"projectId":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"The Jira project of its issue.","examples":[10000]},"date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The day it counts for, in its author's time zone, as on their timesheet.","examples":["2026-10-12"]},"startedAt":{"type":"string","description":"When it started, ISO 8601 in UTC.","examples":["2026-10-12T08:00:00.000Z"]},"timeSpentSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Time logged, in seconds.","examples":[5400]},"billableSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The billable part of it, in seconds.","examples":[3600]},"billableMode":{"enum":["auto","full","none","custom"],"type":"string","description":"How the billable part is worked out: `auto` from the account, `full`, `none`, or `custom`."},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"What was done.","examples":["Release checks"]},"workType":{"anyOf":[{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"The work type's id.","examples":[3]}},"required":["id"]},{"type":"null"}],"description":"Its work type, if any."},"account":{"anyOf":[{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"The account's id.","examples":[7]}},"required":["id"]},{"type":"null"}],"description":"The LogQuill account the time is for, if any."},"overtime":{"type":"boolean","description":"Marked as overtime: outside the daily hours limit."},"fields":{"type":"object","propertyNames":{"type":"string","pattern":"^\\d+$"},"additionalProperties":{"anyOf":[{"type":"string","maxLength":255},{"type":"number"},{"type":"boolean"}]},"description":"Custom worklog field values, by field id.","examples":[{"12":"Client meeting"}]},"origin":{"enum":["logquill","jira","tempo","api","mcp"],"type":"string","description":"Where it was made: `logquill` (in the app), `jira` (in Jira, by hand or by another app), `tempo` (imported from Tempo), `api` or `mcp` (an AI assistant).","examples":["logquill"]},"createdAt":{"type":"string","description":"When it was made in LogQuill.","examples":["2026-10-12T08:00:00.000Z"]},"updatedAt":{"type":"string","description":"When it last changed.","examples":["2026-10-12T08:00:00.000Z"]}},"required":["id","jiraWorklogId","author","issue","projectId","date","startedAt","timeSpentSeconds","billableSeconds","billableMode","description","workType","account","overtime","fields","origin","createdAt","updatedAt"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"security":[{"apiKey":[]}]}},"/worklogs/{id}":{"get":{"operationId":"worklogs.get","summary":"Get a worklog","description":"One worklog the key's owner may see.\n\n**Scope:** `worklogs:read`","tags":["Worklogs"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"Its id, as the list gives it.","examples":[123]}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"LogQuill's id for it.","examples":[123]},"jiraWorklogId":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Jira's id for it.","examples":["10848"]},"author":{"type":"object","properties":{"accountId":{"type":"string","description":"Their Jira account id.","examples":["712020:4d42d4f9-1a2b-4c3d-8e9f-0a1b2c3d4e5f"]},"displayName":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Their name in Jira.","examples":["Alex Martin"]}},"required":["accountId","displayName"],"description":"Whose time it is."},"issue":{"anyOf":[{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"The Jira issue's id.","examples":[10232]}},"required":["id"]},{"type":"null"}],"description":"The Jira issue it was logged on."},"projectId":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"The Jira project of its issue.","examples":[10000]},"date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The day it counts for, in its author's time zone, as on their timesheet.","examples":["2026-10-12"]},"startedAt":{"type":"string","description":"When it started, ISO 8601 in UTC.","examples":["2026-10-12T08:00:00.000Z"]},"timeSpentSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Time logged, in seconds.","examples":[5400]},"billableSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The billable part of it, in seconds.","examples":[3600]},"billableMode":{"enum":["auto","full","none","custom"],"type":"string","description":"How the billable part is worked out: `auto` from the account, `full`, `none`, or `custom`."},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"What was done.","examples":["Release checks"]},"workType":{"anyOf":[{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"The work type's id.","examples":[3]}},"required":["id"]},{"type":"null"}],"description":"Its work type, if any."},"account":{"anyOf":[{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"The account's id.","examples":[7]}},"required":["id"]},{"type":"null"}],"description":"The LogQuill account the time is for, if any."},"overtime":{"type":"boolean","description":"Marked as overtime: outside the daily hours limit."},"fields":{"type":"object","propertyNames":{"type":"string","pattern":"^\\d+$"},"additionalProperties":{"anyOf":[{"type":"string","maxLength":255},{"type":"number"},{"type":"boolean"}]},"description":"Custom worklog field values, by field id.","examples":[{"12":"Client meeting"}]},"origin":{"enum":["logquill","jira","tempo","api","mcp"],"type":"string","description":"Where it was made: `logquill` (in the app), `jira` (in Jira, by hand or by another app), `tempo` (imported from Tempo), `api` or `mcp` (an AI assistant).","examples":["logquill"]},"createdAt":{"type":"string","description":"When it was made in LogQuill.","examples":["2026-10-12T08:00:00.000Z"]},"updatedAt":{"type":"string","description":"When it last changed.","examples":["2026-10-12T08:00:00.000Z"]}},"required":["id","jiraWorklogId","author","issue","projectId","date","startedAt","timeSpentSeconds","billableSeconds","billableMode","description","workType","account","overtime","fields","origin","createdAt","updatedAt"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"security":[{"apiKey":[]}]},"patch":{"operationId":"worklogs.update","summary":"Change a worklog","description":"Only the key owner's own worklogs.\n\n**Scope:** `worklogs:write`","tags":["Worklogs"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"The worklog's id.","examples":[123]}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"issue":{"anyOf":[{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"The Jira issue's id.","examples":[10232]}},"required":["id"]},{"type":"object","properties":{"key":{"type":"string","pattern":"^[A-Za-z][A-Za-z0-9_]*-\\d+$","description":"The Jira issue's key.","examples":["ABC-123"]}},"required":["key"]}],"description":"Move it to this issue."},"date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Move it to this day, YYYY-MM-DD.","examples":["2026-10-15"]},"timeSpentSeconds":{"type":"integer","minimum":60,"maximum":86400,"description":"Time to log, in seconds: 60 (1 minute) to 86400 (24 hours).","examples":[5400]},"description":{"type":"string","maxLength":100,"description":"What was done, 100 characters at most.","examples":["Release checks"]},"workType":{"anyOf":[{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"The work type's id.","examples":[3]}},"required":["id"]},{"type":"null"}],"description":"null clears it, where work types are optional."},"account":{"anyOf":[{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"The account's id.","examples":[7]}},"required":["id"]},{"type":"null"}],"description":"null goes back to the issue's account."},"billable":{"type":"object","properties":{"mode":{"enum":["auto","full","none","custom"],"type":"string","description":"`auto`: as the account says. `full`: all of it. `none`: none of it. `custom`: `seconds` of it."},"seconds":{"type":"integer","minimum":0,"maximum":9007199254740991,"description":"With `custom`: how many seconds are billable.","examples":[3600]}},"required":["mode"],"description":"How much of it is billable."},"overtime":{"type":"boolean","description":"Mark or unmark as overtime."},"fields":{"type":"object","propertyNames":{"type":"string","pattern":"^\\d+$"},"additionalProperties":{"anyOf":[{"anyOf":[{"type":"string","maxLength":255},{"type":"number"},{"type":"boolean"}]},{"type":"null"}]},"description":"Only the fields to change, by field id; null clears one.","examples":[{"12":null}]}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"LogQuill's id for it.","examples":[123]},"jiraWorklogId":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Jira's id for it.","examples":["10848"]},"author":{"type":"object","properties":{"accountId":{"type":"string","description":"Their Jira account id.","examples":["712020:4d42d4f9-1a2b-4c3d-8e9f-0a1b2c3d4e5f"]},"displayName":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Their name in Jira.","examples":["Alex Martin"]}},"required":["accountId","displayName"],"description":"Whose time it is."},"issue":{"anyOf":[{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"The Jira issue's id.","examples":[10232]}},"required":["id"]},{"type":"null"}],"description":"The Jira issue it was logged on."},"projectId":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"The Jira project of its issue.","examples":[10000]},"date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The day it counts for, in its author's time zone, as on their timesheet.","examples":["2026-10-12"]},"startedAt":{"type":"string","description":"When it started, ISO 8601 in UTC.","examples":["2026-10-12T08:00:00.000Z"]},"timeSpentSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Time logged, in seconds.","examples":[5400]},"billableSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The billable part of it, in seconds.","examples":[3600]},"billableMode":{"enum":["auto","full","none","custom"],"type":"string","description":"How the billable part is worked out: `auto` from the account, `full`, `none`, or `custom`."},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"What was done.","examples":["Release checks"]},"workType":{"anyOf":[{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"The work type's id.","examples":[3]}},"required":["id"]},{"type":"null"}],"description":"Its work type, if any."},"account":{"anyOf":[{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"The account's id.","examples":[7]}},"required":["id"]},{"type":"null"}],"description":"The LogQuill account the time is for, if any."},"overtime":{"type":"boolean","description":"Marked as overtime: outside the daily hours limit."},"fields":{"type":"object","propertyNames":{"type":"string","pattern":"^\\d+$"},"additionalProperties":{"anyOf":[{"type":"string","maxLength":255},{"type":"number"},{"type":"boolean"}]},"description":"Custom worklog field values, by field id.","examples":[{"12":"Client meeting"}]},"origin":{"enum":["logquill","jira","tempo","api","mcp"],"type":"string","description":"Where it was made: `logquill` (in the app), `jira` (in Jira, by hand or by another app), `tempo` (imported from Tempo), `api` or `mcp` (an AI assistant).","examples":["logquill"]},"createdAt":{"type":"string","description":"When it was made in LogQuill.","examples":["2026-10-12T08:00:00.000Z"]},"updatedAt":{"type":"string","description":"When it last changed.","examples":["2026-10-12T08:00:00.000Z"]}},"required":["id","jiraWorklogId","author","issue","projectId","date","startedAt","timeSpentSeconds","billableSeconds","billableMode","description","workType","account","overtime","fields","origin","createdAt","updatedAt"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"security":[{"apiKey":[]}]},"delete":{"operationId":"worklogs.delete","summary":"Delete a worklog","description":"Only the key owner's own worklogs, in LogQuill and in Jira.\n\n**Scope:** `worklogs:write`","tags":["Worklogs"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"Its id, as the list gives it.","examples":[123]}}],"responses":{"204":{"description":"OK","content":{"application/json":{"schema":{"anyOf":[{"not":{}},{"not":{}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"security":[{"apiKey":[]}]}},"/plans":{"get":{"operationId":"plans.list","summary":"List plans","description":"Plans in a period that the key's owner may see.\n\n**Scope:** `plans:read`","tags":["Plans"],"parameters":[{"name":"from","in":"query","required":true,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The first day, YYYY-MM-DD.","examples":["2026-10-01"]},"allowEmptyValue":true,"allowReserved":true},{"name":"to","in":"query","required":true,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The last day, YYYY-MM-DD, included. At most 366 days after `from`.","examples":["2026-10-31"]},"allowEmptyValue":true,"allowReserved":true},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":1000,"default":100,"description":"How many results a page holds: 1 to 1000.","examples":[100]},"allowEmptyValue":true,"allowReserved":true},{"name":"cursor","in":"query","required":false,"schema":{"type":"string","maxLength":512,"description":"Where the page starts. Don't build it: follow the previous page's `metadata.next`, which holds it."},"allowEmptyValue":true,"allowReserved":true},{"name":"accountId","in":"query","required":false,"schema":{"type":"string","minLength":1,"maxLength":128,"description":"Only this person's; `me` for the key's owner. Left out: everyone's you may see."},"allowEmptyValue":true,"allowReserved":true},{"name":"issueId","in":"query","required":false,"schema":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"Only those on this Jira issue.","examples":[10232]},"allowEmptyValue":true,"allowReserved":true},{"name":"projectId","in":"query","required":false,"schema":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"Only those in this Jira project.","examples":[10000]},"allowEmptyValue":true,"allowReserved":true},{"name":"updatedFrom","in":"query","required":false,"schema":{"type":"string","format":"date-time","description":"Only those changed at or after this moment, ISO 8601 in UTC: to keep another system in step.","examples":["2026-10-14T06:00:00Z"]},"allowEmptyValue":true,"allowReserved":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"results":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"LogQuill's id for it.","examples":[456]},"person":{"type":"object","properties":{"accountId":{"type":"string","description":"Their Jira account id.","examples":["712020:4d42d4f9-1a2b-4c3d-8e9f-0a1b2c3d4e5f"]},"displayName":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Their name in Jira.","examples":["Alex Martin"]}},"required":["accountId","displayName"],"description":"Whose plan it is."},"issue":{"anyOf":[{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"The Jira issue's id.","examples":[10232]}},"required":["id"]},{"type":"null"}],"description":"The Jira issue it's planned on."},"projectId":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"The Jira project of its issue.","examples":[10000]},"date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The day it's planned on: a plan is one day.","examples":["2026-10-12"]},"plannedSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Time planned that day, in seconds.","examples":[7200]},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"What's planned.","examples":["Sprint review prep"]},"origin":{"enum":["logquill","jira","tempo","api","mcp"],"type":"string","description":"Where it was made: `logquill` (in the app), `jira` (in Jira, by hand or by another app), `tempo` (imported from Tempo), `api` or `mcp` (an AI assistant).","examples":["logquill"]},"createdAt":{"type":"string","description":"When it was made.","examples":["2026-10-12T08:00:00.000Z"]},"updatedAt":{"type":"string","description":"When it last changed.","examples":["2026-10-12T08:00:00.000Z"]}},"required":["id","person","issue","projectId","date","plannedSeconds","description","origin","createdAt","updatedAt"]}},"metadata":{"type":"object","properties":{"count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"How many results this page holds.","examples":[100]},"limit":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The most a page holds, as asked.","examples":[100]},"next":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The full address of the next page, or null on the last one.","examples":["https://api.logquill.com/v1/plans?from=2026-10-01&to=2026-10-31&cursor=WyIyMDI2LTEwLTEyIiw0NTZd"]}},"required":["count","limit","next"]}},"required":["results","metadata"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"security":[{"apiKey":[]}]},"post":{"operationId":"plans.create","summary":"Plan time","description":"Plans time as the key's owner on each day from `startDate` to `endDate`, one plan a day. In Jira, plans first fill the issue's original estimate; only the time planned beyond it is added to the remaining estimate.\n\n**Scope:** `plans:write`","tags":["Plans"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"issue":{"anyOf":[{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"The Jira issue's id.","examples":[10232]}},"required":["id"]},{"type":"object","properties":{"key":{"type":"string","pattern":"^[A-Za-z][A-Za-z0-9_]*-\\d+$","description":"The Jira issue's key.","examples":["ABC-123"]}},"required":["key"]}],"description":"The Jira issue, by `id` or by `key`."},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The first day, YYYY-MM-DD.","examples":["2026-10-19"]},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The last day, included. Left out: the start day only. Each day gets its own plan.","examples":["2026-10-21"]},"plannedSecondsPerDay":{"type":"integer","minimum":60,"maximum":86400,"description":"Time to plan for the day, in seconds: 60 to 86400.","examples":[7200]},"description":{"type":"string","maxLength":100,"description":"What was done, 100 characters at most.","examples":["Release checks"]}},"required":["issue","startDate","plannedSecondsPerDay"]}}}},"responses":{"201":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"results":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"LogQuill's id for it.","examples":[456]},"person":{"type":"object","properties":{"accountId":{"type":"string","description":"Their Jira account id.","examples":["712020:4d42d4f9-1a2b-4c3d-8e9f-0a1b2c3d4e5f"]},"displayName":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Their name in Jira.","examples":["Alex Martin"]}},"required":["accountId","displayName"],"description":"Whose plan it is."},"issue":{"anyOf":[{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"The Jira issue's id.","examples":[10232]}},"required":["id"]},{"type":"null"}],"description":"The Jira issue it's planned on."},"projectId":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"The Jira project of its issue.","examples":[10000]},"date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The day it's planned on: a plan is one day.","examples":["2026-10-12"]},"plannedSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Time planned that day, in seconds.","examples":[7200]},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"What's planned.","examples":["Sprint review prep"]},"origin":{"enum":["logquill","jira","tempo","api","mcp"],"type":"string","description":"Where it was made: `logquill` (in the app), `jira` (in Jira, by hand or by another app), `tempo` (imported from Tempo), `api` or `mcp` (an AI assistant).","examples":["logquill"]},"createdAt":{"type":"string","description":"When it was made.","examples":["2026-10-12T08:00:00.000Z"]},"updatedAt":{"type":"string","description":"When it last changed.","examples":["2026-10-12T08:00:00.000Z"]}},"required":["id","person","issue","projectId","date","plannedSeconds","description","origin","createdAt","updatedAt"]},"description":"The plans made: one a day."}},"required":["results"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"security":[{"apiKey":[]}]}},"/plans/{id}":{"get":{"operationId":"plans.get","summary":"Get a plan","description":"One plan the key's owner may see.\n\n**Scope:** `plans:read`","tags":["Plans"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"Its id, as the list gives it.","examples":[123]}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"LogQuill's id for it.","examples":[456]},"person":{"type":"object","properties":{"accountId":{"type":"string","description":"Their Jira account id.","examples":["712020:4d42d4f9-1a2b-4c3d-8e9f-0a1b2c3d4e5f"]},"displayName":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Their name in Jira.","examples":["Alex Martin"]}},"required":["accountId","displayName"],"description":"Whose plan it is."},"issue":{"anyOf":[{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"The Jira issue's id.","examples":[10232]}},"required":["id"]},{"type":"null"}],"description":"The Jira issue it's planned on."},"projectId":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"The Jira project of its issue.","examples":[10000]},"date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The day it's planned on: a plan is one day.","examples":["2026-10-12"]},"plannedSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Time planned that day, in seconds.","examples":[7200]},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"What's planned.","examples":["Sprint review prep"]},"origin":{"enum":["logquill","jira","tempo","api","mcp"],"type":"string","description":"Where it was made: `logquill` (in the app), `jira` (in Jira, by hand or by another app), `tempo` (imported from Tempo), `api` or `mcp` (an AI assistant).","examples":["logquill"]},"createdAt":{"type":"string","description":"When it was made.","examples":["2026-10-12T08:00:00.000Z"]},"updatedAt":{"type":"string","description":"When it last changed.","examples":["2026-10-12T08:00:00.000Z"]}},"required":["id","person","issue","projectId","date","plannedSeconds","description","origin","createdAt","updatedAt"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"security":[{"apiKey":[]}]},"patch":{"operationId":"plans.update","summary":"Change a plan","description":"Only the key owner's own plans.\n\n**Scope:** `plans:write`","tags":["Plans"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"The plan's id.","examples":[456]}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"issue":{"anyOf":[{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"The Jira issue's id.","examples":[10232]}},"required":["id"]},{"type":"object","properties":{"key":{"type":"string","pattern":"^[A-Za-z][A-Za-z0-9_]*-\\d+$","description":"The Jira issue's key.","examples":["ABC-123"]}},"required":["key"]}],"description":"Move it to this issue."},"date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Move it to this day, YYYY-MM-DD.","examples":["2026-10-20"]},"plannedSeconds":{"type":"integer","minimum":60,"maximum":86400,"description":"Time to plan for the day, in seconds: 60 to 86400.","examples":[7200]},"description":{"type":"string","maxLength":100,"description":"What was done, 100 characters at most.","examples":["Release checks"]}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"LogQuill's id for it.","examples":[456]},"person":{"type":"object","properties":{"accountId":{"type":"string","description":"Their Jira account id.","examples":["712020:4d42d4f9-1a2b-4c3d-8e9f-0a1b2c3d4e5f"]},"displayName":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Their name in Jira.","examples":["Alex Martin"]}},"required":["accountId","displayName"],"description":"Whose plan it is."},"issue":{"anyOf":[{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"The Jira issue's id.","examples":[10232]}},"required":["id"]},{"type":"null"}],"description":"The Jira issue it's planned on."},"projectId":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"The Jira project of its issue.","examples":[10000]},"date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The day it's planned on: a plan is one day.","examples":["2026-10-12"]},"plannedSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Time planned that day, in seconds.","examples":[7200]},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"What's planned.","examples":["Sprint review prep"]},"origin":{"enum":["logquill","jira","tempo","api","mcp"],"type":"string","description":"Where it was made: `logquill` (in the app), `jira` (in Jira, by hand or by another app), `tempo` (imported from Tempo), `api` or `mcp` (an AI assistant).","examples":["logquill"]},"createdAt":{"type":"string","description":"When it was made.","examples":["2026-10-12T08:00:00.000Z"]},"updatedAt":{"type":"string","description":"When it last changed.","examples":["2026-10-12T08:00:00.000Z"]}},"required":["id","person","issue","projectId","date","plannedSeconds","description","origin","createdAt","updatedAt"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"security":[{"apiKey":[]}]},"delete":{"operationId":"plans.delete","summary":"Delete a plan","description":"Only the key owner's own plans.\n\n**Scope:** `plans:write`","tags":["Plans"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"Its id, as the list gives it.","examples":[123]}}],"responses":{"204":{"description":"OK","content":{"application/json":{"schema":{"anyOf":[{"not":{}},{"not":{}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"security":[{"apiKey":[]}]}},"/timesheets":{"get":{"operationId":"timesheets.get","summary":"Get a timesheet","description":"One person's timesheet for the period holding `date`: your own, or someone whose timesheets you review. Says whether it can be submitted, and to which teams.\n\n**Scope:** `timesheets:read`","tags":["Timesheets"],"parameters":[{"name":"date","in":"query","required":true,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Any day in the period wanted, YYYY-MM-DD.","examples":["2026-10-14"]},"allowEmptyValue":true,"allowReserved":true},{"name":"accountId","in":"query","required":false,"schema":{"type":"string","minLength":1,"maxLength":128,"description":"Whose timesheet. Left out: your own."},"allowEmptyValue":true,"allowReserved":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The timesheet's id, to approve or reject it. Null until it's first submitted.","examples":["9b8a7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d"]},"person":{"type":"object","properties":{"accountId":{"type":"string","description":"Their Jira account id.","examples":["712020:4d42d4f9-1a2b-4c3d-8e9f-0a1b2c3d4e5f"]},"displayName":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Their name in Jira.","examples":["Alex Martin"]}},"required":["accountId","displayName"],"description":"Whose timesheet it is."},"periodStart":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The period's first day.","examples":["2026-10-12"]},"periodEnd":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The period's last day.","examples":["2026-10-18"]},"status":{"enum":["open","submitted","approved"],"type":"string","description":"`open`: not submitted, or sent back. `submitted`: waiting for review. `approved`."},"team":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"The team's id.","examples":["3f2b6c1e-8d4a-4f5b-9c7e-2a1d0b9e8f7a"]},"name":{"type":"string","description":"The team's name.","examples":["Platform"]}},"required":["id","name"]},{"type":"null"}],"description":"The team it was submitted to, while submitted or approved."},"submittedAt":{"anyOf":[{"type":"string","description":"When it was submitted.","examples":["2026-10-12T08:00:00.000Z"]},{"type":"null"}]},"reviewedAt":{"anyOf":[{"type":"string","description":"When it was last approved or sent back.","examples":["2026-10-20T09:30:00.000Z"]},{"type":"null"}]},"requiredSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Time expected in the period, after holidays and days off.","examples":[144000]},"loggedSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Time logged.","examples":[140400]},"countedSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Logged time that counts, after the site's rules (for example extra hours).","examples":[140400]},"plannedSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Time planned.","examples":[0]},"missingSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Required minus counted, after the site's tolerance; 0 when nothing is missing.","examples":[3600]},"days":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The day.","examples":["2026-10-12"]},"requiredSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Time expected that day.","examples":[28800]},"loggedSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Time logged that day.","examples":[27000]},"countedSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Logged time that counts that day.","examples":[27000]},"plannedSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Time planned that day.","examples":[0]},"holiday":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The public holiday that day, if any.","examples":["Armistice Day"]},"absence":{"anyOf":[{"type":"object","properties":{"type":{"anyOf":[{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The absence type's id.","examples":[1]},"name":{"type":"string","description":"Its name.","examples":["Paid leave"]}},"required":["id","name"]},{"type":"null"}],"description":"Its type, for those who may see it; null otherwise."},"part":{"enum":["full","morning","afternoon"],"type":"string","description":"The part of the day it takes."}},"required":["type","part"]},{"type":"null"}],"description":"An approved absence that day, which takes its required time off."}},"required":["date","requiredSeconds","loggedSeconds","countedSeconds","plannedSeconds","holiday","absence"]},"description":"Each day of the period."},"canSubmit":{"type":"boolean","description":"Whether the key's owner may submit it now."},"blockReason":{"anyOf":[{"enum":["periodNotEnded","noTeams","onlyLeader","alreadySubmitted","approved","incomplete","noTimeTracking"],"type":"string"},{"type":"null"}],"description":"Why it can't be submitted now: `periodNotEnded`, `noTeams`, `onlyLeader`, `alreadySubmitted`, `approved`, `incomplete` (time is missing), `noTimeTracking`."},"submitTo":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The team's id.","examples":["3f2b6c1e-8d4a-4f5b-9c7e-2a1d0b9e8f7a"]},"name":{"type":"string","description":"The team's name.","examples":["Platform"]}},"required":["id","name"]},"description":"The teams it can be submitted to: use one's `id` to submit."},"canReview":{"type":"boolean","description":"Whether the key's owner may approve or reject it."}},"required":["id","person","periodStart","periodEnd","status","team","submittedAt","reviewedAt","requiredSeconds","loggedSeconds","countedSeconds","plannedSeconds","missingSeconds","days","canSubmit","blockReason","submitTo","canReview"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"security":[{"apiKey":[]}]}},"/teams/{id}/timesheets":{"get":{"operationId":"timesheets.team","summary":"A team's timesheets","description":"Every member's timesheet for the period holding `date`, for those who review the team's timesheets.\n\n**Scope:** `timesheets:read`","tags":["Timesheets"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","description":"The team's id.","examples":["3f2b6c1e-8d4a-4f5b-9c7e-2a1d0b9e8f7a"]}},{"name":"date","in":"query","required":true,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Any day in the period wanted, YYYY-MM-DD.","examples":["2026-10-14"]},"allowEmptyValue":true,"allowReserved":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"periodStart":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The period's first day.","examples":["2026-10-12"]},"periodEnd":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The period's last day.","examples":["2026-10-18"]},"results":{"type":"array","items":{"type":"object","properties":{"person":{"type":"object","properties":{"accountId":{"type":"string","description":"Their Jira account id.","examples":["712020:4d42d4f9-1a2b-4c3d-8e9f-0a1b2c3d4e5f"]},"displayName":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Their name in Jira.","examples":["Alex Martin"]}},"required":["accountId","displayName"]},"timesheetId":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The timesheet's id, to approve or reject it. Null until it's submitted.","examples":["9b8a7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d"]},"status":{"enum":["open","submitted","approved"],"type":"string","description":"`open`: not submitted, or sent back. `submitted`: waiting for review. `approved`."},"submittedAt":{"anyOf":[{"type":"string","description":"When it was submitted.","examples":["2026-10-12T08:00:00.000Z"]},{"type":"null"}]},"requiredSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Time expected in the period, after holidays and days off.","examples":[144000]},"loggedSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Time logged.","examples":[140400]},"countedSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Logged time that counts, after the site's rules (for example extra hours).","examples":[140400]},"plannedSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Time planned.","examples":[0]},"missingSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Required minus counted, after the site's tolerance; 0 when nothing is missing.","examples":[3600]}},"required":["person","timesheetId","status","submittedAt","requiredSeconds","loggedSeconds","countedSeconds","plannedSeconds","missingSeconds"]},"description":"Each member's timesheet for the period."}},"required":["periodStart","periodEnd","results"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"security":[{"apiKey":[]}]}},"/timesheets/submit":{"post":{"operationId":"timesheets.submit","summary":"Submit a timesheet","description":"Submits the timesheet for the period holding `date` to one of its `submitTo` teams, with the site's rules (finished period, no missing time unless allowed). Any day of the period stands for the whole of it, and the answer names the period (`periodStart`, `periodEnd`). A period that hasn't ended is refused with `data.previousPeriod`, the last one that has; a team it can't go to, with `data.submitTo`. Your own, or a member's if you lead their team. The team's reviewers are emailed as in LogQuill.\n\n**Scope:** `timesheets:write`","tags":["Timesheets"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Any day in the period to submit, YYYY-MM-DD.","examples":["2026-10-14"]},"teamId":{"type":"string","format":"uuid","description":"The team to submit it to: one of the timesheet's `submitTo`.","examples":["3f2b6c1e-8d4a-4f5b-9c7e-2a1d0b9e8f7a"]},"accountId":{"type":"string","minLength":1,"maxLength":128,"description":"Whose timesheet. Left out: your own. A team leader may submit for their members."},"note":{"type":"string","maxLength":1000,"description":"A note for the reviewer.","examples":["Two days on site"]}},"required":["date","teamId"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The timesheet's id, to approve or reject it. Null until it's first submitted.","examples":["9b8a7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d"]},"person":{"type":"object","properties":{"accountId":{"type":"string","description":"Their Jira account id.","examples":["712020:4d42d4f9-1a2b-4c3d-8e9f-0a1b2c3d4e5f"]},"displayName":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Their name in Jira.","examples":["Alex Martin"]}},"required":["accountId","displayName"],"description":"Whose timesheet it is."},"periodStart":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The period's first day.","examples":["2026-10-12"]},"periodEnd":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The period's last day.","examples":["2026-10-18"]},"status":{"enum":["open","submitted","approved"],"type":"string","description":"`open`: not submitted, or sent back. `submitted`: waiting for review. `approved`."},"team":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"The team's id.","examples":["3f2b6c1e-8d4a-4f5b-9c7e-2a1d0b9e8f7a"]},"name":{"type":"string","description":"The team's name.","examples":["Platform"]}},"required":["id","name"]},{"type":"null"}],"description":"The team it was submitted to, while submitted or approved."},"submittedAt":{"anyOf":[{"type":"string","description":"When it was submitted.","examples":["2026-10-12T08:00:00.000Z"]},{"type":"null"}]},"reviewedAt":{"anyOf":[{"type":"string","description":"When it was last approved or sent back.","examples":["2026-10-20T09:30:00.000Z"]},{"type":"null"}]},"requiredSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Time expected in the period, after holidays and days off.","examples":[144000]},"loggedSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Time logged.","examples":[140400]},"countedSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Logged time that counts, after the site's rules (for example extra hours).","examples":[140400]},"plannedSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Time planned.","examples":[0]},"missingSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Required minus counted, after the site's tolerance; 0 when nothing is missing.","examples":[3600]},"days":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The day.","examples":["2026-10-12"]},"requiredSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Time expected that day.","examples":[28800]},"loggedSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Time logged that day.","examples":[27000]},"countedSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Logged time that counts that day.","examples":[27000]},"plannedSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Time planned that day.","examples":[0]},"holiday":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The public holiday that day, if any.","examples":["Armistice Day"]},"absence":{"anyOf":[{"type":"object","properties":{"type":{"anyOf":[{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The absence type's id.","examples":[1]},"name":{"type":"string","description":"Its name.","examples":["Paid leave"]}},"required":["id","name"]},{"type":"null"}],"description":"Its type, for those who may see it; null otherwise."},"part":{"enum":["full","morning","afternoon"],"type":"string","description":"The part of the day it takes."}},"required":["type","part"]},{"type":"null"}],"description":"An approved absence that day, which takes its required time off."}},"required":["date","requiredSeconds","loggedSeconds","countedSeconds","plannedSeconds","holiday","absence"]},"description":"Each day of the period."},"canSubmit":{"type":"boolean","description":"Whether the key's owner may submit it now."},"blockReason":{"anyOf":[{"enum":["periodNotEnded","noTeams","onlyLeader","alreadySubmitted","approved","incomplete","noTimeTracking"],"type":"string"},{"type":"null"}],"description":"Why it can't be submitted now: `periodNotEnded`, `noTeams`, `onlyLeader`, `alreadySubmitted`, `approved`, `incomplete` (time is missing), `noTimeTracking`."},"submitTo":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The team's id.","examples":["3f2b6c1e-8d4a-4f5b-9c7e-2a1d0b9e8f7a"]},"name":{"type":"string","description":"The team's name.","examples":["Platform"]}},"required":["id","name"]},"description":"The teams it can be submitted to: use one's `id` to submit."},"canReview":{"type":"boolean","description":"Whether the key's owner may approve or reject it."}},"required":["id","person","periodStart","periodEnd","status","team","submittedAt","reviewedAt","requiredSeconds","loggedSeconds","countedSeconds","plannedSeconds","missingSeconds","days","canSubmit","blockReason","submitTo","canReview"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"security":[{"apiKey":[]}]}},"/timesheets/{id}/approve":{"post":{"operationId":"timesheets.approve","summary":"Approve a timesheet","description":"Approves a submitted timesheet you review (never your own). Its owner is emailed as in LogQuill.\n\n**Scope:** `timesheets:write`","tags":["Timesheets"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","description":"The timesheet's id.","examples":["9b8a7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d"]}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"note":{"type":"string","maxLength":1000,"description":"A note for its owner: the reason, when sending it back.","examples":["Missing Friday afternoon"]}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The timesheet's id, to approve or reject it. Null until it's first submitted.","examples":["9b8a7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d"]},"person":{"type":"object","properties":{"accountId":{"type":"string","description":"Their Jira account id.","examples":["712020:4d42d4f9-1a2b-4c3d-8e9f-0a1b2c3d4e5f"]},"displayName":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Their name in Jira.","examples":["Alex Martin"]}},"required":["accountId","displayName"],"description":"Whose timesheet it is."},"periodStart":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The period's first day.","examples":["2026-10-12"]},"periodEnd":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The period's last day.","examples":["2026-10-18"]},"status":{"enum":["open","submitted","approved"],"type":"string","description":"`open`: not submitted, or sent back. `submitted`: waiting for review. `approved`."},"team":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"The team's id.","examples":["3f2b6c1e-8d4a-4f5b-9c7e-2a1d0b9e8f7a"]},"name":{"type":"string","description":"The team's name.","examples":["Platform"]}},"required":["id","name"]},{"type":"null"}],"description":"The team it was submitted to, while submitted or approved."},"submittedAt":{"anyOf":[{"type":"string","description":"When it was submitted.","examples":["2026-10-12T08:00:00.000Z"]},{"type":"null"}]},"reviewedAt":{"anyOf":[{"type":"string","description":"When it was last approved or sent back.","examples":["2026-10-20T09:30:00.000Z"]},{"type":"null"}]},"requiredSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Time expected in the period, after holidays and days off.","examples":[144000]},"loggedSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Time logged.","examples":[140400]},"countedSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Logged time that counts, after the site's rules (for example extra hours).","examples":[140400]},"plannedSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Time planned.","examples":[0]},"missingSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Required minus counted, after the site's tolerance; 0 when nothing is missing.","examples":[3600]},"days":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The day.","examples":["2026-10-12"]},"requiredSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Time expected that day.","examples":[28800]},"loggedSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Time logged that day.","examples":[27000]},"countedSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Logged time that counts that day.","examples":[27000]},"plannedSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Time planned that day.","examples":[0]},"holiday":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The public holiday that day, if any.","examples":["Armistice Day"]},"absence":{"anyOf":[{"type":"object","properties":{"type":{"anyOf":[{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The absence type's id.","examples":[1]},"name":{"type":"string","description":"Its name.","examples":["Paid leave"]}},"required":["id","name"]},{"type":"null"}],"description":"Its type, for those who may see it; null otherwise."},"part":{"enum":["full","morning","afternoon"],"type":"string","description":"The part of the day it takes."}},"required":["type","part"]},{"type":"null"}],"description":"An approved absence that day, which takes its required time off."}},"required":["date","requiredSeconds","loggedSeconds","countedSeconds","plannedSeconds","holiday","absence"]},"description":"Each day of the period."},"canSubmit":{"type":"boolean","description":"Whether the key's owner may submit it now."},"blockReason":{"anyOf":[{"enum":["periodNotEnded","noTeams","onlyLeader","alreadySubmitted","approved","incomplete","noTimeTracking"],"type":"string"},{"type":"null"}],"description":"Why it can't be submitted now: `periodNotEnded`, `noTeams`, `onlyLeader`, `alreadySubmitted`, `approved`, `incomplete` (time is missing), `noTimeTracking`."},"submitTo":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The team's id.","examples":["3f2b6c1e-8d4a-4f5b-9c7e-2a1d0b9e8f7a"]},"name":{"type":"string","description":"The team's name.","examples":["Platform"]}},"required":["id","name"]},"description":"The teams it can be submitted to: use one's `id` to submit."},"canReview":{"type":"boolean","description":"Whether the key's owner may approve or reject it."}},"required":["id","person","periodStart","periodEnd","status","team","submittedAt","reviewedAt","requiredSeconds","loggedSeconds","countedSeconds","plannedSeconds","missingSeconds","days","canSubmit","blockReason","submitTo","canReview"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"security":[{"apiKey":[]}]}},"/timesheets/{id}/reject":{"post":{"operationId":"timesheets.reject","summary":"Send a timesheet back","description":"Sends a submitted or approved timesheet back to its owner, open again, with `note` as the reason.\n\n**Scope:** `timesheets:write`","tags":["Timesheets"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","description":"The timesheet's id.","examples":["9b8a7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d"]}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"note":{"type":"string","maxLength":1000,"description":"A note for its owner: the reason, when sending it back.","examples":["Missing Friday afternoon"]}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The timesheet's id, to approve or reject it. Null until it's first submitted.","examples":["9b8a7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d"]},"person":{"type":"object","properties":{"accountId":{"type":"string","description":"Their Jira account id.","examples":["712020:4d42d4f9-1a2b-4c3d-8e9f-0a1b2c3d4e5f"]},"displayName":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Their name in Jira.","examples":["Alex Martin"]}},"required":["accountId","displayName"],"description":"Whose timesheet it is."},"periodStart":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The period's first day.","examples":["2026-10-12"]},"periodEnd":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The period's last day.","examples":["2026-10-18"]},"status":{"enum":["open","submitted","approved"],"type":"string","description":"`open`: not submitted, or sent back. `submitted`: waiting for review. `approved`."},"team":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"The team's id.","examples":["3f2b6c1e-8d4a-4f5b-9c7e-2a1d0b9e8f7a"]},"name":{"type":"string","description":"The team's name.","examples":["Platform"]}},"required":["id","name"]},{"type":"null"}],"description":"The team it was submitted to, while submitted or approved."},"submittedAt":{"anyOf":[{"type":"string","description":"When it was submitted.","examples":["2026-10-12T08:00:00.000Z"]},{"type":"null"}]},"reviewedAt":{"anyOf":[{"type":"string","description":"When it was last approved or sent back.","examples":["2026-10-20T09:30:00.000Z"]},{"type":"null"}]},"requiredSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Time expected in the period, after holidays and days off.","examples":[144000]},"loggedSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Time logged.","examples":[140400]},"countedSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Logged time that counts, after the site's rules (for example extra hours).","examples":[140400]},"plannedSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Time planned.","examples":[0]},"missingSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Required minus counted, after the site's tolerance; 0 when nothing is missing.","examples":[3600]},"days":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The day.","examples":["2026-10-12"]},"requiredSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Time expected that day.","examples":[28800]},"loggedSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Time logged that day.","examples":[27000]},"countedSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Logged time that counts that day.","examples":[27000]},"plannedSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Time planned that day.","examples":[0]},"holiday":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The public holiday that day, if any.","examples":["Armistice Day"]},"absence":{"anyOf":[{"type":"object","properties":{"type":{"anyOf":[{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The absence type's id.","examples":[1]},"name":{"type":"string","description":"Its name.","examples":["Paid leave"]}},"required":["id","name"]},{"type":"null"}],"description":"Its type, for those who may see it; null otherwise."},"part":{"enum":["full","morning","afternoon"],"type":"string","description":"The part of the day it takes."}},"required":["type","part"]},{"type":"null"}],"description":"An approved absence that day, which takes its required time off."}},"required":["date","requiredSeconds","loggedSeconds","countedSeconds","plannedSeconds","holiday","absence"]},"description":"Each day of the period."},"canSubmit":{"type":"boolean","description":"Whether the key's owner may submit it now."},"blockReason":{"anyOf":[{"enum":["periodNotEnded","noTeams","onlyLeader","alreadySubmitted","approved","incomplete","noTimeTracking"],"type":"string"},{"type":"null"}],"description":"Why it can't be submitted now: `periodNotEnded`, `noTeams`, `onlyLeader`, `alreadySubmitted`, `approved`, `incomplete` (time is missing), `noTimeTracking`."},"submitTo":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The team's id.","examples":["3f2b6c1e-8d4a-4f5b-9c7e-2a1d0b9e8f7a"]},"name":{"type":"string","description":"The team's name.","examples":["Platform"]}},"required":["id","name"]},"description":"The teams it can be submitted to: use one's `id` to submit."},"canReview":{"type":"boolean","description":"Whether the key's owner may approve or reject it."}},"required":["id","person","periodStart","periodEnd","status","team","submittedAt","reviewedAt","requiredSeconds","loggedSeconds","countedSeconds","plannedSeconds","missingSeconds","days","canSubmit","blockReason","submitTo","canReview"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"security":[{"apiKey":[]}]}},"/time":{"get":{"operationId":"time","summary":"Time totals","description":"Logged, billable and planned time in a period, totalled by what `groupBy` names, over what the key's owner may see. With `day` in `groupBy`, rows come day by day, in date order, however many pages the period takes.\n\n**Scope:** `time:read`","tags":["Time"],"parameters":[{"name":"from","in":"query","required":true,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The first day, YYYY-MM-DD.","examples":["2026-10-01"]},"allowEmptyValue":true,"allowReserved":true},{"name":"to","in":"query","required":true,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The last day, YYYY-MM-DD, included. At most 366 days after `from`.","examples":["2026-10-31"]},"allowEmptyValue":true,"allowReserved":true},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":1000,"default":100,"description":"How many results a page holds: 1 to 1000.","examples":[100]},"allowEmptyValue":true,"allowReserved":true},{"name":"cursor","in":"query","required":false,"schema":{"type":"string","maxLength":512,"description":"Where the page starts. Don't build it: follow the previous page's `metadata.next`, which holds it."},"allowEmptyValue":true,"allowReserved":true},{"name":"groupBy","in":"query","required":false,"schema":{"type":"string","pattern":"^(person|issue|project|account|workType|day)(,(person|issue|project|account|workType|day))*$","default":"person","description":"What to total by, one or more, comma-separated: `person`, `issue`, `project`, `account`, `workType`, `day`. Each row is one combination of them.","examples":["person","person,day","account,project"]},"allowEmptyValue":true,"allowReserved":true},{"name":"type","in":"query","required":false,"schema":{"enum":["worklogs","plans","both"],"type":"string","default":"both","description":"Which time: `worklogs` (logged), `plans` (planned), or `both`."},"allowEmptyValue":true,"allowReserved":true},{"name":"accountId","in":"query","required":false,"schema":{"type":"string","minLength":1,"maxLength":128,"description":"Only this person's time; `me` for the key's owner. Left out: everyone's you may see."},"allowEmptyValue":true,"allowReserved":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"results":{"type":"array","items":{"type":"object","properties":{"person":{"type":"object","properties":{"accountId":{"type":"string","description":"Their Jira account id.","examples":["712020:4d42d4f9-1a2b-4c3d-8e9f-0a1b2c3d4e5f"]},"displayName":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Their name in Jira.","examples":["Alex Martin"]}},"required":["accountId","displayName"],"description":"With `groupBy` person."},"issue":{"anyOf":[{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"The Jira issue's id.","examples":[10232]}},"required":["id"]},{"type":"null"}],"description":"With `groupBy` issue. Null: no issue."},"project":{"anyOf":[{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"The Jira project's id.","examples":[10000]}},"required":["id"]},{"type":"null"}],"description":"With `groupBy` project. Null: time whose issue isn't placed in a project yet."},"account":{"anyOf":[{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"The account's id.","examples":[7]}},"required":["id"]},{"type":"null"}],"description":"With `groupBy` account. Null: no account."},"workType":{"anyOf":[{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"The work type's id.","examples":[3]}},"required":["id"]},{"type":"null"}],"description":"With `groupBy` workType. Null: none."},"day":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"With `groupBy` day: the day, in each person's time zone.","examples":["2026-10-12"]},"loggedSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Time logged.","examples":[576000]},"billableSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The billable part of it.","examples":[432000]},"plannedSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Time planned.","examples":[0]}},"required":["loggedSeconds","billableSeconds","plannedSeconds"]}},"metadata":{"type":"object","properties":{"count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"How many results this page holds.","examples":[100]},"limit":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The most a page holds, as asked.","examples":[100]},"next":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The full address of the next page, or null on the last one.","examples":["https://api.logquill.com/v1/time?from=2025-10-01&to=2026-09-30&groupBy=person&limit=100&cursor=MTAw"]}},"required":["count","limit","next"]}},"required":["results","metadata"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"security":[{"apiKey":[]}]}},"/issues":{"get":{"operationId":"issues","summary":"Name issues","description":"The key and summary of Jira issues other answers name by id (`issue: { id }`), as Jira shows them to the key's owner. Only issues with time the owner may see.\n\n**Scope:** `time:read`","tags":["Time"],"parameters":[{"name":"ids","in":"query","required":true,"schema":{"type":"string","pattern":"^\\d{1,12}(,\\d{1,12}){0,99}$","description":"Up to 100 Jira issue ids, comma-separated, as the other answers give them.","examples":["10232,10233"]},"allowEmptyValue":true,"allowReserved":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"results":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"The Jira issue's id.","examples":[10232]},"key":{"type":"string","description":"Its key.","examples":["BET-5"]},"summary":{"type":"string","description":"Its summary.","examples":["Export to CSV"]},"project":{"anyOf":[{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0}},"required":["id"]},{"type":"null"}],"description":"The project it is in."}},"required":["id","key","summary","project"]}},"unknown":{"type":"array","items":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"description":"Ids asked for that can't be named: no time you may see on them, or hidden from you in Jira."}},"required":["results","unknown"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"security":[{"apiKey":[]}]}},"/projects":{"get":{"operationId":"projects","summary":"Name projects","description":"The key and name of Jira projects other answers name by id (`project: { id }`), as Jira shows them. Only projects with time the key's owner may see, or that they lead.\n\n**Scope:** `time:read`","tags":["Time"],"parameters":[{"name":"ids","in":"query","required":true,"schema":{"type":"string","pattern":"^\\d{1,12}(,\\d{1,12}){0,99}$","description":"Up to 100 Jira project ids, comma-separated, as the other answers give them.","examples":["10000,10001"]},"allowEmptyValue":true,"allowReserved":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"results":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"The Jira project's id.","examples":[10000]},"key":{"type":"string","description":"Its key.","examples":["BET"]},"name":{"type":"string","description":"Its name.","examples":["Beta Platform"]},"archived":{"type":"boolean","description":"Archived in Jira."}},"required":["id","key","name","archived"]}},"unknown":{"type":"array","items":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"description":"Ids asked for that can't be named: no time you may see in them, or hidden from you in Jira."}},"required":["results","unknown"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"security":[{"apiKey":[]}]}},"/teams":{"get":{"operationId":"teams.list","summary":"List teams","description":"The teams the key's owner may see.\n\n**Scope:** `teams:read`","tags":["Teams"],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"results":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The team's id.","examples":["3f2b6c1e-8d4a-4f5b-9c7e-2a1d0b9e8f7a"]},"name":{"type":"string","description":"Its name.","examples":["Platform"]},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"What it does.","examples":["Core services"]},"country":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Whose public holidays its members take, as a country code. Null: none set.","examples":["FR"]},"type":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"The team type's id."},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Its name.","examples":["Technical"]}},"required":["id","name"]},{"type":"null"}],"description":"Its team type, if any."},"leader":{"anyOf":[{"type":"object","properties":{"accountId":{"type":"string","description":"Their Jira account id.","examples":["712020:4d42d4f9-1a2b-4c3d-8e9f-0a1b2c3d4e5f"]},"displayName":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Their name in Jira.","examples":["Alex Martin"]}},"required":["accountId","displayName"]},{"type":"null"}],"description":"Who leads it."},"memberCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"How many people are in it.","examples":[8]},"projectIds":{"type":"array","items":{"type":"string"},"description":"The Jira projects it works on, by id.","examples":[["10000","10001"]]}},"required":["id","name","description","country","type","leader","memberCount","projectIds"]}}},"required":["results"]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"security":[{"apiKey":[]}]}},"/teams/{id}":{"get":{"operationId":"teams.get","summary":"Get a team","description":"A team and its members.\n\n**Scope:** `teams:read`","tags":["Teams"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","description":"The team's id.","examples":["3f2b6c1e-8d4a-4f5b-9c7e-2a1d0b9e8f7a"]}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"The team's id.","examples":["3f2b6c1e-8d4a-4f5b-9c7e-2a1d0b9e8f7a"]},"name":{"type":"string","description":"Its name.","examples":["Platform"]},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"What it does.","examples":["Core services"]},"country":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Whose public holidays its members take, as a country code. Null: none set.","examples":["FR"]},"type":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"The team type's id."},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Its name.","examples":["Technical"]}},"required":["id","name"]},{"type":"null"}],"description":"Its team type, if any."},"leader":{"anyOf":[{"type":"object","properties":{"accountId":{"type":"string","description":"Their Jira account id.","examples":["712020:4d42d4f9-1a2b-4c3d-8e9f-0a1b2c3d4e5f"]},"displayName":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Their name in Jira.","examples":["Alex Martin"]}},"required":["accountId","displayName"]},{"type":"null"}],"description":"Who leads it."},"memberCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"How many people are in it.","examples":[8]},"projectIds":{"type":"array","items":{"type":"string"},"description":"The Jira projects it works on, by id.","examples":[["10000","10001"]]},"members":{"type":"array","items":{"type":"object","properties":{"accountId":{"type":"string","description":"Their Jira account id.","examples":["712020:4d42d4f9-1a2b-4c3d-8e9f-0a1b2c3d4e5f"]},"displayName":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Their name in Jira.","examples":["Alex Martin"]},"role":{"enum":["leader","member"],"type":"string","description":"`leader` or `member`."},"joinedAt":{"type":"string","description":"When they joined the team.","examples":["2026-03-02T09:00:00.000Z"]}},"required":["accountId","displayName","role","joinedAt"]},"description":"Everyone in the team."}},"required":["id","name","description","country","type","leader","memberCount","projectIds","members"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"security":[{"apiKey":[]}]}},"/absences":{"get":{"operationId":"absences.list","summary":"List absences","description":"Absences touching a period, in date order, as LogQuill shows them: your own, your teams' and those you approve; everyone's for HR and whoever sees everyone's time. Waiting, rejected and cancelled ones only for their person, their approvers and HR. Their type and note only for those who may know them. With `updatedFrom`, only those changed since: to keep a payroll or HR system in step.\n\n**Scope:** `absences:read`","tags":["Absences"],"parameters":[{"name":"from","in":"query","required":true,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The first day, YYYY-MM-DD.","examples":["2026-10-01"]},"allowEmptyValue":true,"allowReserved":true},{"name":"to","in":"query","required":true,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The last day, YYYY-MM-DD, included. At most 366 days after `from`.","examples":["2026-10-31"]},"allowEmptyValue":true,"allowReserved":true},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":1000,"default":100,"description":"How many results a page holds: 1 to 1000.","examples":[100]},"allowEmptyValue":true,"allowReserved":true},{"name":"cursor","in":"query","required":false,"schema":{"type":"string","maxLength":512,"description":"Where the page starts. Don't build it: follow the previous page's `metadata.next`, which holds it."},"allowEmptyValue":true,"allowReserved":true},{"name":"accountId","in":"query","required":false,"schema":{"type":"string","minLength":1,"maxLength":128,"description":"Only this person's; `me` for the key's owner. Left out: everyone's you may see."},"allowEmptyValue":true,"allowReserved":true},{"name":"teamId","in":"query","required":false,"schema":{"type":"string","format":"uuid","description":"Only the members of this team.","examples":["3f2b6c1e-8d4a-4f5b-9c7e-2a1d0b9e8f7a"]},"allowEmptyValue":true,"allowReserved":true},{"name":"status","in":"query","required":false,"schema":{"enum":["pending","approved","cancelling","rejected","cancelled"],"type":"string","description":"Only those with this status. For payroll, `approved` (and `cancelling`, which still counts)."},"allowEmptyValue":true,"allowReserved":true},{"name":"updatedFrom","in":"query","required":false,"schema":{"type":"string","format":"date-time","description":"Only those changed at or after this moment, ISO 8601 in UTC: to keep another system in step.","examples":["2026-10-14T06:00:00Z"]},"allowEmptyValue":true,"allowReserved":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"results":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The absence's id.","examples":[4521]},"person":{"type":"object","properties":{"accountId":{"type":"string","description":"Their Jira account id.","examples":["712020:4d42d4f9-1a2b-4c3d-8e9f-0a1b2c3d4e5f"]},"displayName":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Their name in Jira.","examples":["Alex Martin"]}},"required":["accountId","displayName"],"description":"Whose absence it is."},"type":{"anyOf":[{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The absence type's id.","examples":[1]},"name":{"type":"string","description":"Its name.","examples":["Paid leave"]}},"required":["id","name"]},{"type":"null"}],"description":"Its type. Null when the key's owner may only know the person is away (sick leave is health data)."},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Its first day.","examples":["2026-11-02"]},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Its last day, included.","examples":["2026-11-06"]},"startPart":{"enum":["full","afternoon"],"type":"string","description":"`afternoon`: the first day starts at noon."},"endPart":{"enum":["full","morning"],"type":"string","description":"`morning`: the last day ends at noon."},"dayPart":{"enum":["full","morning","afternoon"],"type":"string","description":"`morning` or `afternoon`: only that half of every day of the range."},"workingDays":{"type":"number","description":"Working days it takes, half days as half: its person's weekdays, less their public holidays.","examples":[4.5]},"status":{"enum":["pending","approved","cancelling","rejected","cancelled"],"type":"string","description":"`pending`: waiting for approval. `approved`: it counts. `cancelling`: a cancellation is asked, it still counts. `rejected`, `cancelled`."},"source":{"enum":["logquill","odoo","google","microsoft"],"type":"string","description":"Where it came from: asked for in LogQuill, Odoo Time Off, or a calendar's Out of office event."},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Its person's note, for those who may see its type.","examples":["Family trip"]},"decidedAt":{"anyOf":[{"type":"string","description":"When it was last approved, rejected or cancelled.","examples":["2026-10-20T09:30:00.000Z"]},{"type":"null"}]},"createdAt":{"type":"string","description":"When it was asked for.","examples":["2026-10-14T08:00:00.000Z"]},"updatedAt":{"type":"string","description":"When it last changed.","examples":["2026-10-20T09:30:00.000Z"]}},"required":["id","person","type","startDate","endDate","startPart","endPart","dayPart","workingDays","status","source","note","decidedAt","createdAt","updatedAt"]}},"metadata":{"type":"object","properties":{"count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"How many results this page holds.","examples":[100]},"limit":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The most a page holds, as asked.","examples":[100]},"next":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The full address of the next page, or null on the last one.","examples":["https://api.logquill.com/v1/absences?from=2026-01-01&to=2026-12-31&cursor=WyIyMDI2LTExLTAyIiw0NTIxXQ=="]}},"required":["count","limit","next"]}},"required":["results","metadata"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"security":[{"apiKey":[]}]},"post":{"operationId":"absences.request","summary":"Request time off","description":"Asks for time off as the key's owner, sick leave included, with the site's rules: the type must be available, the days must be working days, not taken by another of their absences, and within their balance when the type has an allowance. It then waits for approval and its approvers are emailed, or it is approved at once for a type that needs none. A type that asks for a supporting document (a sick note) takes it in LogQuill afterwards.\n\n**Scope:** `absences:write`","tags":["Absences"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"typeId":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"The absence type, from `/absence-types`: paid leave, sick leave...","examples":[1]},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The first day off.","examples":["2026-11-02"]},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The last day off, included. Left out: the first day only.","examples":["2026-11-06"]},"startPart":{"enum":["full","afternoon"],"type":"string","default":"full","description":"`afternoon`: the first day starts at noon."},"endPart":{"enum":["full","morning"],"type":"string","default":"full","description":"`morning`: the last day ends at noon."},"dayPart":{"enum":["full","morning","afternoon"],"type":"string","default":"full","description":"`morning` or `afternoon`: only that half of every day. The first and last days are then like the others."},"note":{"type":"string","maxLength":500,"description":"For whoever approves it. Only they and HR see it.","examples":["Family trip"]}},"required":["typeId","startDate"],"description":"The time off. A supporting document (a sick note) is added in LogQuill afterwards."}}}},"responses":{"201":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The absence's id.","examples":[4521]},"person":{"type":"object","properties":{"accountId":{"type":"string","description":"Their Jira account id.","examples":["712020:4d42d4f9-1a2b-4c3d-8e9f-0a1b2c3d4e5f"]},"displayName":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Their name in Jira.","examples":["Alex Martin"]}},"required":["accountId","displayName"],"description":"Whose absence it is."},"type":{"anyOf":[{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The absence type's id.","examples":[1]},"name":{"type":"string","description":"Its name.","examples":["Paid leave"]}},"required":["id","name"]},{"type":"null"}],"description":"Its type. Null when the key's owner may only know the person is away (sick leave is health data)."},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Its first day.","examples":["2026-11-02"]},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Its last day, included.","examples":["2026-11-06"]},"startPart":{"enum":["full","afternoon"],"type":"string","description":"`afternoon`: the first day starts at noon."},"endPart":{"enum":["full","morning"],"type":"string","description":"`morning`: the last day ends at noon."},"dayPart":{"enum":["full","morning","afternoon"],"type":"string","description":"`morning` or `afternoon`: only that half of every day of the range."},"workingDays":{"type":"number","description":"Working days it takes, half days as half: its person's weekdays, less their public holidays.","examples":[4.5]},"status":{"enum":["pending","approved","cancelling","rejected","cancelled"],"type":"string","description":"`pending`: waiting for approval. `approved`: it counts. `cancelling`: a cancellation is asked, it still counts. `rejected`, `cancelled`."},"source":{"enum":["logquill","odoo","google","microsoft"],"type":"string","description":"Where it came from: asked for in LogQuill, Odoo Time Off, or a calendar's Out of office event."},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Its person's note, for those who may see its type.","examples":["Family trip"]},"decidedAt":{"anyOf":[{"type":"string","description":"When it was last approved, rejected or cancelled.","examples":["2026-10-20T09:30:00.000Z"]},{"type":"null"}]},"createdAt":{"type":"string","description":"When it was asked for.","examples":["2026-10-14T08:00:00.000Z"]},"updatedAt":{"type":"string","description":"When it last changed.","examples":["2026-10-20T09:30:00.000Z"]}},"required":["id","person","type","startDate","endDate","startPart","endPart","dayPart","workingDays","status","source","note","decidedAt","createdAt","updatedAt"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"security":[{"apiKey":[]}]}},"/absences/{id}":{"get":{"operationId":"absences.get","summary":"Get an absence","description":"One absence, as the list gives it.\n\n**Scope:** `absences:read`","tags":["Absences"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"Its id, as the list gives it.","examples":[123]}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The absence's id.","examples":[4521]},"person":{"type":"object","properties":{"accountId":{"type":"string","description":"Their Jira account id.","examples":["712020:4d42d4f9-1a2b-4c3d-8e9f-0a1b2c3d4e5f"]},"displayName":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Their name in Jira.","examples":["Alex Martin"]}},"required":["accountId","displayName"],"description":"Whose absence it is."},"type":{"anyOf":[{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The absence type's id.","examples":[1]},"name":{"type":"string","description":"Its name.","examples":["Paid leave"]}},"required":["id","name"]},{"type":"null"}],"description":"Its type. Null when the key's owner may only know the person is away (sick leave is health data)."},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Its first day.","examples":["2026-11-02"]},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Its last day, included.","examples":["2026-11-06"]},"startPart":{"enum":["full","afternoon"],"type":"string","description":"`afternoon`: the first day starts at noon."},"endPart":{"enum":["full","morning"],"type":"string","description":"`morning`: the last day ends at noon."},"dayPart":{"enum":["full","morning","afternoon"],"type":"string","description":"`morning` or `afternoon`: only that half of every day of the range."},"workingDays":{"type":"number","description":"Working days it takes, half days as half: its person's weekdays, less their public holidays.","examples":[4.5]},"status":{"enum":["pending","approved","cancelling","rejected","cancelled"],"type":"string","description":"`pending`: waiting for approval. `approved`: it counts. `cancelling`: a cancellation is asked, it still counts. `rejected`, `cancelled`."},"source":{"enum":["logquill","odoo","google","microsoft"],"type":"string","description":"Where it came from: asked for in LogQuill, Odoo Time Off, or a calendar's Out of office event."},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Its person's note, for those who may see its type.","examples":["Family trip"]},"decidedAt":{"anyOf":[{"type":"string","description":"When it was last approved, rejected or cancelled.","examples":["2026-10-20T09:30:00.000Z"]},{"type":"null"}]},"createdAt":{"type":"string","description":"When it was asked for.","examples":["2026-10-14T08:00:00.000Z"]},"updatedAt":{"type":"string","description":"When it last changed.","examples":["2026-10-20T09:30:00.000Z"]}},"required":["id","person","type","startDate","endDate","startPart","endPart","dayPart","workingDays","status","source","note","decidedAt","createdAt","updatedAt"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"security":[{"apiKey":[]}]}},"/absences/{id}/cancel":{"post":{"operationId":"absences.cancel","summary":"Cancel an absence","description":"Cancels an absence of the key's owner, as LogQuill would: one still waiting is withdrawn; an approved one asks for the cancellation to be approved when its type needs approval, else it is cancelled (or ended early, once started).\n\n**Scope:** `absences:write`","tags":["Absences"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"Its id, as the list gives it.","examples":[123]}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"note":{"type":"string","maxLength":500,"description":"Why, for whoever approves the cancellation.","examples":["Plans changed"]}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The absence's id.","examples":[4521]},"person":{"type":"object","properties":{"accountId":{"type":"string","description":"Their Jira account id.","examples":["712020:4d42d4f9-1a2b-4c3d-8e9f-0a1b2c3d4e5f"]},"displayName":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Their name in Jira.","examples":["Alex Martin"]}},"required":["accountId","displayName"],"description":"Whose absence it is."},"type":{"anyOf":[{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The absence type's id.","examples":[1]},"name":{"type":"string","description":"Its name.","examples":["Paid leave"]}},"required":["id","name"]},{"type":"null"}],"description":"Its type. Null when the key's owner may only know the person is away (sick leave is health data)."},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Its first day.","examples":["2026-11-02"]},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Its last day, included.","examples":["2026-11-06"]},"startPart":{"enum":["full","afternoon"],"type":"string","description":"`afternoon`: the first day starts at noon."},"endPart":{"enum":["full","morning"],"type":"string","description":"`morning`: the last day ends at noon."},"dayPart":{"enum":["full","morning","afternoon"],"type":"string","description":"`morning` or `afternoon`: only that half of every day of the range."},"workingDays":{"type":"number","description":"Working days it takes, half days as half: its person's weekdays, less their public holidays.","examples":[4.5]},"status":{"enum":["pending","approved","cancelling","rejected","cancelled"],"type":"string","description":"`pending`: waiting for approval. `approved`: it counts. `cancelling`: a cancellation is asked, it still counts. `rejected`, `cancelled`."},"source":{"enum":["logquill","odoo","google","microsoft"],"type":"string","description":"Where it came from: asked for in LogQuill, Odoo Time Off, or a calendar's Out of office event."},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Its person's note, for those who may see its type.","examples":["Family trip"]},"decidedAt":{"anyOf":[{"type":"string","description":"When it was last approved, rejected or cancelled.","examples":["2026-10-20T09:30:00.000Z"]},{"type":"null"}]},"createdAt":{"type":"string","description":"When it was asked for.","examples":["2026-10-14T08:00:00.000Z"]},"updatedAt":{"type":"string","description":"When it last changed.","examples":["2026-10-20T09:30:00.000Z"]}},"required":["id","person","type","startDate","endDate","startPart","endPart","dayPart","workingDays","status","source","note","decidedAt","createdAt","updatedAt"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"security":[{"apiKey":[]}]}},"/absence-types":{"get":{"operationId":"absences.types","summary":"List absence types","description":"The site's absence types, removed ones included (old absences keep theirs).\n\n**Scope:** `absences:read`","tags":["Absences"],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"results":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The type's id.","examples":[1]},"name":{"type":"string","description":"Its name.","examples":["Paid leave"]},"needsApproval":{"type":"boolean","description":"Whether its absences are approved before they count."},"logging":{"enum":["allowed","blocked"],"type":"string","description":"Whether time can be logged on its days."},"countsAsOvertime":{"type":"boolean","description":"Whether time logged on its days counts as overtime."},"removed":{"type":"boolean","description":"Removed: absences of it keep it, new ones can't take it."}},"required":["id","name","needsApproval","logging","countsAsOvertime","removed"]}}},"required":["results"]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"security":[{"apiKey":[]}]}},"/balances":{"get":{"operationId":"absences.balances","summary":"List leave balances","description":"Each person's leave balances, one per absence type with an allowance plan for them, worked out today as LogQuill shows them: days that may still be asked for this leave year, what was earned, taken and carried over, and days about to be lost. For yourself, the people whose absences you approve, the teams you lead, and everyone for HR and whoever may see absence types. By name.\n\n**Scope:** `absences:read`","tags":["Absences"],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":1000,"default":100,"description":"How many results a page holds: 1 to 1000.","examples":[100]},"allowEmptyValue":true,"allowReserved":true},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":512,"description":"Where the page starts. Don't build it: follow the previous page's `metadata.next`, which holds it."},"allowEmptyValue":true,"allowReserved":true},{"name":"accountId","in":"query","schema":{"type":"string","minLength":1,"maxLength":128,"description":"Only this person's; `me` for the key's owner. Left out: everyone's you may see."},"allowEmptyValue":true,"allowReserved":true},{"name":"teamId","in":"query","schema":{"type":"string","format":"uuid","description":"Only the members of this team.","examples":["3f2b6c1e-8d4a-4f5b-9c7e-2a1d0b9e8f7a"]},"allowEmptyValue":true,"allowReserved":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"results":{"type":"array","items":{"type":"object","properties":{"person":{"type":"object","properties":{"accountId":{"type":"string","description":"Their Jira account id.","examples":["712020:4d42d4f9-1a2b-4c3d-8e9f-0a1b2c3d4e5f"]},"displayName":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Their name in Jira.","examples":["Alex Martin"]}},"required":["accountId","displayName"],"description":"Whose balances they are."},"balances":{"type":"array","items":{"type":"object","properties":{"type":{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"name":{"type":"string"}},"required":["id","name"],"description":"The absence type.","examples":[{"id":1,"name":"Paid leave"}]},"plan":{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"name":{"type":"string"}},"required":["id","name"],"description":"The allowance plan it follows.","examples":[{"id":2,"name":"Standard"}]},"available":{"type":"number","description":"Days that may still be asked for this leave year, approved and pending absences counted. Below zero: that many short.","examples":[12.5]},"later":{"anyOf":[{"type":"object","properties":{"yearStart":{"type":"string"},"short":{"type":"number"}},"required":["yearStart","short"]},{"type":"null"}],"description":"A later leave year whose absences need more days than it will have: its first day, and how many short."},"yearStart":{"type":"string","description":"The first day of the current leave year, YYYY-MM-DD.","examples":["2026-01-01"]},"carriedIn":{"type":"number","description":"Days carried into this leave year.","examples":[3]},"earned":{"type":"number","description":"Days earned this leave year so far.","examples":[20.83]},"used":{"type":"number","description":"Days taken this leave year so far.","examples":[7]},"approvedDays":{"type":"number","description":"Days of approved absences this leave year and later, taken or to come.","examples":[9]},"pendingDays":{"type":"number","description":"Days of absences waiting for approval, this leave year and later. Only this year's are counted in `available`; a later year short of days shows in `later`.","examples":[2]},"expiring":{"anyOf":[{"type":"object","properties":{"days":{"type":"number"},"on":{"type":"string"}},"required":["days","on"]},{"type":"null"}],"description":"The next carried days to be lost if not used, and the day they go."}},"required":["type","plan","available","later","yearStart","carriedIn","earned","used","approvedDays","pendingDays","expiring"]},"description":"One per absence type with an allowance plan for them; empty without any."}},"required":["person","balances"]}},"metadata":{"type":"object","properties":{"count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"How many results this page holds.","examples":[100]},"limit":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The most a page holds, as asked.","examples":[100]},"next":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The full address of the next page, or null on the last one.","examples":["https://api.logquill.com/v1/balances?cursor=WyJBbGV4IiwiM2YyYjZjMWUiXQ=="]}},"required":["count","limit","next"]}},"required":["results","metadata"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"security":[{"apiKey":[]}]}}}}