[{"data":1,"prerenderedAt":1867},["ShallowReactive",2],{"navigation":3,"\u002Freference\u002Fapi":80,"\u002Freference\u002Fapi-surround":1862},[4,9,14,50,75],{"title":5,"path":6,"stem":7,"icon":8},"Getting started","\u002Fgetting-started","1.getting-started","i-lucide-rocket",{"title":10,"path":11,"stem":12,"icon":13},"Installation","\u002Finstallation","2.installation","i-lucide-hard-drive-download",{"title":15,"path":16,"stem":17,"children":18,"page":49},"Guide","\u002Fguide","3.guide",[19,24,29,34,39,44],{"title":20,"path":21,"stem":22,"icon":23},"Timer & entries","\u002Fguide\u002Ftimer-and-entries","3.guide\u002F1.timer-and-entries","i-lucide-timer",{"title":25,"path":26,"stem":27,"icon":28},"Projects, clients & tasks","\u002Fguide\u002Fprojects-clients-tasks","3.guide\u002F2.projects-clients-tasks","i-lucide-git-branch",{"title":30,"path":31,"stem":32,"icon":33},"Reports & calendar","\u002Fguide\u002Freports-calendar","3.guide\u002F3.reports-calendar","i-lucide-chart-column",{"title":35,"path":36,"stem":37,"icon":38},"Theme editor","\u002Fguide\u002Ftheme-editor","3.guide\u002F4.theme-editor","i-lucide-palette",{"title":40,"path":41,"stem":42,"icon":43},"Importing data","\u002Fguide\u002Fimport","3.guide\u002F5.import","i-lucide-hard-drive-upload",{"title":45,"path":46,"stem":47,"icon":48},"Team & organizations","\u002Fguide\u002Fteam","3.guide\u002F6.team","i-lucide-users",false,{"title":51,"path":52,"stem":53,"children":54,"page":49},"Reference","\u002Freference","4.reference",[55,60,65,70],{"title":56,"path":57,"stem":58,"icon":59},"Data model","\u002Freference\u002Fdata-model","4.reference\u002F1.data-model","i-lucide-database",{"title":61,"path":62,"stem":63,"icon":64},"API routes","\u002Freference\u002Fapi","4.reference\u002F2.api","i-lucide-route",{"title":66,"path":67,"stem":68,"icon":69},"Environment variables","\u002Freference\u002Fenv","4.reference\u002F3.env","i-lucide-settings-2",{"title":71,"path":72,"stem":73,"icon":74},"Security","\u002Freference\u002Fsecurity","4.reference\u002F4.security","i-lucide-shield",{"title":76,"path":77,"stem":78,"icon":79},"About","\u002Fabout","5.about","i-lucide-info",{"id":81,"title":61,"body":82,"description":1856,"extension":1857,"meta":1858,"navigation":1859,"path":62,"seo":1860,"stem":63,"__hash__":1861},"docs\u002F4.reference\u002F2.api.md",{"type":83,"value":84,"toc":1844},"minimark",[85,110,200,223,238,270,275,427,431,528,532,539,636,649,653,768,774,1118,1122,1130,1339,1343,1422,1470,1474,1525,1529,1689,1693,1747,1751,1840],[86,87,88,89,93,94,97,98,105,106,109],"p",{},"All routes live under ",[90,91,92],"code",{},"\u002Fapi",", speak JSON, validate bodies and queries with zod, and require a session cookie — except ",[90,95,96],{},"\u002Fapi\u002Fauth\u002F*"," and the public invite lookup. Auth uses ",[99,100,104],"a",{"href":101,"rel":102},"https:\u002F\u002Fgithub.com\u002Fatinux\u002Fnuxt-auth-utils",[103],"nofollow","nuxt-auth-utils"," sealed session cookies; log in once with ",[90,107,108],{},"POST \u002Fapi\u002Fauth\u002Flogin"," and reuse the cookie.",[111,112,117],"pre",{"className":113,"code":114,"language":115,"meta":116,"style":116},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","# log in, keep the cookie, then use it\ncurl -sc tick.cookies -X POST http:\u002F\u002Flocalhost:3000\u002Fapi\u002Fauth\u002Flogin \\\n  -H 'content-type: application\u002Fjson' \\\n  -d '{\"email\":\"mara@example.com\",\"password\":\"tick-demo\"}'\ncurl -sb tick.cookies http:\u002F\u002Flocalhost:3000\u002Fapi\u002Fme\n","bash","",[90,118,119,128,155,173,187],{"__ignoreMap":116},[120,121,124],"span",{"class":122,"line":123},"line",1,[120,125,127],{"class":126},"sHwdD","# log in, keep the cookie, then use it\n",[120,129,131,135,139,142,145,148,151],{"class":122,"line":130},2,[120,132,134],{"class":133},"sBMFI","curl",[120,136,138],{"class":137},"sfazB"," -sc",[120,140,141],{"class":137}," tick.cookies",[120,143,144],{"class":137}," -X",[120,146,147],{"class":137}," POST",[120,149,150],{"class":137}," http:\u002F\u002Flocalhost:3000\u002Fapi\u002Fauth\u002Flogin",[120,152,154],{"class":153},"sTEyZ"," \\\n",[120,156,158,161,165,168,171],{"class":122,"line":157},3,[120,159,160],{"class":137},"  -H",[120,162,164],{"class":163},"sMK4o"," '",[120,166,167],{"class":137},"content-type: application\u002Fjson",[120,169,170],{"class":163},"'",[120,172,154],{"class":153},[120,174,176,179,181,184],{"class":122,"line":175},4,[120,177,178],{"class":137},"  -d",[120,180,164],{"class":163},[120,182,183],{"class":137},"{\"email\":\"mara@example.com\",\"password\":\"tick-demo\"}",[120,185,186],{"class":163},"'\n",[120,188,190,192,195,197],{"class":122,"line":189},5,[120,191,134],{"class":133},[120,193,194],{"class":137}," -sb",[120,196,141],{"class":137},[120,198,199],{"class":137}," http:\u002F\u002Flocalhost:3000\u002Fapi\u002Fme\n",[86,201,202,203,206,207,210,211,214,215,218,219,222],{},"The session cookie is ",[90,204,205],{},"Secure"," by default, so curl's jar won't send it back to anything but ",[90,208,209],{},"localhost","\u002F",[90,212,213],{},"127.0.0.1"," over plain HTTP — use HTTPS, or ",[90,216,217],{},"NUXT_SESSION_COOKIE_SECURE=false"," on a trusted network (see ",[99,220,71],{"href":221},"\u002Freference\u002Fsecurity#plain-http-and-the-secure-flag",").",[86,224,225,226,230,231,234,235,222],{},"Multi-user scoping: catalog and reporting routes operate on the whole ",[227,228,229],"strong",{},"org","; the timer and entry mutations operate on the ",[227,232,233],{},"current user",". Every request re-reads the caller's membership and role from the database, so removing or demoting a member takes effect immediately (see ",[99,236,71],{"href":237},"\u002Freference\u002Fsecurity#sessions",[239,240,241],"note",{},[86,242,243,244,247,248,252,253,256,257,260,261,265,266,269],{},"Cross-cutting behavior: ",[90,245,246],{},"POST \u002Fapi\u002Fauth\u002F{login,register,forgot,reset}"," are ",[99,249,251],{"href":250},"\u002Freference\u002Fsecurity#rate-limiting","rate-limited"," (429 + ",[90,254,255],{},"Retry-After","), API bodies are capped at 1 MB (413) except ",[90,258,259],{},"\u002Fapi\u002Fimport\u002F*"," at 5 MB, and ",[99,262,264],{"href":263},"\u002Freference\u002Fenv#variables","demo mode"," turns a set of destructive routes into ",[90,267,268],{},"403",".",[271,272,274],"h2",{"id":273},"auth","Auth",[276,277,278,294],"table",{},[279,280,281],"thead",{},[282,283,284,288,291],"tr",{},[285,286,287],"th",{},"Method",[285,289,290],{},"Route",[285,292,293],{},"Description",[295,296,297,342,365,377,404],"tbody",{},[282,298,299,303,308],{},[300,301,302],"td",{},"POST",[300,304,305],{},[90,306,307],{},"\u002Fapi\u002Fauth\u002Fregister",[300,309,310,313,314,317,318,320,321,325,326,329,330,333,334,337,338,341],{},[90,311,312],{},"{name, email, password, inviteToken?}"," → creates the user, sets the session. Without a token: new personal org, role ",[90,315,316],{},"owner",". With one: joins that org with the invite's role. ",[90,319,268],{}," when ",[99,322,324],{"href":323},"\u002Finstallation#registration-modes","registration"," is ",[90,327,328],{},"closed",", or ",[90,331,332],{},"invite"," without a token; ",[90,335,336],{},"409"," duplicate email; ",[90,339,340],{},"410"," unknown\u002Fexpired\u002Fused token",[282,343,344,346,351],{},[300,345,302],{},[300,347,348],{},[90,349,350],{},"\u002Fapi\u002Fauth\u002Flogin",[300,352,353,356,357,360,361,364],{},[90,354,355],{},"{email, password}"," → ",[90,358,359],{},"SessionUser",", sets the session. Generic ",[90,362,363],{},"401"," on bad credentials (never says which half was wrong)",[282,366,367,369,374],{},[300,368,302],{},[300,370,371],{},[90,372,373],{},"\u002Fapi\u002Fauth\u002Flogout",[300,375,376],{},"Clears the session",[282,378,379,381,386],{},[300,380,302],{},[300,382,383],{},[90,384,385],{},"\u002Fapi\u002Fauth\u002Fforgot",[300,387,388,391,392,395,396,399,400],{},[90,389,390],{},"{email}"," → always ",[90,393,394],{},"{ok: true}",", even for unknown addresses (no account enumeration). Known address: a ",[227,397,398],{},"1-hour single-use"," token is created and the reset link emailed — or logged to the server console when ",[99,401,403],{"href":402},"\u002Finstallation#email-smtp","SMTP is unset",[282,405,406,408,413],{},[300,407,302],{},[300,409,410],{},[90,411,412],{},"\u002Fapi\u002Fauth\u002Freset",[300,414,415,356,418,420,421,423,424],{},[90,416,417],{},"{token, password}",[90,419,394],{},". ",[90,422,340],{}," when the token is unknown, used or expired. Sets the new password, voids the user's other reset tokens and ",[227,425,426],{},"revokes every existing session",[271,428,430],{"id":429},"current-user","Current user",[276,432,433,443],{},[279,434,435],{},[282,436,437,439,441],{},[285,438,287],{},[285,440,290],{},[285,442,293],{},[295,444,445,464,485,509],{},[282,446,447,450,455],{},[300,448,449],{},"GET",[300,451,452],{},[90,453,454],{},"\u002Fapi\u002Fme",[300,456,457,458,460,461],{},"Fresh ",[90,459,359],{}," + saved ",[90,462,463],{},"theme",[282,465,466,469,474],{},[300,467,468],{},"PATCH",[300,470,471],{},[90,472,473],{},"\u002Fapi\u002Fme\u002Fprofile",[300,475,476,356,479,481,482,484],{},[90,477,478],{},"{name?, email?, defaultRate?}",[90,480,359],{},"; ",[90,483,336],{}," on duplicate email",[282,486,487,489,494],{},[300,488,468],{},[300,490,491],{},[90,492,493],{},"\u002Fapi\u002Fme\u002Fpassword",[300,495,496,356,499,501,502,504,505,508],{},[90,497,498],{},"{currentPassword, newPassword}",[90,500,394],{},". Generic ",[90,503,268],{}," when the current password is wrong. Revokes your ",[227,506,507],{},"other"," sessions and keeps this one",[282,510,511,513,518],{},[300,512,468],{},[300,514,515],{},[90,516,517],{},"\u002Fapi\u002Fme\u002Ftheme",[300,519,520,523,524,527],{},[90,521,522],{},"{theme}"," → persists the theme editor state to ",[90,525,526],{},"users.theme"," (jsonb). Known keys only, payload capped at 2 KB",[271,529,531],{"id":530},"timers","Timers",[86,533,534,535,538],{},"A user can run ",[227,536,537],{},"up to 10 timers at once",". Every timer is named by its entry id, so stopping or editing one leaves the others running.",[276,540,541,551],{},[279,542,543],{},[282,544,545,547,549],{},[285,546,287],{},[285,548,290],{},[285,550,293],{},[295,552,553,579,603,617],{},[282,554,555,557,562],{},[300,556,449],{},[300,558,559],{},[90,560,561],{},"\u002Fapi\u002Ftimers",[300,563,564,567,568,571,572,575,576],{},[90,565,566],{},"TimerState[]"," — every running timer, ordered ",[90,569,570],{},"start"," ascending (ties by id). ",[90,573,574],{},"[]"," when nothing is running, never a ",[90,577,578],{},"204",[282,580,581,583,587],{},[300,582,302],{},[300,584,585],{},[90,586,561],{},[300,588,589,356,592,595,596,602],{},[90,590,591],{},"{name?, refType?, refId?, billable?}",[90,593,594],{},"TimerState",". Stops nothing. ",[227,597,598,599],{},"409 ",[90,600,601],{},"Timer limit reached (10 running)."," at the cap",[282,604,605,607,612],{},[300,606,468],{},[300,608,609],{},[90,610,611],{},"\u002Fapi\u002Ftimers\u002F:id",[300,613,614,615],{},"Edit one running timer (name, reference, billable) → ",[90,616,594],{},[282,618,619,621,626],{},[300,620,302],{},[300,622,623],{},[90,624,625],{},"\u002Fapi\u002Ftimers\u002F:id\u002Fstop",[300,627,628,629,329,632,635],{},"→ ",[90,630,631],{},"EntryDto",[90,633,634],{},"null"," when under 1 second (discarded)",[86,637,638,640,641,644,645,648],{},[90,639,468],{}," and ",[90,642,643],{},"stop"," answer ",[90,646,647],{},"404 No timer running."," whenever the id is unknown, already stopped, trashed, or someone else's — the message is deliberately identical in all four cases, so it can't be used to prove that an id exists in another org.",[271,650,652],{"id":651},"entries","Entries",[276,654,655,665],{},[279,656,657],{},[282,658,659,661,663],{},[285,660,287],{},[285,662,290],{},[285,664,293],{},[295,666,667,686,701,713,728],{},[282,668,669,671,676],{},[300,670,449],{},[300,672,673],{},[90,674,675],{},"\u002Fapi\u002Fentries?from&to",[300,677,678,681,682,685],{},[90,679,680],{},"EntryDto[]"," in ",[90,683,684],{},"[from, to)",", newest first; excludes running + trashed",[282,687,688,690,695],{},[300,689,302],{},[300,691,692],{},[90,693,694],{},"\u002Fapi\u002Fentries",[300,696,697,698],{},"Manual entry: ",[90,699,700],{},"{name, refType?, refId?, billable?, rateOverride?, start, end, tags?}",[282,702,703,705,710],{},[300,704,468],{},[300,706,707],{},[90,708,709],{},"\u002Fapi\u002Fentries\u002F:id",[300,711,712],{},"Partial update, same fields",[282,714,715,718,722],{},[300,716,717],{},"DELETE",[300,719,720],{},[90,721,709],{},[300,723,724,725],{},"Soft delete → ",[90,726,727],{},"DeleteResult",[282,729,730,732,737],{},[300,731,302],{},[300,733,734],{},[90,735,736],{},"\u002Fapi\u002Fentries\u002Fbulk",[300,738,739,742,743,356,746,748,749,210,752,356,755,748,758,356,761,763,764,767],{},[90,740,741],{},"{ids, action: 'delete' | 'billable' | 'restore' | 'reassign', billable?, refType?, refId?}"," — up to 500 ids. ",[90,744,745],{},"delete",[90,747,727],{},", ",[90,750,751],{},"billable",[90,753,754],{},"restore",[90,756,757],{},"{count}",[90,759,760],{},"reassign",[90,762,680],{}," (null ",[90,765,766],{},"refType"," clears the reference)",[86,769,770,771,773],{},"An ",[90,772,631],{}," carries the resolved chain and money, so clients never compute either:",[111,775,779],{"className":776,"code":777,"language":778,"meta":116,"style":116},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{\n  \"id\": \"70f73e13-…\",\n  \"name\": \"Intake form validation\",\n  \"ref\": {\n    \"refType\": \"task\",\n    \"refId\": \"4e197f26-…\",\n    \"taskName\": \"Intake form validation\",\n    \"projectName\": \"Intake form\",\n    \"clientName\": \"Northwind Legal\",\n    \"clientColor\": \"primary-400\"\n  },\n  \"billable\": true,\n  \"resolvedRate\": 95,\n  \"rateOverridden\": false,\n  \"start\": \"2026-09-13T13:00:00.000Z\",\n  \"end\": \"2026-09-13T14:45:00.000Z\",\n  \"durationSec\": 6300,\n  \"amount\": 166.25,\n  \"tags\": []\n}\n","json",[90,780,781,786,812,832,846,866,887,907,928,949,969,975,989,1007,1022,1042,1063,1080,1097,1112],{"__ignoreMap":116},[120,782,783],{"class":122,"line":123},[120,784,785],{"class":163},"{\n",[120,787,788,791,795,798,801,804,807,809],{"class":122,"line":130},[120,789,790],{"class":163},"  \"",[120,792,794],{"class":793},"spNyl","id",[120,796,797],{"class":163},"\"",[120,799,800],{"class":163},":",[120,802,803],{"class":163}," \"",[120,805,806],{"class":137},"70f73e13-…",[120,808,797],{"class":163},[120,810,811],{"class":163},",\n",[120,813,814,816,819,821,823,825,828,830],{"class":122,"line":157},[120,815,790],{"class":163},[120,817,818],{"class":793},"name",[120,820,797],{"class":163},[120,822,800],{"class":163},[120,824,803],{"class":163},[120,826,827],{"class":137},"Intake form validation",[120,829,797],{"class":163},[120,831,811],{"class":163},[120,833,834,836,839,841,843],{"class":122,"line":175},[120,835,790],{"class":163},[120,837,838],{"class":793},"ref",[120,840,797],{"class":163},[120,842,800],{"class":163},[120,844,845],{"class":163}," {\n",[120,847,848,851,853,855,857,859,862,864],{"class":122,"line":189},[120,849,850],{"class":163},"    \"",[120,852,766],{"class":133},[120,854,797],{"class":163},[120,856,800],{"class":163},[120,858,803],{"class":163},[120,860,861],{"class":137},"task",[120,863,797],{"class":163},[120,865,811],{"class":163},[120,867,869,871,874,876,878,880,883,885],{"class":122,"line":868},6,[120,870,850],{"class":163},[120,872,873],{"class":133},"refId",[120,875,797],{"class":163},[120,877,800],{"class":163},[120,879,803],{"class":163},[120,881,882],{"class":137},"4e197f26-…",[120,884,797],{"class":163},[120,886,811],{"class":163},[120,888,890,892,895,897,899,901,903,905],{"class":122,"line":889},7,[120,891,850],{"class":163},[120,893,894],{"class":133},"taskName",[120,896,797],{"class":163},[120,898,800],{"class":163},[120,900,803],{"class":163},[120,902,827],{"class":137},[120,904,797],{"class":163},[120,906,811],{"class":163},[120,908,910,912,915,917,919,921,924,926],{"class":122,"line":909},8,[120,911,850],{"class":163},[120,913,914],{"class":133},"projectName",[120,916,797],{"class":163},[120,918,800],{"class":163},[120,920,803],{"class":163},[120,922,923],{"class":137},"Intake form",[120,925,797],{"class":163},[120,927,811],{"class":163},[120,929,931,933,936,938,940,942,945,947],{"class":122,"line":930},9,[120,932,850],{"class":163},[120,934,935],{"class":133},"clientName",[120,937,797],{"class":163},[120,939,800],{"class":163},[120,941,803],{"class":163},[120,943,944],{"class":137},"Northwind Legal",[120,946,797],{"class":163},[120,948,811],{"class":163},[120,950,952,954,957,959,961,963,966],{"class":122,"line":951},10,[120,953,850],{"class":163},[120,955,956],{"class":133},"clientColor",[120,958,797],{"class":163},[120,960,800],{"class":163},[120,962,803],{"class":163},[120,964,965],{"class":137},"primary-400",[120,967,968],{"class":163},"\"\n",[120,970,972],{"class":122,"line":971},11,[120,973,974],{"class":163},"  },\n",[120,976,978,980,982,984,986],{"class":122,"line":977},12,[120,979,790],{"class":163},[120,981,751],{"class":793},[120,983,797],{"class":163},[120,985,800],{"class":163},[120,987,988],{"class":163}," true,\n",[120,990,992,994,997,999,1001,1005],{"class":122,"line":991},13,[120,993,790],{"class":163},[120,995,996],{"class":793},"resolvedRate",[120,998,797],{"class":163},[120,1000,800],{"class":163},[120,1002,1004],{"class":1003},"sbssI"," 95",[120,1006,811],{"class":163},[120,1008,1010,1012,1015,1017,1019],{"class":122,"line":1009},14,[120,1011,790],{"class":163},[120,1013,1014],{"class":793},"rateOverridden",[120,1016,797],{"class":163},[120,1018,800],{"class":163},[120,1020,1021],{"class":163}," false,\n",[120,1023,1025,1027,1029,1031,1033,1035,1038,1040],{"class":122,"line":1024},15,[120,1026,790],{"class":163},[120,1028,570],{"class":793},[120,1030,797],{"class":163},[120,1032,800],{"class":163},[120,1034,803],{"class":163},[120,1036,1037],{"class":137},"2026-09-13T13:00:00.000Z",[120,1039,797],{"class":163},[120,1041,811],{"class":163},[120,1043,1045,1047,1050,1052,1054,1056,1059,1061],{"class":122,"line":1044},16,[120,1046,790],{"class":163},[120,1048,1049],{"class":793},"end",[120,1051,797],{"class":163},[120,1053,800],{"class":163},[120,1055,803],{"class":163},[120,1057,1058],{"class":137},"2026-09-13T14:45:00.000Z",[120,1060,797],{"class":163},[120,1062,811],{"class":163},[120,1064,1066,1068,1071,1073,1075,1078],{"class":122,"line":1065},17,[120,1067,790],{"class":163},[120,1069,1070],{"class":793},"durationSec",[120,1072,797],{"class":163},[120,1074,800],{"class":163},[120,1076,1077],{"class":1003}," 6300",[120,1079,811],{"class":163},[120,1081,1083,1085,1088,1090,1092,1095],{"class":122,"line":1082},18,[120,1084,790],{"class":163},[120,1086,1087],{"class":793},"amount",[120,1089,797],{"class":163},[120,1091,800],{"class":163},[120,1093,1094],{"class":1003}," 166.25",[120,1096,811],{"class":163},[120,1098,1100,1102,1105,1107,1109],{"class":122,"line":1099},19,[120,1101,790],{"class":163},[120,1103,1104],{"class":793},"tags",[120,1106,797],{"class":163},[120,1108,800],{"class":163},[120,1110,1111],{"class":163}," []\n",[120,1113,1115],{"class":122,"line":1114},20,[120,1116,1117],{"class":163},"}\n",[271,1119,1121],{"id":1120},"catalog","Catalog",[86,1123,1124,1125,1129],{},"Clients, projects, tasks and tags share the same CRUD shape. Cascade endpoints return the counts the ",[99,1126,1128],{"href":1127},"\u002Fguide\u002Fprojects-clients-tasks#rule-3-cascade-delete","cascade dialog"," shows.",[276,1131,1132,1142],{},[279,1133,1134],{},[282,1135,1136,1138,1140],{},[285,1137,287],{},[285,1139,290],{},[285,1141,293],{},[295,1143,1144,1164,1184,1199,1214,1229,1242,1269,1285,1304,1316],{},[282,1145,1146,1149,1154],{},[300,1147,1148],{},"GET \u002F POST",[300,1150,1151],{},[90,1152,1153],{},"\u002Fapi\u002Fclients",[300,1155,1156,1157,1160,1161],{},"List ",[90,1158,1159],{},"ClientDto[]"," \u002F create ",[90,1162,1163],{},"{name, rate?}",[282,1165,1166,1169,1174],{},[300,1167,1168],{},"PATCH \u002F DELETE",[300,1170,1171],{},[90,1172,1173],{},"\u002Fapi\u002Fclients\u002F:id",[300,1175,1176,1177,1180,1181],{},"Update \u002F cascade delete (body ",[90,1178,1179],{},"{cascadeProjects, cascadeTasks, cascadeEntries}",") → ",[90,1182,1183],{},"CascadeDeleteResult",[282,1185,1186,1188,1193],{},[300,1187,449],{},[300,1189,1190],{},[90,1191,1192],{},"\u002Fapi\u002Fclients\u002F:id\u002Fcascade",[300,1194,1195,1198],{},[90,1196,1197],{},"CascadeCounts"," for the dialog",[282,1200,1201,1203,1208],{},[300,1202,1148],{},[300,1204,1205],{},[90,1206,1207],{},"\u002Fapi\u002Fprojects",[300,1209,1156,1210,1213],{},[90,1211,1212],{},"ProjectDto[]"," \u002F create",[282,1215,1216,1218,1223],{},[300,1217,1168],{},[300,1219,1220],{},[90,1221,1222],{},"\u002Fapi\u002Fprojects\u002F:id",[300,1224,1176,1225,1228],{},[90,1226,1227],{},"{cascadeTasks, cascadeEntries}",")",[282,1230,1231,1233,1238],{},[300,1232,449],{},[300,1234,1235],{},[90,1236,1237],{},"\u002Fapi\u002Fprojects\u002F:id\u002Fcascade",[300,1239,1240],{},[90,1241,1197],{},[282,1243,1244,1246,1251],{},[300,1245,1148],{},[300,1247,1248],{},[90,1249,1250],{},"\u002Fapi\u002Ftasks",[300,1252,1156,1253,1256,1257,748,1260,748,1262,1265,1266],{},[90,1254,1255],{},"TaskDto[]"," (carries ",[90,1258,1259],{},"rate",[90,1261,996],{},[90,1263,1264],{},"rateSource"," per Rule 2) \u002F create ",[90,1267,1268],{},"{name, projectId?, rate?, estimateMinutes?, done?}",[282,1270,1271,1273,1278],{},[300,1272,1168],{},[300,1274,1275],{},[90,1276,1277],{},"\u002Fapi\u002Ftasks\u002F:id",[300,1279,1280,1281,1284],{},"Update (same fields, partial; ",[90,1282,1283],{},"rate: null"," clears) \u002F delete",[282,1286,1287,1289,1294],{},[300,1288,1148],{},[300,1290,1291],{},[90,1292,1293],{},"\u002Fapi\u002Ftags",[300,1295,1156,1296,1299,1300,1303],{},[90,1297,1298],{},"TagDto[]"," \u002F create (lowercased, leading ",[90,1301,1302],{},"#"," stripped; an existing name — even a trashed one — is revived and returned instead of duplicated)",[282,1305,1306,1308,1313],{},[300,1307,717],{},[300,1309,1310],{},[90,1311,1312],{},"\u002Fapi\u002Ftags\u002F:id",[300,1314,1315],{},"Strips labels from entries; never touches time",[282,1317,1318,1320,1325],{},[300,1319,302],{},[300,1321,1322],{},[90,1323,1324],{},"\u002Fapi\u002Frestore",[300,1326,1327,1328,1331,1332,1334,1335,1338],{},"Undo, in one of two shapes. ",[90,1329,1330],{},"{batchId}"," — from a ",[90,1333,1183],{},"; the server un-trashes every row that cascade stamped and re-applies the references it cleared, whatever the size. ",[90,1336,1337],{},"{deleted, relinked?}"," — an explicit id snapshot for small, known sets (the trash list, a tag, one entry); capped at 10k entries \u002F 5k tasks \u002F 1k each of clients, projects and tags",[271,1340,1342],{"id":1341},"summaries-export","Summaries & export",[276,1344,1345,1355],{},[279,1346,1347],{},[282,1348,1349,1351,1353],{},[285,1350,287],{},[285,1352,290],{},[285,1354,293],{},[295,1356,1357,1372,1387,1406],{},[282,1358,1359,1361,1366],{},[300,1360,449],{},[300,1362,1363],{},[90,1364,1365],{},"\u002Fapi\u002Fsummary\u002Fdashboard",[300,1367,1368,1371],{},[90,1369,1370],{},"DashboardSummary"," — today\u002Fweek stats, 16-week activity, week bars, unbilled amount",[282,1373,1374,1376,1381],{},[300,1375,449],{},[300,1377,1378],{},[90,1379,1380],{},"\u002Fapi\u002Fsummary\u002Freports?from&to&billable&groupBy",[300,1382,1383,1386],{},[90,1384,1385],{},"ReportSummary"," — stacked days, regroupable breakdown, fan-out-safe totals",[282,1388,1389,1391,1396],{},[300,1390,449],{},[300,1392,1393],{},[90,1394,1395],{},"\u002Fapi\u002Fexport\u002Fcsv?from&to&billable",[300,1397,1398,1399,1402,1403,1228],{},"The range as a ",[90,1400,1401],{},"text\u002Fcsv"," attachment (",[90,1404,1405],{},"date, start, end, duration_h, name, task, project, client, tags, billable, rate, amount",[282,1407,1408,1410,1415],{},[300,1409,449],{},[300,1411,1412],{},[90,1413,1414],{},"\u002Fapi\u002Fexport\u002Fpdf?from&to&billable&groupBy",[300,1416,1417,1418,1421],{},"The same report as an ",[90,1419,1420],{},"application\u002Fpdf"," attachment, rendered server-side",[86,1423,1424,210,1427,1430,1431,420,1433,325,1435,1438,1439,1441,1442,481,1445,325,1448,1441,1451,1438,1454,1441,1456,1459,1460,1463,1464,748,1467,222],{},[90,1425,1426],{},"from",[90,1428,1429],{},"to"," are ISO datetimes and the range is half-open on entry start — ",[90,1432,684],{},[90,1434,751],{},[90,1436,1437],{},"all"," (default) \u002F ",[90,1440,751],{}," \u002F ",[90,1443,1444],{},"nonbillable",[90,1446,1447],{},"groupBy",[90,1449,1450],{},"client",[90,1452,1453],{},"project",[90,1455,861],{},[90,1457,1458],{},"tag",". Both exports set ",[90,1461,1462],{},"Content-Disposition: attachment"," with a dated filename (",[90,1465,1466],{},"tick-export-2026-09-07--2026-09-13.csv",[90,1468,1469],{},"tick-report-2026-09-07_2026-09-13.pdf",[271,1471,1473],{"id":1472},"import","Import",[276,1475,1476,1486],{},[279,1477,1478],{},[282,1479,1480,1482,1484],{},[285,1481,287],{},[285,1483,290],{},[285,1485,293],{},[295,1487,1488,1506],{},[282,1489,1490,1492,1497],{},[300,1491,302],{},[300,1493,1494],{},[90,1495,1496],{},"\u002Fapi\u002Fimport\u002Fpreview",[300,1498,1499,356,1502,1505],{},[90,1500,1501],{},"{source: 'toggl' | 'clockify' | 'generic', csv}",[90,1503,1504],{},"ImportPreview"," (dry run, writes nothing)",[282,1507,1508,1510,1515],{},[300,1509,302],{},[300,1511,1512],{},[90,1513,1514],{},"\u002Fapi\u002Fimport\u002Fcommit",[300,1516,1517,1518,1521,1522,1524],{},"Same body → ",[90,1519,1520],{},"ImportCommitResult"," (creates catalog rows + inserts entries). ",[90,1523,268],{}," in demo mode",[271,1526,1528],{"id":1527},"organization-team","Organization & team",[276,1530,1531,1541],{},[279,1532,1533],{},[282,1534,1535,1537,1539],{},[285,1536,287],{},[285,1538,290],{},[285,1540,293],{},[295,1542,1543,1566,1587,1607,1618,1651,1663],{},[282,1544,1545,1548,1553],{},[300,1546,1547],{},"GET \u002F PATCH",[300,1549,1550],{},[90,1551,1552],{},"\u002Fapi\u002Forg",[300,1554,1555,1558,1559,748,1562,1565],{},[90,1556,1557],{},"OrgInfoDto"," (id, name, ",[90,1560,1561],{},"memberCount",[90,1563,1564],{},"createdAt",") \u002F rename (owner\u002Fadmin)",[282,1567,1568,1570,1575],{},[300,1569,449],{},[300,1571,1572],{},[90,1573,1574],{},"\u002Fapi\u002Forg\u002Fmembers",[300,1576,1577,1580,1581,1583,1584],{},[90,1578,1579],{},"OrgMemberDto[]"," — name, email, role, ",[90,1582,1259],{}," override, ",[90,1585,1586],{},"defaultRate",[282,1588,1589,1591,1596],{},[300,1590,468],{},[300,1592,1593],{},[90,1594,1595],{},"\u002Fapi\u002Forg\u002Fmembers\u002F:userId",[300,1597,1598,1601,1602,1604,1605,1228],{},[90,1599,1600],{},"{role?, rate?}"," (owner\u002Fadmin). Admins cannot touch owners or grant the owner role (",[90,1603,268],{},"); the last owner can't be demoted (",[90,1606,336],{},[282,1608,1609,1611,1615],{},[300,1610,717],{},[300,1612,1613],{},[90,1614,1595],{},[300,1616,1617],{},"Remove member (owner\u002Fadmin; admins can't remove owners, last owner protected)",[282,1619,1620,1622,1627],{},[300,1621,1148],{},[300,1623,1624],{},[90,1625,1626],{},"\u002Fapi\u002Finvites",[300,1628,1629,1630,356,1633,1636,1637,1640,1641,640,1644,1647,1648,1650],{},"List pending (unaccepted, unexpired) \u002F create ",[90,1631,1632],{},"{email, role}",[90,1634,1635],{},"InviteCreateDto"," with the ",[90,1638,1639],{},"token",", a 7-day ",[90,1642,1643],{},"expiresAt",[90,1645,1646],{},"emailSent",". Owner\u002Fadmin only; only owners may invite owners; ",[90,1649,336],{}," if the address is already a member",[282,1652,1653,1655,1660],{},[300,1654,717],{},[300,1656,1657],{},[90,1658,1659],{},"\u002Fapi\u002Finvites\u002F:id",[300,1661,1662],{},"Revoke an invite",[282,1664,1665,1667,1672],{},[300,1666,449],{},[300,1668,1669],{},[90,1670,1671],{},"\u002Fapi\u002Finvites\u002Flookup\u002F:token",[300,1673,1674,1677,1678,1681,1682,1685,1686,1688],{},[227,1675,1676],{},"Public"," — ",[90,1679,1680],{},"{email, role, orgName}"," for the register page; ",[90,1683,1684],{},"404"," unknown, ",[90,1687,340],{}," expired or used",[271,1690,1692],{"id":1691},"trash","Trash",[276,1694,1695,1705],{},[279,1696,1697],{},[282,1698,1699,1701,1703],{},[285,1700,287],{},[285,1702,290],{},[285,1704,293],{},[295,1706,1707,1726],{},[282,1708,1709,1711,1716],{},[300,1710,449],{},[300,1712,1713],{},[90,1714,1715],{},"\u002Fapi\u002Ftrash",[300,1717,1718,1721,1722,1725],{},[90,1719,1720],{},"TrashDto"," — trashed rows per entity with ",[90,1723,1724],{},"daysLeft","; auto-purges anything older than 30 days first",[282,1727,1728,1730,1735],{},[300,1729,302],{},[300,1731,1732],{},[90,1733,1734],{},"\u002Fapi\u002Ftrash\u002Fpurge",[300,1736,1737,1740,1741,1744,1745,1524],{},[90,1738,1739],{},"{all: true}"," or ",[90,1742,1743],{},"{items: {clients, projects, tasks, tags, entries}}"," — hard delete (\"Delete forever\"). ",[90,1746,268],{},[271,1748,1750],{"id":1749},"errors","Errors",[276,1752,1753,1763],{},[279,1754,1755],{},[282,1756,1757,1760],{},[285,1758,1759],{},"Status",[285,1761,1762],{},"When",[295,1764,1765,1779,1788,1797,1810,1827],{},[282,1766,1767,1772],{},[300,1768,1769],{},[90,1770,1771],{},"400",[300,1773,1774,1775,1778],{},"Validation failure. Routes reachable without a session answer with a terse ",[90,1776,1777],{},"{statusMessage: 'Invalid input', data: {fields: […]}}"," — field names only, never zod internals",[282,1780,1781,1785],{},[300,1782,1783],{},[90,1784,363],{},[300,1786,1787],{},"No session, a revoked session, or a membership that no longer exists",[282,1789,1790,1794],{},[300,1791,1792],{},[90,1793,268],{},[300,1795,1796],{},"Role not allowed, wrong current password, or the action is blocked in demo mode",[282,1798,1799,1807],{},[300,1800,1801,1441,1803,1441,1805],{},[90,1802,1684],{},[90,1804,336],{},[90,1806,340],{},[300,1808,1809],{},"Missing row \u002F conflict (duplicate email, the running-timer cap, last owner) \u002F expired-or-used token",[282,1811,1812,1820],{},[300,1813,1814,1441,1817],{},[90,1815,1816],{},"411",[90,1818,1819],{},"413",[300,1821,1822,1823,1826],{},"Body without a ",[90,1824,1825],{},"Content-Length"," on an API mutation \u002F body over the cap",[282,1828,1829,1834],{},[300,1830,1831],{},[90,1832,1833],{},"429",[300,1835,1836,1837,1839],{},"Auth rate limit — see the ",[90,1838,255],{}," header",[1841,1842,1843],"style",{},"html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}",{"title":116,"searchDepth":130,"depth":130,"links":1845},[1846,1847,1848,1849,1850,1851,1852,1853,1854,1855],{"id":273,"depth":130,"text":274},{"id":429,"depth":130,"text":430},{"id":530,"depth":130,"text":531},{"id":651,"depth":130,"text":652},{"id":1120,"depth":130,"text":1121},{"id":1341,"depth":130,"text":1342},{"id":1472,"depth":130,"text":1473},{"id":1527,"depth":130,"text":1528},{"id":1691,"depth":130,"text":1692},{"id":1749,"depth":130,"text":1750},"Every server route under \u002Fapi — JSON, zod-validated, session-guarded.","md",{},{"icon":64},{"title":61,"description":1856},"WQ1qYp_hLT6zg48qrqo8vFFmeQlVLOsGMZdrC4-HsTo",[1863,1865],{"title":56,"path":57,"stem":58,"description":1864,"icon":59,"children":-1},"The PostgreSQL entities and the four rules that govern references, rates and deletion.",{"title":66,"path":67,"stem":68,"description":1866,"icon":69,"children":-1},"Every variable Tick reads, plus the npm scripts you'll use in development.",1790777312389]