[{"data":1,"prerenderedAt":3858},["ShallowReactive",2],{"docs:\u002Fdocs\u002Fendpoints":3,"i-lucide:moon":3849,"i-lucide:github":3854,"i-lucide:menu":3856},{"id":4,"title":5,"body":6,"description":3842,"extension":3843,"meta":3844,"navigation":64,"path":3845,"seo":3846,"stem":3847,"__hash__":3848},"docs\u002Fdocs\u002Fendpoints.md","Define Endpoints",{"type":7,"value":8,"toc":3822},"minimark",[9,13,18,30,306,309,366,373,478,482,508,512,518,735,738,788,791,836,862,865,869,887,1068,1071,1109,1119,1163,1184,1196,1230,1325,1335,1350,1353,1378,1382,1391,1575,1680,1685,1694,1742,1760,1767,1771,1784,1787,1803,1821,1827,1831,1840,1853,1860,1866,1919,1922,2015,2024,2027,2096,2100,2109,2286,2290,2293,2425,2428,2488,2503,2524,2578,2581,2643,2647,2658,2792,2806,2818,2829,2845,2872,2886,2892,2921,2927,2940,2945,2949,2962,3022,3030,3038,3042,3045,3126,3129,3142,3149,3180,3184,3187,3253,3257,3268,3359,3483,3513,3519,3531,3535,3554,3561,3656,3746,3765,3772,3815,3818],[10,11,12],"p",{},"The endpoint definition is the contract for runtime validation, handler context types, generated client input, and OpenAPI schema output.",[14,15,17],"h2",{"id":16},"basic-route","Basic route",[10,19,20,21,25,26,29],{},"Default-export a ",[22,23,24],"code",{},"defineEndpoint()"," call with a ",[22,27,28],{},"handler"," property. The handler receives parsed schema output.",[31,32,37],"pre",{"className":33,"code":34,"language":35,"meta":36,"style":36},"language-ts shiki shiki-themes github-light-default github-dark-default","import { z } from 'zod'\n\nconst User = z.object({\n  id: z.number(),\n  name: z.string(),\n})\n\nexport default defineEndpoint({\n  summary: 'Get a user',\n  params: z.object({\n    id: z.coerce.number(),\n  }),\n  query: z.object({\n    includePosts: z.coerce.boolean().optional(),\n  }),\n  responses: { 200: User },\n  handler: ({ params, query }) => {\n    return {\n      id: params.id,\n      name: query.includePosts ? 'Tom with posts' : 'Tom',\n    }\n  },\n})\n","ts","",[22,38,39,59,66,89,101,112,118,123,138,150,160,170,178,188,205,212,226,253,261,267,287,293,301],{"__ignoreMap":36},[40,41,44,48,52,55],"span",{"class":42,"line":43},"line",1,[40,45,47],{"class":46},"swxxe","import",[40,49,51],{"class":50},"saQ_J"," { z } ",[40,53,54],{"class":46},"from",[40,56,58],{"class":57},"sZItA"," 'zod'\n",[40,60,62],{"class":42,"line":61},2,[40,63,65],{"emptyLinePlaceholder":64},true,"\n",[40,67,69,72,76,79,82,86],{"class":42,"line":68},3,[40,70,71],{"class":46},"const",[40,73,75],{"class":74},"sOOdx"," User",[40,77,78],{"class":46}," =",[40,80,81],{"class":50}," z.",[40,83,85],{"class":84},"s9HWX","object",[40,87,88],{"class":50},"({\n",[40,90,92,95,98],{"class":42,"line":91},4,[40,93,94],{"class":50},"  id: z.",[40,96,97],{"class":84},"number",[40,99,100],{"class":50},"(),\n",[40,102,104,107,110],{"class":42,"line":103},5,[40,105,106],{"class":50},"  name: z.",[40,108,109],{"class":84},"string",[40,111,100],{"class":50},[40,113,115],{"class":42,"line":114},6,[40,116,117],{"class":50},"})\n",[40,119,121],{"class":42,"line":120},7,[40,122,65],{"emptyLinePlaceholder":64},[40,124,126,129,132,135],{"class":42,"line":125},8,[40,127,128],{"class":46},"export",[40,130,131],{"class":46}," default",[40,133,134],{"class":84}," defineEndpoint",[40,136,88],{"class":137},"sVS1I",[40,139,141,144,147],{"class":42,"line":140},9,[40,142,143],{"class":50},"  summary: ",[40,145,146],{"class":57},"'Get a user'",[40,148,149],{"class":137},",\n",[40,151,153,156,158],{"class":42,"line":152},10,[40,154,155],{"class":50},"  params: z.",[40,157,85],{"class":84},[40,159,88],{"class":50},[40,161,163,166,168],{"class":42,"line":162},11,[40,164,165],{"class":50},"    id: z.coerce.",[40,167,97],{"class":84},[40,169,100],{"class":50},[40,171,173,176],{"class":42,"line":172},12,[40,174,175],{"class":50},"  })",[40,177,149],{"class":137},[40,179,181,184,186],{"class":42,"line":180},13,[40,182,183],{"class":50},"  query: z.",[40,185,85],{"class":84},[40,187,88],{"class":50},[40,189,191,194,197,200,203],{"class":42,"line":190},14,[40,192,193],{"class":50},"    includePosts: z.coerce.",[40,195,196],{"class":84},"boolean",[40,198,199],{"class":50},"().",[40,201,202],{"class":84},"optional",[40,204,100],{"class":50},[40,206,208,210],{"class":42,"line":207},15,[40,209,175],{"class":50},[40,211,149],{"class":137},[40,213,215,218,221,224],{"class":42,"line":214},16,[40,216,217],{"class":50},"  responses: { ",[40,219,220],{"class":74},"200",[40,222,223],{"class":50},": User }",[40,225,149],{"class":137},[40,227,229,232,235,238,241,244,247,250],{"class":42,"line":228},17,[40,230,231],{"class":84},"  handler",[40,233,234],{"class":50},": ({ ",[40,236,237],{"class":137},"params",[40,239,240],{"class":50},", ",[40,242,243],{"class":137},"query",[40,245,246],{"class":50}," }) ",[40,248,249],{"class":46},"=>",[40,251,252],{"class":50}," {\n",[40,254,256,259],{"class":42,"line":255},18,[40,257,258],{"class":46},"    return",[40,260,252],{"class":50},[40,262,264],{"class":42,"line":263},19,[40,265,266],{"class":50},"      id: params.id,\n",[40,268,270,273,276,279,282,285],{"class":42,"line":269},20,[40,271,272],{"class":50},"      name: query.includePosts ",[40,274,275],{"class":46},"?",[40,277,278],{"class":57}," 'Tom with posts'",[40,280,281],{"class":46}," :",[40,283,284],{"class":57}," 'Tom'",[40,286,149],{"class":50},[40,288,290],{"class":42,"line":289},21,[40,291,292],{"class":50},"    }\n",[40,294,296,299],{"class":42,"line":295},22,[40,297,298],{"class":50},"  }",[40,300,149],{"class":137},[40,302,304],{"class":42,"line":303},23,[40,305,117],{"class":137},[10,307,308],{},"The generated client can call this route by path and method:",[31,310,312],{"className":33,"code":311,"language":35,"meta":36,"style":36},"await $endpoint('\u002Fapi\u002Fusers\u002F:id', {\n  method: 'get',\n  params: { id: '123' },\n  query: { includePosts: true },\n})\n",[22,313,314,331,341,352,362],{"__ignoreMap":36},[40,315,316,319,322,325,328],{"class":42,"line":43},[40,317,318],{"class":46},"await",[40,320,321],{"class":84}," $endpoint",[40,323,324],{"class":50},"(",[40,326,327],{"class":57},"'\u002Fapi\u002Fusers\u002F:id'",[40,329,330],{"class":50},", {\n",[40,332,333,336,339],{"class":42,"line":61},[40,334,335],{"class":50},"  method: ",[40,337,338],{"class":57},"'get'",[40,340,149],{"class":50},[40,342,343,346,349],{"class":42,"line":68},[40,344,345],{"class":50},"  params: { id: ",[40,347,348],{"class":57},"'123'",[40,350,351],{"class":50}," },\n",[40,353,354,357,360],{"class":42,"line":91},[40,355,356],{"class":50},"  query: { includePosts: ",[40,358,359],{"class":74},"true",[40,361,351],{"class":50},[40,363,364],{"class":42,"line":103},[40,365,117],{"class":50},[10,367,368,369,372],{},"Add ",[22,370,371],{},"operation"," when you also want a named call target or a hand-picked OpenAPI operationId:",[31,374,376],{"className":33,"code":375,"language":35,"meta":36,"style":36},"export default defineEndpoint({\n  operation: 'getUser',\n  params: UserParams,\n  responses: { 200: User },\n  handler: ({ params }) => findUser(params.id),\n})\n\nawait $endpoint('getUser', { params: { id: '123' } })\nawait $endpoint.getUser({ params: { id: '123' } })\n",[22,377,378,388,398,405,415,435,439,443,461],{"__ignoreMap":36},[40,379,380,382,384,386],{"class":42,"line":43},[40,381,128],{"class":46},[40,383,131],{"class":46},[40,385,134],{"class":84},[40,387,88],{"class":137},[40,389,390,393,396],{"class":42,"line":61},[40,391,392],{"class":50},"  operation: ",[40,394,395],{"class":57},"'getUser'",[40,397,149],{"class":137},[40,399,400,403],{"class":42,"line":68},[40,401,402],{"class":50},"  params: UserParams",[40,404,149],{"class":137},[40,406,407,409,411,413],{"class":42,"line":91},[40,408,217],{"class":50},[40,410,220],{"class":74},[40,412,223],{"class":50},[40,414,149],{"class":137},[40,416,417,419,421,423,425,427,430,433],{"class":42,"line":103},[40,418,231],{"class":84},[40,420,234],{"class":50},[40,422,237],{"class":137},[40,424,246],{"class":50},[40,426,249],{"class":46},[40,428,429],{"class":84}," findUser",[40,431,432],{"class":50},"(params.id)",[40,434,149],{"class":137},[40,436,437],{"class":42,"line":114},[40,438,117],{"class":137},[40,440,441],{"class":42,"line":120},[40,442,65],{"emptyLinePlaceholder":64},[40,444,445,447,449,451,453,456,458],{"class":42,"line":125},[40,446,318],{"class":46},[40,448,321],{"class":84},[40,450,324],{"class":50},[40,452,395],{"class":57},[40,454,455],{"class":50},", { params: { id: ",[40,457,348],{"class":57},[40,459,460],{"class":50}," } })\n",[40,462,463,465,468,471,474,476],{"class":42,"line":140},[40,464,318],{"class":46},[40,466,467],{"class":50}," $endpoint.",[40,469,470],{"class":84},"getUser",[40,472,473],{"class":50},"({ params: { id: ",[40,475,348],{"class":57},[40,477,460],{"class":50},[14,479,481],{"id":480},"validated-request-parts","Validated request parts",[483,484,485,491,496,502],"ul",{},[486,487,488,490],"li",{},[22,489,237],{},": route params are parsed before the handler runs. Coercion is reflected in handler types.",[486,492,493,495],{},[22,494,243],{},": query string values can be coerced into booleans, numbers, arrays, or richer schemas.",[486,497,498,501],{},[22,499,500],{},"headers",": header schemas are useful for explicit authentication or versioning boundaries.",[486,503,504,507],{},[22,505,506],{},"body",": JSON request bodies are the first-class body format in the current API.",[14,509,511],{"id":510},"multiple-methods-on-one-route","Multiple methods on one route",[10,513,514,515,517],{},"A route file without a method suffix can declare several methods at once. Each\nmember is an ordinary ",[22,516,24],{}," contract, so operations, response\nstatuses, media-type bodies, and idempotency all work per method:",[31,519,521],{"className":33,"code":520,"language":35,"meta":36,"style":36},"\u002F\u002F server\u002Fapi\u002Fusers\u002F[id].ts — no method suffix\nexport const endpoints = defineEndpointMethods({\n  get: defineEndpoint({\n    operation: 'getUser',\n    params: z.object({ id: z.coerce.number() }),\n    responses: { 200: User },\n  }),\n  put: defineEndpoint({\n    operation: 'updateUser',\n    params: z.object({ id: z.coerce.number() }),\n    body: UpdateUser,\n    responses: { 200: User, 404: NotFound },\n  }),\n})\n\nexport default defineEndpointMethodHandlers(endpoints, {\n  get: ({ params }) => findUser(params.id),\n  put: ({ params, body, respond }) => respond(200, updateUser(params.id, body)),\n})\n",[22,522,523,529,546,556,565,580,590,595,604,613,625,630,645,649,653,657,673,692,731],{"__ignoreMap":36},[40,524,525],{"class":42,"line":43},[40,526,528],{"class":527},"sA0OV","\u002F\u002F server\u002Fapi\u002Fusers\u002F[id].ts — no method suffix\n",[40,530,531,533,536,539,541,544],{"class":42,"line":61},[40,532,128],{"class":46},[40,534,535],{"class":46}," const",[40,537,538],{"class":74}," endpoints",[40,540,78],{"class":46},[40,542,543],{"class":84}," defineEndpointMethods",[40,545,88],{"class":50},[40,547,548,551,554],{"class":42,"line":68},[40,549,550],{"class":50},"  get: ",[40,552,553],{"class":84},"defineEndpoint",[40,555,88],{"class":50},[40,557,558,561,563],{"class":42,"line":91},[40,559,560],{"class":50},"    operation: ",[40,562,395],{"class":57},[40,564,149],{"class":50},[40,566,567,570,572,575,577],{"class":42,"line":103},[40,568,569],{"class":50},"    params: z.",[40,571,85],{"class":84},[40,573,574],{"class":50},"({ id: z.coerce.",[40,576,97],{"class":84},[40,578,579],{"class":50},"() }),\n",[40,581,582,585,587],{"class":42,"line":114},[40,583,584],{"class":50},"    responses: { ",[40,586,220],{"class":74},[40,588,589],{"class":50},": User },\n",[40,591,592],{"class":42,"line":120},[40,593,594],{"class":50},"  }),\n",[40,596,597,600,602],{"class":42,"line":125},[40,598,599],{"class":50},"  put: ",[40,601,553],{"class":84},[40,603,88],{"class":50},[40,605,606,608,611],{"class":42,"line":140},[40,607,560],{"class":50},[40,609,610],{"class":57},"'updateUser'",[40,612,149],{"class":50},[40,614,615,617,619,621,623],{"class":42,"line":152},[40,616,569],{"class":50},[40,618,85],{"class":84},[40,620,574],{"class":50},[40,622,97],{"class":84},[40,624,579],{"class":50},[40,626,627],{"class":42,"line":162},[40,628,629],{"class":50},"    body: UpdateUser,\n",[40,631,632,634,636,639,642],{"class":42,"line":172},[40,633,584],{"class":50},[40,635,220],{"class":74},[40,637,638],{"class":50},": User, ",[40,640,641],{"class":74},"404",[40,643,644],{"class":50},": NotFound },\n",[40,646,647],{"class":42,"line":180},[40,648,594],{"class":50},[40,650,651],{"class":42,"line":190},[40,652,117],{"class":50},[40,654,655],{"class":42,"line":207},[40,656,65],{"emptyLinePlaceholder":64},[40,658,659,661,663,666,668,671],{"class":42,"line":214},[40,660,128],{"class":46},[40,662,131],{"class":46},[40,664,665],{"class":84}," defineEndpointMethodHandlers",[40,667,324],{"class":137},[40,669,670],{"class":50},"endpoints",[40,672,330],{"class":137},[40,674,675,678,680,682,684,686,688,690],{"class":42,"line":228},[40,676,677],{"class":84},"  get",[40,679,234],{"class":50},[40,681,237],{"class":137},[40,683,246],{"class":50},[40,685,249],{"class":46},[40,687,429],{"class":84},[40,689,432],{"class":50},[40,691,149],{"class":137},[40,693,694,697,699,701,703,705,707,710,712,714,717,719,721,723,726,729],{"class":42,"line":255},[40,695,696],{"class":84},"  put",[40,698,234],{"class":50},[40,700,237],{"class":137},[40,702,240],{"class":50},[40,704,506],{"class":137},[40,706,240],{"class":50},[40,708,709],{"class":137},"respond",[40,711,246],{"class":50},[40,713,249],{"class":46},[40,715,716],{"class":84}," respond",[40,718,324],{"class":50},[40,720,220],{"class":74},[40,722,240],{"class":50},[40,724,725],{"class":84},"updateUser",[40,727,728],{"class":50},"(params.id, body))",[40,730,149],{"class":137},[40,732,733],{"class":42,"line":263},[40,734,117],{"class":137},[10,736,737],{},"The generated client calls each method on the one path, and every member keeps\nits own request and response types:",[31,739,741],{"className":33,"code":740,"language":35,"meta":36,"style":36},"await $endpoint('\u002Fapi\u002Fusers\u002F:id', { method: 'get', params: { id: '1' } })\nawait $endpoint('updateUser', { params: { id: '1' }, body: { name: 'Tom' } })\n",[22,742,743,766],{"__ignoreMap":36},[40,744,745,747,749,751,753,756,758,761,764],{"class":42,"line":43},[40,746,318],{"class":46},[40,748,321],{"class":84},[40,750,324],{"class":50},[40,752,327],{"class":57},[40,754,755],{"class":50},", { method: ",[40,757,338],{"class":57},[40,759,760],{"class":50},", params: { id: ",[40,762,763],{"class":57},"'1'",[40,765,460],{"class":50},[40,767,768,770,772,774,776,778,780,783,786],{"class":42,"line":61},[40,769,318],{"class":46},[40,771,321],{"class":84},[40,773,324],{"class":50},[40,775,610],{"class":57},[40,777,455],{"class":50},[40,779,763],{"class":57},[40,781,782],{"class":50}," }, body: { name: ",[40,784,785],{"class":57},"'Tom'",[40,787,460],{"class":50},[10,789,790],{},"The dispatcher answers the whole route:",[483,792,793,796,806,820],{},[486,794,795],{},"Declared methods run their own handler, with their own validation.",[486,797,798,801,802,805],{},[22,799,800],{},"HEAD"," runs the ",[22,803,804],{},"GET"," member and returns its status and headers with no body.",[486,807,808,811,812,815,816,819],{},[22,809,810],{},"OPTIONS"," answers ",[22,813,814],{},"204"," with an ",[22,817,818],{},"Allow"," header.",[486,821,822,823,826,827,829,830,832,833,835],{},"Anything else gets ",[22,824,825],{},"405"," with the same ",[22,828,818],{}," header, listing the declared\nmethods plus the derived ",[22,831,800],{}," and ",[22,834,810],{},".",[10,837,838,839,842,843,846,847,850,851,854,855,858,859,861],{},"Declaring ",[22,840,841],{},"head"," or ",[22,844,845],{},"options"," yourself is an error — they are derived — and so\nare empty groups, ",[22,848,849],{},"connect","\u002F",[22,852,853],{},"trace",", and handler maps whose keys do not match\nthe group. Groups belong on method-suffix-free files: putting one in\n",[22,856,857],{},"users.get.ts"," fails the build, because the other methods would be\nunreachable. The reverse also fails: a single ",[22,860,24],{}," in a\nsuffix-free file cannot know which method it serves.",[10,863,864],{},"Use single-method files when a route has one method — nothing about them\nchanges. Reach for a group when one path genuinely serves several methods and\nyou would rather keep them together.",[14,866,868],{"id":867},"media-type-request-bodies","Media-type request bodies",[10,870,871,872,874,875,878,879,882,883,886],{},"A ",[22,873,506],{}," contract can also be a map from media types to schemas. The request's\n",[22,876,877],{},"Content-Type"," (parameters such as ",[22,880,881],{},"charset"," stripped, lowercased) selects the\nmember to validate against; a request matching no member gets a ",[22,884,885],{},"415"," listing\nthe supported types.",[31,888,890],{"className":33,"code":889,"language":35,"meta":36,"style":36},"export default defineEndpoint({\n  operation: 'createUser',\n  body: {\n    'application\u002Fjson': z.object({ name: z.string() }),\n    'multipart\u002Fform-data': z.object({\n      name: z.string(),\n      avatar: z.instanceof(File),\n    }),\n  },\n  responses: { 201: User },\n  handler: ({ body, bodyMediaType, respond }) => {\n    \u002F\u002F body is the union of member outputs; bodyMediaType narrows which one matched\n    if (bodyMediaType === 'multipart\u002Fform-data') {\n      \u002F\u002F body.avatar is a File here\n    }\n    return respond(201, createUser(body.name))\n  },\n})\n",[22,891,892,902,911,916,933,944,953,964,969,975,986,1009,1014,1031,1036,1040,1058,1064],{"__ignoreMap":36},[40,893,894,896,898,900],{"class":42,"line":43},[40,895,128],{"class":46},[40,897,131],{"class":46},[40,899,134],{"class":84},[40,901,88],{"class":137},[40,903,904,906,909],{"class":42,"line":61},[40,905,392],{"class":50},[40,907,908],{"class":57},"'createUser'",[40,910,149],{"class":137},[40,912,913],{"class":42,"line":68},[40,914,915],{"class":50},"  body: {\n",[40,917,918,921,924,926,929,931],{"class":42,"line":91},[40,919,920],{"class":57},"    'application\u002Fjson'",[40,922,923],{"class":50},": z.",[40,925,85],{"class":84},[40,927,928],{"class":50},"({ name: z.",[40,930,109],{"class":84},[40,932,579],{"class":50},[40,934,935,938,940,942],{"class":42,"line":103},[40,936,937],{"class":57},"    'multipart\u002Fform-data'",[40,939,923],{"class":50},[40,941,85],{"class":84},[40,943,88],{"class":50},[40,945,946,949,951],{"class":42,"line":114},[40,947,948],{"class":50},"      name: z.",[40,950,109],{"class":84},[40,952,100],{"class":50},[40,954,955,958,961],{"class":42,"line":120},[40,956,957],{"class":50},"      avatar: z.",[40,959,960],{"class":84},"instanceof",[40,962,963],{"class":50},"(File),\n",[40,965,966],{"class":42,"line":125},[40,967,968],{"class":50},"    }),\n",[40,970,971,973],{"class":42,"line":140},[40,972,298],{"class":50},[40,974,149],{"class":137},[40,976,977,979,982,984],{"class":42,"line":152},[40,978,217],{"class":50},[40,980,981],{"class":74},"201",[40,983,223],{"class":50},[40,985,149],{"class":137},[40,987,988,990,992,994,996,999,1001,1003,1005,1007],{"class":42,"line":162},[40,989,231],{"class":84},[40,991,234],{"class":50},[40,993,506],{"class":137},[40,995,240],{"class":50},[40,997,998],{"class":137},"bodyMediaType",[40,1000,240],{"class":50},[40,1002,709],{"class":137},[40,1004,246],{"class":50},[40,1006,249],{"class":46},[40,1008,252],{"class":50},[40,1010,1011],{"class":42,"line":172},[40,1012,1013],{"class":527},"    \u002F\u002F body is the union of member outputs; bodyMediaType narrows which one matched\n",[40,1015,1016,1019,1022,1025,1028],{"class":42,"line":180},[40,1017,1018],{"class":46},"    if",[40,1020,1021],{"class":50}," (bodyMediaType ",[40,1023,1024],{"class":46},"===",[40,1026,1027],{"class":57}," 'multipart\u002Fform-data'",[40,1029,1030],{"class":50},") {\n",[40,1032,1033],{"class":42,"line":190},[40,1034,1035],{"class":527},"      \u002F\u002F body.avatar is a File here\n",[40,1037,1038],{"class":42,"line":207},[40,1039,292],{"class":50},[40,1041,1042,1044,1046,1048,1050,1052,1055],{"class":42,"line":214},[40,1043,258],{"class":46},[40,1045,716],{"class":84},[40,1047,324],{"class":50},[40,1049,981],{"class":74},[40,1051,240],{"class":50},[40,1053,1054],{"class":84},"createUser",[40,1056,1057],{"class":50},"(body.name))\n",[40,1059,1060,1062],{"class":42,"line":228},[40,1061,298],{"class":50},[40,1063,149],{"class":137},[40,1065,1066],{"class":42,"line":255},[40,1067,117],{"class":137},[10,1069,1070],{},"Supported member families and how each is parsed before validation:",[483,1072,1073,1079,1085,1099],{},[486,1074,1075,1078],{},[22,1076,1077],{},"application\u002Fjson"," — parsed as JSON, exactly like a single-schema body.",[486,1080,1081,1084],{},[22,1082,1083],{},"application\u002Fx-www-form-urlencoded"," — parsed into an object.",[486,1086,1087,1090,1091,1094,1095,1098],{},[22,1088,1089],{},"multipart\u002Fform-data"," — parsed into an object: repeated field names become\narrays, file parts stay ",[22,1092,1093],{},"File"," values (validate them with e.g.\n",[22,1096,1097],{},"z.instanceof(File)",").",[486,1100,1101,1104,1105,1108],{},[22,1102,1103],{},"text\u002Fplain"," and other specific ",[22,1106,1107],{},"text\u002F*"," types — the raw request text as a\nstring, with no coercion.",[10,1110,1111,1112,1114,1115,1118],{},"A schema needs one of those families, because a schema can only check a value\nthe runtime knows how to parse. For anything else — XML, a PDF, arbitrary bytes\n— declare the member ",[22,1113,359],{}," instead and receive the body unparsed, as a\n",[22,1116,1117],{},"Uint8Array",":",[31,1120,1122],{"className":33,"code":1121,"language":35,"meta":36,"style":36},"body: {\n  'application\u002Fjson': z.object({ name: z.string() }),\n  'application\u002Fpdf': true,\n}\n",[22,1123,1124,1131,1146,1158],{"__ignoreMap":36},[40,1125,1126,1128],{"class":42,"line":43},[40,1127,506],{"class":137},[40,1129,1130],{"class":50},": {\n",[40,1132,1133,1136,1138,1140,1142,1144],{"class":42,"line":61},[40,1134,1135],{"class":57},"  'application\u002Fjson'",[40,1137,923],{"class":50},[40,1139,85],{"class":84},[40,1141,928],{"class":50},[40,1143,109],{"class":84},[40,1145,579],{"class":50},[40,1147,1148,1151,1154,1156],{"class":42,"line":68},[40,1149,1150],{"class":57},"  'application\u002Fpdf'",[40,1152,1153],{"class":50},": ",[40,1155,359],{"class":74},[40,1157,149],{"class":50},[40,1159,1160],{"class":42,"line":91},[40,1161,1162],{"class":50},"}\n",[10,1164,1165,1166,1171,1172,1174,1175,1178,1179,1183],{},"This is the request-side counterpart of declaring a\n",[1167,1168,1170],"a",{"href":1169},"#non-json-responses","response by media type",": the media type is part of the\ncontract and reaches OpenAPI, and the payload is yours. ",[22,1173,359],{}," accepts any\nwell-formed ",[22,1176,1177],{},"type\u002Fsubtype",", and nothing about the body is validated. It is read\ninto memory rather than streamed — for a genuinely large upload, drop the\ncontract and read the event directly, as ",[1167,1180,1182],{"href":1181},"\u002Fdocs\u002Flow-level-http","Low-level HTTP","\ndescribes.",[10,1185,1186,1187,1189,1190,1192,1193,1195],{},"An empty map, uppercase keys, a malformed media type, or a schema on a family\nthe runtime cannot parse all fail at ",[22,1188,24],{}," time — which means\nduring build discovery, not on a live request. A media-type map makes the body\nmandatory: requests without a matching ",[22,1191,877],{}," are rejected with ",[22,1194,885],{},"\nbefore the handler runs.",[10,1197,1198,1199,1202,1203,1206,1207,1209,1210,1212,1213,1215,1216,1219,1220,1223,1224,1226,1227,1229],{},"On the client, the generated ",[22,1200,1201],{},"$endpoint"," gains a ",[22,1204,1205],{},"mediaType"," request option for\nmap contracts. When the map has an ",[22,1208,1077],{}," member, ",[22,1211,1205],{}," is\noptional and calls read exactly like a single-schema body. Selecting any other\nmember types ",[22,1214,506],{}," as its wire value — ",[22,1217,1218],{},"FormData"," for multipart,\n",[22,1221,1222],{},"URLSearchParams"," for URL-encoded forms, ",[22,1225,109],{}," for ",[22,1228,1107],{},", and bytes for an\nunparsed member — because the client does not invent an object-to-wire\nserialization it cannot make honest:",[31,1231,1233],{"className":33,"code":1232,"language":35,"meta":36,"style":36},"const formData = new FormData()\nformData.append('name', 'Tom')\nformData.append('avatar', file)\n\nawait $endpoint('createUser', {\n  mediaType: 'multipart\u002Fform-data',\n  body: formData, \u002F\u002F typed as FormData; content-type is left to the runtime\n})\n",[22,1234,1235,1253,1273,1287,1291,1303,1313,1321],{"__ignoreMap":36},[40,1236,1237,1239,1242,1244,1247,1250],{"class":42,"line":43},[40,1238,71],{"class":46},[40,1240,1241],{"class":74}," formData",[40,1243,78],{"class":46},[40,1245,1246],{"class":46}," new",[40,1248,1249],{"class":84}," FormData",[40,1251,1252],{"class":50},"()\n",[40,1254,1255,1258,1261,1263,1266,1268,1270],{"class":42,"line":61},[40,1256,1257],{"class":50},"formData.",[40,1259,1260],{"class":84},"append",[40,1262,324],{"class":50},[40,1264,1265],{"class":57},"'name'",[40,1267,240],{"class":50},[40,1269,785],{"class":57},[40,1271,1272],{"class":50},")\n",[40,1274,1275,1277,1279,1281,1284],{"class":42,"line":68},[40,1276,1257],{"class":50},[40,1278,1260],{"class":84},[40,1280,324],{"class":50},[40,1282,1283],{"class":57},"'avatar'",[40,1285,1286],{"class":50},", file)\n",[40,1288,1289],{"class":42,"line":91},[40,1290,65],{"emptyLinePlaceholder":64},[40,1292,1293,1295,1297,1299,1301],{"class":42,"line":103},[40,1294,318],{"class":46},[40,1296,321],{"class":84},[40,1298,324],{"class":50},[40,1300,908],{"class":57},[40,1302,330],{"class":50},[40,1304,1305,1308,1311],{"class":42,"line":114},[40,1306,1307],{"class":50},"  mediaType: ",[40,1309,1310],{"class":57},"'multipart\u002Fform-data'",[40,1312,149],{"class":50},[40,1314,1315,1318],{"class":42,"line":120},[40,1316,1317],{"class":50},"  body: formData, ",[40,1319,1320],{"class":527},"\u002F\u002F typed as FormData; content-type is left to the runtime\n",[40,1322,1323],{"class":42,"line":125},[40,1324,117],{"class":50},[10,1326,1327,1328,1330,1331,1334],{},"Maps without a JSON member make ",[22,1329,1205],{}," required at the type level. The\noption also participates in ",[22,1332,1333],{},"useEndpoint"," and Vue Query cache keys, so calls\ndiffering only by media type never share a cache entry.",[10,1336,1337,1338,1340,1341,1343,1344,1346,1347,1349],{},"Send ",[22,1339,1089],{}," from the client. Its ",[22,1342,877],{}," carries a\nboundary generated while the request is built, and a server-side call to a\nlocal route never builds one — Nuxt dispatches straight into the handler — so\nsuch a call arrives without a ",[22,1345,877],{}," and is rejected with ",[22,1348,885],{},". Every\nother media type is labelled by the client itself and works from either side.",[10,1351,1352],{},"Two caveats:",[483,1354,1355,1365],{},[486,1356,1357,1358,1361,1362,1364],{},"The generated OpenAPI document lists every member under ",[22,1359,1360],{},"requestBody.content",".\nSchema constructs the converter libraries cannot express (such as\n",[22,1363,1097],{},") fail conversion according to those libraries' behavior.",[486,1366,1367,1368,1370,1371,1373,1374,1377],{},"The default idempotency fingerprint projects ",[22,1369,506],{},", and ",[22,1372,1093],{}," values are\nnot JSON-serializable, so an idempotent multipart endpoint must supply a\ncustom ",[22,1375,1376],{},"fingerprint"," that projects serializable fields only.",[14,1379,1381],{"id":1380},"hooks","Hooks",[10,1383,1384,1385,1387,1388,835],{},"Two extension points sit on every endpoint, and both are declared the same way\nat either scope: as runtime options on ",[22,1386,24],{},", or application-wide\nin ",[22,1389,1390],{},"server\u002Fendpoints\u002Fruntime.ts",[31,1392,1394],{"className":33,"code":1393,"language":35,"meta":36,"style":36},"\u002F\u002F server\u002Fendpoints\u002Fruntime.ts\nexport default defineEndpointRuntime({\n  onValidationError: ({ kind, source, event }) => ({\n    status: 422,\n    body: { error: 'invalid_request', field: source, reason: kind },\n  }),\n  wrapHandler: async (context, next) => {\n    const started = Date.now()\n    try {\n      return await next()\n    } finally {\n      recordDuration(context.event, Date.now() - started)\n    }\n  },\n})\n",[22,1395,1396,1401,1412,1439,1449,1460,1466,1494,1512,1519,1532,1542,1561,1565,1571],{"__ignoreMap":36},[40,1397,1398],{"class":42,"line":43},[40,1399,1400],{"class":527},"\u002F\u002F server\u002Fendpoints\u002Fruntime.ts\n",[40,1402,1403,1405,1407,1410],{"class":42,"line":61},[40,1404,128],{"class":46},[40,1406,131],{"class":46},[40,1408,1409],{"class":84}," defineEndpointRuntime",[40,1411,88],{"class":137},[40,1413,1414,1417,1419,1422,1424,1427,1429,1432,1434,1436],{"class":42,"line":68},[40,1415,1416],{"class":84},"  onValidationError",[40,1418,234],{"class":50},[40,1420,1421],{"class":137},"kind",[40,1423,240],{"class":50},[40,1425,1426],{"class":137},"source",[40,1428,240],{"class":50},[40,1430,1431],{"class":137},"event",[40,1433,246],{"class":50},[40,1435,249],{"class":46},[40,1437,1438],{"class":50}," ({\n",[40,1440,1441,1444,1447],{"class":42,"line":91},[40,1442,1443],{"class":50},"    status: ",[40,1445,1446],{"class":74},"422",[40,1448,149],{"class":50},[40,1450,1451,1454,1457],{"class":42,"line":103},[40,1452,1453],{"class":50},"    body: { error: ",[40,1455,1456],{"class":57},"'invalid_request'",[40,1458,1459],{"class":50},", field: source, reason: kind },\n",[40,1461,1462,1464],{"class":42,"line":114},[40,1463,175],{"class":50},[40,1465,149],{"class":137},[40,1467,1468,1471,1473,1476,1479,1482,1484,1487,1490,1492],{"class":42,"line":120},[40,1469,1470],{"class":84},"  wrapHandler",[40,1472,1153],{"class":50},[40,1474,1475],{"class":46},"async",[40,1477,1478],{"class":50}," (",[40,1480,1481],{"class":137},"context",[40,1483,240],{"class":50},[40,1485,1486],{"class":137},"next",[40,1488,1489],{"class":50},") ",[40,1491,249],{"class":46},[40,1493,252],{"class":50},[40,1495,1496,1499,1502,1504,1507,1510],{"class":42,"line":125},[40,1497,1498],{"class":46},"    const",[40,1500,1501],{"class":74}," started",[40,1503,78],{"class":46},[40,1505,1506],{"class":50}," Date.",[40,1508,1509],{"class":84},"now",[40,1511,1252],{"class":50},[40,1513,1514,1517],{"class":42,"line":140},[40,1515,1516],{"class":46},"    try",[40,1518,252],{"class":50},[40,1520,1521,1524,1527,1530],{"class":42,"line":152},[40,1522,1523],{"class":46},"      return",[40,1525,1526],{"class":46}," await",[40,1528,1529],{"class":84}," next",[40,1531,1252],{"class":50},[40,1533,1534,1537,1540],{"class":42,"line":162},[40,1535,1536],{"class":50},"    } ",[40,1538,1539],{"class":46},"finally",[40,1541,252],{"class":50},[40,1543,1544,1547,1550,1552,1555,1558],{"class":42,"line":172},[40,1545,1546],{"class":84},"      recordDuration",[40,1548,1549],{"class":50},"(context.event, Date.",[40,1551,1509],{"class":84},[40,1553,1554],{"class":50},"() ",[40,1556,1557],{"class":46},"-",[40,1559,1560],{"class":50}," started)\n",[40,1562,1563],{"class":42,"line":180},[40,1564,292],{"class":50},[40,1566,1567,1569],{"class":42,"line":190},[40,1568,298],{"class":50},[40,1570,149],{"class":137},[40,1572,1573],{"class":42,"line":207},[40,1574,117],{"class":137},[31,1576,1578],{"className":33,"code":1577,"language":35,"meta":36,"style":36},"\u002F\u002F or on one endpoint, using the same key names\nexport const endpoint = defineEndpoint(\n  { query: z.object({ page: z.coerce.number() }) },\n  {\n    onValidationError: (failure) =>\n      failure.kind === 'media-type'\n        ? { status: 400, body: { accepts: failure.supportedMediaTypes } }\n        : undefined,\n  },\n)\n",[22,1579,1580,1585,1601,1616,1621,1637,1647,1661,1671,1676],{"__ignoreMap":36},[40,1581,1582],{"class":42,"line":43},[40,1583,1584],{"class":527},"\u002F\u002F or on one endpoint, using the same key names\n",[40,1586,1587,1589,1591,1594,1596,1598],{"class":42,"line":61},[40,1588,128],{"class":46},[40,1590,535],{"class":46},[40,1592,1593],{"class":74}," endpoint",[40,1595,78],{"class":46},[40,1597,134],{"class":84},[40,1599,1600],{"class":50},"(\n",[40,1602,1603,1606,1608,1611,1613],{"class":42,"line":68},[40,1604,1605],{"class":50},"  { query: z.",[40,1607,85],{"class":84},[40,1609,1610],{"class":50},"({ page: z.coerce.",[40,1612,97],{"class":84},[40,1614,1615],{"class":50},"() }) },\n",[40,1617,1618],{"class":42,"line":91},[40,1619,1620],{"class":50},"  {\n",[40,1622,1623,1626,1629,1632,1634],{"class":42,"line":103},[40,1624,1625],{"class":84},"    onValidationError",[40,1627,1628],{"class":50},": (",[40,1630,1631],{"class":137},"failure",[40,1633,1489],{"class":50},[40,1635,1636],{"class":46},"=>\n",[40,1638,1639,1642,1644],{"class":42,"line":114},[40,1640,1641],{"class":50},"      failure.kind ",[40,1643,1024],{"class":46},[40,1645,1646],{"class":57}," 'media-type'\n",[40,1648,1649,1652,1655,1658],{"class":42,"line":120},[40,1650,1651],{"class":46},"        ?",[40,1653,1654],{"class":50}," { status: ",[40,1656,1657],{"class":74},"400",[40,1659,1660],{"class":50},", body: { accepts: failure.supportedMediaTypes } }\n",[40,1662,1663,1666,1669],{"class":42,"line":125},[40,1664,1665],{"class":46},"        :",[40,1667,1668],{"class":74}," undefined",[40,1670,149],{"class":50},[40,1672,1673],{"class":42,"line":140},[40,1674,1675],{"class":50},"  },\n",[40,1677,1678],{"class":42,"line":152},[40,1679,1272],{"class":50},[1681,1682,1684],"h3",{"id":1683},"onvalidationerror","onValidationError",[10,1686,1687,1688,1690,1691,1693],{},"Shapes the response for a request that does not match its contract, replacing\nthe default ",[22,1689,1657],{}," for a schema failure and ",[22,1692,885],{}," when no media-type member\nmatches. The failure describes what its kind can:",[483,1695,1696,1719],{},[486,1697,1698,1701,1702,1704,1705,240,1707,240,1709,1711,1712,1714,1715,1718],{},[22,1699,1700],{},"kind: 'schema'"," — ",[22,1703,1426],{}," is ",[22,1706,237],{},[22,1708,243],{},[22,1710,500],{},", or ",[22,1713,506],{},", and\n",[22,1716,1717],{},"issues"," holds the validator's issues.",[486,1720,1721,1701,1724,1726,1727,1729,1730,1733,1734,1737,1738,1741],{},[22,1722,1723],{},"kind: 'media-type'",[22,1725,1426],{}," is always ",[22,1728,506],{},", with the normalized\n",[22,1731,1732],{},"received"," Content-Type (",[22,1735,1736],{},"null"," when the request sent none) and the\n",[22,1739,1740],{},"supportedMediaTypes"," the contract declares.",[10,1743,1744,1745,1747,1748,240,1751,1753,1754,832,1757,1759],{},"Both carry ",[22,1746,1431],{},", so an envelope can include values Nitro middleware\nattached. Return ",[22,1749,1750],{},"status",[22,1752,506],{},", and optionally ",[22,1755,1756],{},"statusText",[22,1758,500],{}," —\nor return nothing to decline, which passes the failure to the next scope.\nResolution runs endpoint → application → default.",[10,1761,1762,1763,1766],{},"Handler exceptions are ordinary Nitro errors and stay outside this hook, as do\nidempotency failures, which keep their ",[22,1764,1765],{},"application\u002Fproblem+json"," Problem\nDetails shape.",[1681,1768,1770],{"id":1769},"wraphandler","wrapHandler",[10,1772,1773,1774,1777,1778,850,1781,1783],{},"Wraps handler execution, after validation. Call ",[22,1775,1776],{},"next()"," to run the handler,\nor return a response without calling it to answer on its behalf — that is how\na recorded idempotent response is replayed. Because a wrapper is an ordinary\nfunction, ",[22,1779,1780],{},"try",[22,1782,1539],{}," is how work that must survive a thrown handler is\nexpressed, and its own scope is how state is carried across the call.",[10,1785,1786],{},"Wrappers nest outermost-first: the application wrapper, then the endpoint's\nown, then that endpoint's idempotency handling closest to the handler. A\nreplayed response therefore still unwinds back out through both wrappers,\nwhich is what makes rate limiting or audit logging count replays too.",[10,1788,1789,1790,1793,1794,240,1796,240,1798,1370,1800,1802],{},"The context is the same one the handler receives, so ",[22,1791,1792],{},"context.event",",\nvalidated ",[22,1795,237],{},[22,1797,243],{},[22,1799,500],{},[22,1801,506],{}," are all available.",[10,1804,1805,1807,1808,1811,1812,1816,1817,835],{},[22,1806,1390],{}," holds every application-wide endpoint setting\nthat ",[22,1809,1810],{},"nuxt.config.ts"," cannot: module options reach the server as JSON, so they\ncannot carry functions or the connections those functions close over. Two more\nsettings live in the same file under their own keys — the\n",[1167,1813,1815],{"href":1814},"\u002Fdocs\u002Fidempotency#central-policy","central idempotency policy"," and\n",[1167,1818,1820],{"href":1819},"\u002Fdocs\u002Fopenapi#document-metadata","OpenAPI document metadata",[10,1822,1823,1824,835],{},"To use a different path, set\n",[22,1825,1826],{},"endpoints: { runtime: { path: 'server\u002Fpolicies\u002Fendpoints.ts' } }",[14,1828,1830],{"id":1829},"request-event-and-middleware-context","Request event and middleware context",[10,1832,1833,1834,1836,1837,1118],{},"The handler context exposes both the original H3 ",[22,1835,1431],{}," and a normalized Web ",[22,1838,1839],{},"request",[483,1841,1842,1848],{},[486,1843,1844,1845,1847],{},"Use ",[22,1846,1431],{}," for Nitro middleware context and other runtime-specific features.",[486,1849,1844,1850,1852],{},[22,1851,1839],{}," for portable access to the URL, method, headers, and abort signal.",[10,1854,1855,1856,1859],{},"This does not change the endpoint handler into a Web-standard ",[22,1857,1858],{},"(Request) => Response"," handler. It still receives the typed endpoint context and may return a plain value.",[10,1861,1862,1863,835],{},"Use standard Nitro middleware to attach request-scoped values such as the current user, tenant, request ID, or tracing context to ",[22,1864,1865],{},"event.context",[31,1867,1869],{"className":33,"code":1868,"language":35,"meta":36,"style":36},"\u002F\u002F server\u002Fmiddleware\u002Fauth.ts\nexport default defineEventHandler(async (event) => {\n  event.context.user = await requireUserSession(event)\n})\n",[22,1870,1871,1876,1896,1912],{"__ignoreMap":36},[40,1872,1873],{"class":42,"line":43},[40,1874,1875],{"class":527},"\u002F\u002F server\u002Fmiddleware\u002Fauth.ts\n",[40,1877,1878,1880,1882,1885,1887,1889,1892,1894],{"class":42,"line":61},[40,1879,128],{"class":46},[40,1881,131],{"class":46},[40,1883,1884],{"class":84}," defineEventHandler",[40,1886,324],{"class":137},[40,1888,1475],{"class":46},[40,1890,1891],{"class":137}," (event) ",[40,1893,249],{"class":46},[40,1895,252],{"class":50},[40,1897,1898,1901,1904,1906,1909],{"class":42,"line":68},[40,1899,1900],{"class":50},"  event.context.user ",[40,1902,1903],{"class":46},"=",[40,1905,1526],{"class":46},[40,1907,1908],{"class":84}," requireUserSession",[40,1910,1911],{"class":50},"(event)\n",[40,1913,1914,1917],{"class":42,"line":91},[40,1915,1916],{"class":50},"}",[40,1918,1272],{"class":137},[10,1920,1921],{},"The same event and its middleware context are available alongside the Web request in an endpoint handler:",[31,1923,1925],{"className":33,"code":1924,"language":35,"meta":36,"style":36},"export default defineEndpoint({\n  params: z.object({ id: z.coerce.number() }),\n  handler: ({ event, request, params }) => {\n    const requestId = request.headers.get('x-request-id')\n    return findUser(event.context.user.accountId, params.id, requestId)\n  },\n})\n",[22,1926,1927,1937,1952,1974,1996,2005,2011],{"__ignoreMap":36},[40,1928,1929,1931,1933,1935],{"class":42,"line":43},[40,1930,128],{"class":46},[40,1932,131],{"class":46},[40,1934,134],{"class":84},[40,1936,88],{"class":137},[40,1938,1939,1941,1943,1945,1947,1950],{"class":42,"line":61},[40,1940,155],{"class":50},[40,1942,85],{"class":84},[40,1944,574],{"class":50},[40,1946,97],{"class":84},[40,1948,1949],{"class":50},"() })",[40,1951,149],{"class":137},[40,1953,1954,1956,1958,1960,1962,1964,1966,1968,1970,1972],{"class":42,"line":68},[40,1955,231],{"class":84},[40,1957,234],{"class":50},[40,1959,1431],{"class":137},[40,1961,240],{"class":50},[40,1963,1839],{"class":137},[40,1965,240],{"class":50},[40,1967,237],{"class":137},[40,1969,246],{"class":50},[40,1971,249],{"class":46},[40,1973,252],{"class":50},[40,1975,1976,1978,1981,1983,1986,1989,1991,1994],{"class":42,"line":91},[40,1977,1498],{"class":46},[40,1979,1980],{"class":74}," requestId",[40,1982,78],{"class":46},[40,1984,1985],{"class":50}," request.headers.",[40,1987,1988],{"class":84},"get",[40,1990,324],{"class":50},[40,1992,1993],{"class":57},"'x-request-id'",[40,1995,1272],{"class":50},[40,1997,1998,2000,2002],{"class":42,"line":103},[40,1999,258],{"class":46},[40,2001,429],{"class":84},[40,2003,2004],{"class":50},"(event.context.user.accountId, params.id, requestId)\n",[40,2006,2007,2009],{"class":42,"line":114},[40,2008,298],{"class":50},[40,2010,149],{"class":137},[40,2012,2013],{"class":42,"line":120},[40,2014,117],{"class":137},[10,2016,2017,2018,2020,2021,2023],{},"For endpoints with a body contract, use the parsed and validated ",[22,2019,506],{}," value from the endpoint context. Do not assume that the raw ",[22,2022,1839],{}," body can be consumed again after endpoint parsing.",[10,2025,2026],{},"Use H3 module augmentation when the application needs shared static types for custom context fields:",[31,2028,2030],{"className":33,"code":2029,"language":35,"meta":36,"style":36},"declare module 'h3' {\n  interface H3EventContext {\n    user: {\n      id: string\n      accountId: string\n    }\n  }\n}\n",[22,2031,2032,2045,2055,2064,2074,2083,2087,2092],{"__ignoreMap":36},[40,2033,2034,2037,2040,2043],{"class":42,"line":43},[40,2035,2036],{"class":46},"declare",[40,2038,2039],{"class":46}," module",[40,2041,2042],{"class":57}," 'h3'",[40,2044,252],{"class":50},[40,2046,2047,2050,2053],{"class":42,"line":61},[40,2048,2049],{"class":46},"  interface",[40,2051,2052],{"class":137}," H3EventContext",[40,2054,252],{"class":50},[40,2056,2057,2060,2062],{"class":42,"line":68},[40,2058,2059],{"class":137},"    user",[40,2061,1118],{"class":46},[40,2063,252],{"class":50},[40,2065,2066,2069,2071],{"class":42,"line":91},[40,2067,2068],{"class":137},"      id",[40,2070,1118],{"class":46},[40,2072,2073],{"class":74}," string\n",[40,2075,2076,2079,2081],{"class":42,"line":103},[40,2077,2078],{"class":137},"      accountId",[40,2080,1118],{"class":46},[40,2082,2073],{"class":74},[40,2084,2085],{"class":42,"line":114},[40,2086,292],{"class":50},[40,2088,2089],{"class":42,"line":120},[40,2090,2091],{"class":50},"  }\n",[40,2093,2094],{"class":42,"line":125},[40,2095,1162],{"class":50},[14,2097,2099],{"id":2098},"multiple-responses","Multiple responses",[10,2101,1844,2102,2105,2106,2108],{},[22,2103,2104],{},"responses"," when an endpoint can return multiple statuses. Return a specific status with ",[22,2107,709],{},", and TypeScript checks that the body matches the declared schema.",[31,2110,2112],{"className":33,"code":2111,"language":35,"meta":36,"style":36},"const ErrorBody = z.object({\n  message: z.string(),\n})\n\nexport default defineEndpoint({\n  params: z.object({\n    id: z.coerce.number(),\n  }),\n  responses: {\n    200: User,\n    404: ErrorBody,\n  },\n  handler: ({ params, respond }) => {\n    if (params.id === 404) {\n      return respond(404, { message: 'Not found' })\n    }\n\n    return { id: params.id, name: 'Tom' }\n  },\n})\n",[22,2113,2114,2129,2138,2142,2146,2156,2164,2172,2178,2183,2191,2199,2205,2223,2237,2256,2260,2264,2276,2282],{"__ignoreMap":36},[40,2115,2116,2118,2121,2123,2125,2127],{"class":42,"line":43},[40,2117,71],{"class":46},[40,2119,2120],{"class":74}," ErrorBody",[40,2122,78],{"class":46},[40,2124,81],{"class":50},[40,2126,85],{"class":84},[40,2128,88],{"class":50},[40,2130,2131,2134,2136],{"class":42,"line":61},[40,2132,2133],{"class":50},"  message: z.",[40,2135,109],{"class":84},[40,2137,100],{"class":50},[40,2139,2140],{"class":42,"line":68},[40,2141,117],{"class":50},[40,2143,2144],{"class":42,"line":91},[40,2145,65],{"emptyLinePlaceholder":64},[40,2147,2148,2150,2152,2154],{"class":42,"line":103},[40,2149,128],{"class":46},[40,2151,131],{"class":46},[40,2153,134],{"class":84},[40,2155,88],{"class":137},[40,2157,2158,2160,2162],{"class":42,"line":114},[40,2159,155],{"class":50},[40,2161,85],{"class":84},[40,2163,88],{"class":50},[40,2165,2166,2168,2170],{"class":42,"line":120},[40,2167,165],{"class":50},[40,2169,97],{"class":84},[40,2171,100],{"class":50},[40,2173,2174,2176],{"class":42,"line":125},[40,2175,175],{"class":50},[40,2177,149],{"class":137},[40,2179,2180],{"class":42,"line":140},[40,2181,2182],{"class":50},"  responses: {\n",[40,2184,2185,2188],{"class":42,"line":152},[40,2186,2187],{"class":74},"    200",[40,2189,2190],{"class":50},": User,\n",[40,2192,2193,2196],{"class":42,"line":162},[40,2194,2195],{"class":74},"    404",[40,2197,2198],{"class":50},": ErrorBody,\n",[40,2200,2201,2203],{"class":42,"line":172},[40,2202,298],{"class":50},[40,2204,149],{"class":137},[40,2206,2207,2209,2211,2213,2215,2217,2219,2221],{"class":42,"line":180},[40,2208,231],{"class":84},[40,2210,234],{"class":50},[40,2212,237],{"class":137},[40,2214,240],{"class":50},[40,2216,709],{"class":137},[40,2218,246],{"class":50},[40,2220,249],{"class":46},[40,2222,252],{"class":50},[40,2224,2225,2227,2230,2232,2235],{"class":42,"line":190},[40,2226,1018],{"class":46},[40,2228,2229],{"class":50}," (params.id ",[40,2231,1024],{"class":46},[40,2233,2234],{"class":74}," 404",[40,2236,1030],{"class":50},[40,2238,2239,2241,2243,2245,2247,2250,2253],{"class":42,"line":207},[40,2240,1523],{"class":46},[40,2242,716],{"class":84},[40,2244,324],{"class":50},[40,2246,641],{"class":74},[40,2248,2249],{"class":50},", { message: ",[40,2251,2252],{"class":57},"'Not found'",[40,2254,2255],{"class":50}," })\n",[40,2257,2258],{"class":42,"line":214},[40,2259,292],{"class":50},[40,2261,2262],{"class":42,"line":228},[40,2263,65],{"emptyLinePlaceholder":64},[40,2265,2266,2268,2271,2273],{"class":42,"line":255},[40,2267,258],{"class":46},[40,2269,2270],{"class":50}," { id: params.id, name: ",[40,2272,785],{"class":57},[40,2274,2275],{"class":50}," }\n",[40,2277,2278,2280],{"class":42,"line":263},[40,2279,298],{"class":50},[40,2281,149],{"class":137},[40,2283,2284],{"class":42,"line":269},[40,2285,117],{"class":137},[14,2287,2289],{"id":2288},"non-json-responses","Non-JSON responses",[10,2291,2292],{},"A validated response body is always sent as JSON — that is what having a schema for it means. Everything else goes through one door: declare the status by its media type instead of by a schema.",[31,2294,2296],{"className":33,"code":2295,"language":35,"meta":36,"style":36},"export default defineEndpoint({\n  operation: 'exportUsers',\n  query: z.object({ delimiter: z.string().optional() }),\n  responses: {\n    200: { media: 'text\u002Fcsv', description: 'CSV export' },\n    404: ErrorBody,\n  },\n  handler: ({ query, respond }) => {\n    return respond(200, toCsvStream(query.delimiter ?? ','))\n  },\n})\n",[22,2297,2298,2308,2317,2336,2340,2358,2364,2370,2388,2415,2421],{"__ignoreMap":36},[40,2299,2300,2302,2304,2306],{"class":42,"line":43},[40,2301,128],{"class":46},[40,2303,131],{"class":46},[40,2305,134],{"class":84},[40,2307,88],{"class":137},[40,2309,2310,2312,2315],{"class":42,"line":61},[40,2311,392],{"class":50},[40,2313,2314],{"class":57},"'exportUsers'",[40,2316,149],{"class":137},[40,2318,2319,2321,2323,2326,2328,2330,2332,2334],{"class":42,"line":68},[40,2320,183],{"class":50},[40,2322,85],{"class":84},[40,2324,2325],{"class":50},"({ delimiter: z.",[40,2327,109],{"class":84},[40,2329,199],{"class":50},[40,2331,202],{"class":84},[40,2333,1949],{"class":50},[40,2335,149],{"class":137},[40,2337,2338],{"class":42,"line":91},[40,2339,2182],{"class":50},[40,2341,2342,2344,2347,2350,2353,2356],{"class":42,"line":103},[40,2343,2187],{"class":74},[40,2345,2346],{"class":50},": { media: ",[40,2348,2349],{"class":57},"'text\u002Fcsv'",[40,2351,2352],{"class":50},", description: ",[40,2354,2355],{"class":57},"'CSV export'",[40,2357,351],{"class":50},[40,2359,2360,2362],{"class":42,"line":114},[40,2361,2195],{"class":74},[40,2363,2198],{"class":50},[40,2365,2366,2368],{"class":42,"line":120},[40,2367,298],{"class":50},[40,2369,149],{"class":137},[40,2371,2372,2374,2376,2378,2380,2382,2384,2386],{"class":42,"line":125},[40,2373,231],{"class":84},[40,2375,234],{"class":50},[40,2377,243],{"class":137},[40,2379,240],{"class":50},[40,2381,709],{"class":137},[40,2383,246],{"class":50},[40,2385,249],{"class":46},[40,2387,252],{"class":50},[40,2389,2390,2392,2394,2396,2398,2400,2403,2406,2409,2412],{"class":42,"line":140},[40,2391,258],{"class":46},[40,2393,716],{"class":84},[40,2395,324],{"class":50},[40,2397,220],{"class":74},[40,2399,240],{"class":50},[40,2401,2402],{"class":84},"toCsvStream",[40,2404,2405],{"class":50},"(query.delimiter ",[40,2407,2408],{"class":46},"??",[40,2410,2411],{"class":57}," ','",[40,2413,2414],{"class":50},"))\n",[40,2416,2417,2419],{"class":42,"line":152},[40,2418,298],{"class":50},[40,2420,149],{"class":137},[40,2422,2423],{"class":42,"line":162},[40,2424,117],{"class":137},[10,2426,2427],{},"The same door covers every case that is not JSON — XML, CSV, a file download, an event stream, arbitrary bytes:",[31,2429,2431],{"className":33,"code":2430,"language":35,"meta":36,"style":36},"responses: {\n  200: { media: 'application\u002Fxml' },\n  200: { media: 'application\u002Fpdf' },\n  200: { media: 'text\u002Fevent-stream' },\n  200: { media: 'application\u002Foctet-stream' },\n}\n",[22,2432,2433,2439,2451,2462,2473,2484],{"__ignoreMap":36},[40,2434,2435,2437],{"class":42,"line":43},[40,2436,2104],{"class":137},[40,2438,1130],{"class":50},[40,2440,2441,2444,2446,2449],{"class":42,"line":61},[40,2442,2443],{"class":74},"  200",[40,2445,2346],{"class":50},[40,2447,2448],{"class":57},"'application\u002Fxml'",[40,2450,351],{"class":50},[40,2452,2453,2455,2457,2460],{"class":42,"line":68},[40,2454,2443],{"class":74},[40,2456,2346],{"class":50},[40,2458,2459],{"class":57},"'application\u002Fpdf'",[40,2461,351],{"class":50},[40,2463,2464,2466,2468,2471],{"class":42,"line":91},[40,2465,2443],{"class":74},[40,2467,2346],{"class":50},[40,2469,2470],{"class":57},"'text\u002Fevent-stream'",[40,2472,351],{"class":50},[40,2474,2475,2477,2479,2482],{"class":42,"line":103},[40,2476,2443],{"class":74},[40,2478,2346],{"class":50},[40,2480,2481],{"class":57},"'application\u002Foctet-stream'",[40,2483,351],{"class":50},[40,2485,2486],{"class":42,"line":114},[40,2487,1162],{"class":50},[10,2489,2490,2491,2494,2495,2498,2499,2502],{},"The handler may return anything the HTTP layer forwards to the socket as-is: a web ",[22,2492,2493],{},"ReadableStream",", a Node readable, a native ",[22,2496,2497],{},"Response",", a ",[22,2500,2501],{},"Blob",", raw bytes, or an already-encoded string. The declared media type is sent for you unless the handler sets one itself.",[10,2504,2505,2506,2508,2509,2512,2513,2517,2518,2520,2521,2523],{},"Nothing about the payload is validated, and that is the whole distinction from ",[22,2507,506],{},". There is no schema to check it against, and a stream cannot be buffered and checked without defeating the reason it is a stream. The media type is required rather than defaulted, because taking this door means knowing what you are sending. An optional ",[22,2510,2511],{},"schema"," documents the payload — or one chunk of it — in the ",[1167,2514,2516],{"href":2515},"\u002Fdocs\u002Fopenapi","generated OpenAPI document",", and is named ",[22,2519,2511],{}," rather than ",[22,2522,506],{}," precisely because it never checks anything:",[31,2525,2527],{"className":33,"code":2526,"language":35,"meta":36,"style":36},"responses: {\n  200: {\n    media: 'application\u002Fx-ndjson',\n    schema: z.object({ id: z.string(), at: z.string() }),\n  },\n}\n",[22,2528,2529,2535,2541,2551,2570,2574],{"__ignoreMap":36},[40,2530,2531,2533],{"class":42,"line":43},[40,2532,2104],{"class":137},[40,2534,1130],{"class":50},[40,2536,2537,2539],{"class":42,"line":61},[40,2538,2443],{"class":74},[40,2540,1130],{"class":50},[40,2542,2543,2546,2549],{"class":42,"line":68},[40,2544,2545],{"class":50},"    media: ",[40,2547,2548],{"class":57},"'application\u002Fx-ndjson'",[40,2550,149],{"class":50},[40,2552,2553,2556,2558,2561,2563,2566,2568],{"class":42,"line":91},[40,2554,2555],{"class":50},"    schema: z.",[40,2557,85],{"class":84},[40,2559,2560],{"class":50},"({ id: z.",[40,2562,109],{"class":84},[40,2564,2565],{"class":50},"(), at: z.",[40,2567,109],{"class":84},[40,2569,579],{"class":50},[40,2571,2572],{"class":42,"line":103},[40,2573,1675],{"class":50},[40,2575,2576],{"class":42,"line":114},[40,2577,1162],{"class":50},[10,2579,2580],{},"With several declared media types, key the schema by media type — one schema cannot honestly describe a CSV and a JSON object at once, so a bare schema alongside several types fails the build rather than being copied onto each. Types the map omits stay described as opaque bytes:",[31,2582,2584],{"className":33,"code":2583,"language":35,"meta":36,"style":36},"responses: {\n  200: {\n    media: ['text\u002Fcsv', 'application\u002Fjson'],\n    schema: { 'application\u002Fjson': z.object({ id: z.string(), name: z.string() }) },\n  },\n}\n",[22,2585,2586,2592,2598,2613,2635,2639],{"__ignoreMap":36},[40,2587,2588,2590],{"class":42,"line":43},[40,2589,2104],{"class":137},[40,2591,1130],{"class":50},[40,2593,2594,2596],{"class":42,"line":61},[40,2595,2443],{"class":74},[40,2597,1130],{"class":50},[40,2599,2600,2603,2605,2607,2610],{"class":42,"line":68},[40,2601,2602],{"class":50},"    media: [",[40,2604,2349],{"class":57},[40,2606,240],{"class":50},[40,2608,2609],{"class":57},"'application\u002Fjson'",[40,2611,2612],{"class":50},"],\n",[40,2614,2615,2618,2620,2622,2624,2626,2628,2631,2633],{"class":42,"line":91},[40,2616,2617],{"class":50},"    schema: { ",[40,2619,2609],{"class":57},[40,2621,923],{"class":50},[40,2623,85],{"class":84},[40,2625,2560],{"class":50},[40,2627,109],{"class":84},[40,2629,2630],{"class":50},"(), name: z.",[40,2632,109],{"class":84},[40,2634,1615],{"class":50},[40,2636,2637],{"class":42,"line":103},[40,2638,1675],{"class":50},[40,2640,2641],{"class":42,"line":114},[40,2642,1162],{"class":50},[1681,2644,2646],{"id":2645},"several-representations-of-one-status","Several representations of one status",[10,2648,2649,2650,2653,2654,2657],{},"Give ",[22,2651,2652],{},"media"," an array and the status has more than one representation. The runtime negotiates from the request's ",[22,2655,2656],{},"Accept"," header, tells the handler which one to produce, and sends that media type:",[31,2659,2661],{"className":33,"code":2660,"language":35,"meta":36,"style":36},"export default defineEndpoint({\n  operation: 'exportUsers',\n  responses: {\n    200: { media: ['text\u002Fcsv', 'application\u002Fjson'], description: 'User export' },\n    404: ErrorBody,\n  },\n  handler: ({ responseMediaType, respond }) => {\n    \u002F\u002F narrowed to 'text\u002Fcsv' | 'application\u002Fjson'\n    return respond(200, responseMediaType === 'text\u002Fcsv' ? toCsv(rows) : JSON.stringify(rows))\n  },\n})\n",[22,2662,2663,2673,2681,2685,2706,2712,2718,2737,2742,2782,2788],{"__ignoreMap":36},[40,2664,2665,2667,2669,2671],{"class":42,"line":43},[40,2666,128],{"class":46},[40,2668,131],{"class":46},[40,2670,134],{"class":84},[40,2672,88],{"class":137},[40,2674,2675,2677,2679],{"class":42,"line":61},[40,2676,392],{"class":50},[40,2678,2314],{"class":57},[40,2680,149],{"class":137},[40,2682,2683],{"class":42,"line":68},[40,2684,2182],{"class":50},[40,2686,2687,2689,2692,2694,2696,2698,2701,2704],{"class":42,"line":91},[40,2688,2187],{"class":74},[40,2690,2691],{"class":50},": { media: [",[40,2693,2349],{"class":57},[40,2695,240],{"class":50},[40,2697,2609],{"class":57},[40,2699,2700],{"class":50},"], description: ",[40,2702,2703],{"class":57},"'User export'",[40,2705,351],{"class":50},[40,2707,2708,2710],{"class":42,"line":103},[40,2709,2195],{"class":74},[40,2711,2198],{"class":50},[40,2713,2714,2716],{"class":42,"line":114},[40,2715,298],{"class":50},[40,2717,149],{"class":137},[40,2719,2720,2722,2724,2727,2729,2731,2733,2735],{"class":42,"line":120},[40,2721,231],{"class":84},[40,2723,234],{"class":50},[40,2725,2726],{"class":137},"responseMediaType",[40,2728,240],{"class":50},[40,2730,709],{"class":137},[40,2732,246],{"class":50},[40,2734,249],{"class":46},[40,2736,252],{"class":50},[40,2738,2739],{"class":42,"line":125},[40,2740,2741],{"class":527},"    \u002F\u002F narrowed to 'text\u002Fcsv' | 'application\u002Fjson'\n",[40,2743,2744,2746,2748,2750,2752,2755,2757,2760,2763,2766,2769,2771,2774,2776,2779],{"class":42,"line":140},[40,2745,258],{"class":46},[40,2747,716],{"class":84},[40,2749,324],{"class":50},[40,2751,220],{"class":74},[40,2753,2754],{"class":50},", responseMediaType ",[40,2756,1024],{"class":46},[40,2758,2759],{"class":57}," 'text\u002Fcsv'",[40,2761,2762],{"class":46}," ?",[40,2764,2765],{"class":84}," toCsv",[40,2767,2768],{"class":50},"(rows) ",[40,2770,1118],{"class":46},[40,2772,2773],{"class":74}," JSON",[40,2775,835],{"class":50},[40,2777,2778],{"class":84},"stringify",[40,2780,2781],{"class":50},"(rows))\n",[40,2783,2784,2786],{"class":42,"line":152},[40,2785,298],{"class":50},[40,2787,149],{"class":137},[40,2789,2790],{"class":42,"line":162},[40,2791,117],{"class":137},[10,2793,2794,2795,2799,2800,2802,2803,2805],{},"This is the mirror image of a ",[1167,2796,2798],{"href":2797},"#media-type-request-bodies","media-type request body",": that one reads ",[22,2801,877],{}," and answers 415, this one reads ",[22,2804,2656],{}," and answers 406.",[10,2807,2808,2809,2813,2814,2817],{},"Only ",[2810,2811,2812],"em",{},"successful"," statuses take part. A media-typed error — a ",[22,2815,2816],{},"problem+json"," 404, an HTML error page — is not an alternative the caller chooses between; it is what happens instead. So adding one to an endpoint never starts refusing clients, and a request cannot negotiate its way into an error's media type.",[10,2819,2820,2821,2824,2825,2828],{},"Declaration order is the endpoint's own preference. It breaks ties between equally acceptable types, and it answers a request that expresses no preference at all — an absent header, or ",[22,2822,2823],{},"*\u002F*",". That is what makes omitting ",[22,2826,2827],{},"accept"," on the client a sensible default rather than an arbitrary one.",[10,2830,2831,2832,2834,2835,832,2838,2841,2842,2844],{},"Each media type must be a single lowercase ",[22,2833,1177],{},", and the build fails otherwise — ",[22,2836,2837],{},"media: 'text\u002Fcsv, application\u002Fjson'",[22,2839,2840],{},"media: ['csv', 'json']"," are rejected rather than becoming a nonsense ",[22,2843,877],{}," or an endpoint that answers 406 to everything.",[10,2846,2847,2848,2851,2852,2855,2856,1701,2860,2862,2863,2868,2869,835],{},"Selection follows RFC 9110: quality weights are honored, a more specific range overrides a wider one that would otherwise apply, and ",[22,2849,2850],{},"q=0"," is a refusal rather than a weak preference. When nothing the endpoint can produce is acceptable, the request is refused with ",[22,2853,2854],{},"406 Not Acceptable"," ",[2857,2858,2859],"strong",{},"before anything else is validated and before the body is read",[22,2861,2656],{}," does not depend on the rest of the request, and a request that can never be answered is not worth reading an upload for. That refusal goes through ",[1167,2864,2866],{"href":2865},"#hooks",[22,2867,1684],{}," like any other, with ",[22,2870,2871],{},"kind: 'accept'",[10,2873,2874,2875,2878,2879,2882,2883,2885],{},"Every response of a negotiating endpoint carries ",[22,2876,2877],{},"Vary: Accept"," — including the 406, and including statuses that are not media responses. The header describes the route, not one answer: a cache that only ever saw the CSV must still know the JSON exists. A handler that declares its own ",[22,2880,2881],{},"Vary"," adds to it rather than replacing it, because ",[22,2884,2881],{}," is a list of what the answer depended on and dropping an entry hands caches a wrong answer.",[10,2887,2888,2889,2891],{},"On the client, ",[22,2890,2827],{}," asks for one of the declared types and is typed to them:",[31,2893,2895],{"className":33,"code":2894,"language":35,"meta":36,"style":36},"const json = await $endpoint('exportUsers', { accept: 'application\u002Fjson' })\n",[22,2896,2897],{"__ignoreMap":36},[40,2898,2899,2901,2904,2906,2908,2910,2912,2914,2917,2919],{"class":42,"line":43},[40,2900,71],{"class":46},[40,2902,2903],{"class":74}," json",[40,2905,78],{"class":46},[40,2907,1526],{"class":46},[40,2909,321],{"class":84},[40,2911,324],{"class":50},[40,2913,2314],{"class":57},[40,2915,2916],{"class":50},", { accept: ",[40,2918,2609],{"class":57},[40,2920,2255],{"class":50},[10,2922,2923,2924,2926],{},"It is optional — omitting it takes the endpoint's preference — and it is part of the TanStack Query cache key, so two calls that differ only in ",[22,2925,2827],{}," are two cached values.",[10,2928,2929,2930,2936,2937,2939],{},"An endpoint that negotiates and also uses ",[1167,2931,2933],{"href":2932},"\u002Fdocs\u002Fidempotency",[22,2934,2935],{},"Idempotency-Key"," counts the negotiated media type as part of request identity: a retry that reuses the key but asks for a different representation is answered with ",[22,2938,1446],{},", not with the representation it did not ask for. Producing the other one would mean re-running a handler whose side effect already happened, which is what the key exists to prevent — use a separate key.",[10,2941,2942,2944],{},[22,2943,2726],{}," is present whenever the endpoint declares any media type, not only when it negotiates: with a single declared type it is that type. The field always means the same thing — what this response is being sent as.",[1681,2946,2948],{"id":2947},"json-with-a-different-media-type","JSON with a different media type",[10,2950,2951,2953,2954,2957,2958,2961],{},[22,2952,1765],{}," and other ",[22,2955,2956],{},"+json"," profiles are still JSON, so they keep their schema and stay validated. Label them with ",[22,2959,2960],{},"contentType"," on the validated form, and the header is sent:",[31,2963,2965],{"className":33,"code":2964,"language":35,"meta":36,"style":36},"responses: {\n  404: {\n    body: z.object({ type: z.string(), title: z.string(), status: z.number() }),\n    contentType: 'application\u002Fproblem+json',\n  },\n}\n",[22,2966,2967,2973,2980,3004,3014,3018],{"__ignoreMap":36},[40,2968,2969,2971],{"class":42,"line":43},[40,2970,2104],{"class":137},[40,2972,1130],{"class":50},[40,2974,2975,2978],{"class":42,"line":61},[40,2976,2977],{"class":74},"  404",[40,2979,1130],{"class":50},[40,2981,2982,2985,2987,2990,2992,2995,2997,3000,3002],{"class":42,"line":68},[40,2983,2984],{"class":50},"    body: z.",[40,2986,85],{"class":84},[40,2988,2989],{"class":50},"({ type: z.",[40,2991,109],{"class":84},[40,2993,2994],{"class":50},"(), title: z.",[40,2996,109],{"class":84},[40,2998,2999],{"class":50},"(), status: z.",[40,3001,97],{"class":84},[40,3003,579],{"class":50},[40,3005,3006,3009,3012],{"class":42,"line":91},[40,3007,3008],{"class":50},"    contentType: ",[40,3010,3011],{"class":57},"'application\u002Fproblem+json'",[40,3013,149],{"class":50},[40,3015,3016],{"class":42,"line":103},[40,3017,1675],{"class":50},[40,3019,3020],{"class":42,"line":114},[40,3021,1162],{"class":50},[10,3023,3024,3026,3027,3029],{},[22,3025,2960],{}," accepts JSON media types only. A non-JSON value there would describe one thing and send another, so the build fails and names ",[22,3028,2652],{}," as the replacement:",[31,3031,3036],{"className":3032,"code":3034,"language":3035},[3033],"language-text","Response 200 declares contentType 'application\u002Fxml' on a validated body,\nwhich is always sent as JSON. Declare media: 'application\u002Fxml' instead —\nit sends what the handler returns and documents that media type.\n","text",[22,3037,3034],{"__ignoreMap":36},[1681,3039,3041],{"id":3040},"on-the-client","On the client",[10,3043,3044],{},"A route with any media response is unparsed end to end: the generated client tells the fetcher not to read the body, so what you get back is the live stream rather than a decoded copy of it once it has all arrived.",[31,3046,3048],{"className":33,"code":3047,"language":35,"meta":36,"style":36},"const stream = await $endpoint('exportUsers', { query: { delimiter: ';' } })\nconst reader = stream.getReader()\n\n\u002F\u002F or, when you need the status and headers too\nconst response = await $endpoint('exportUsers', { query: {} }).raw()\n",[22,3049,3050,3075,3092,3096,3101],{"__ignoreMap":36},[40,3051,3052,3054,3057,3059,3061,3063,3065,3067,3070,3073],{"class":42,"line":43},[40,3053,71],{"class":46},[40,3055,3056],{"class":74}," stream",[40,3058,78],{"class":46},[40,3060,1526],{"class":46},[40,3062,321],{"class":84},[40,3064,324],{"class":50},[40,3066,2314],{"class":57},[40,3068,3069],{"class":50},", { query: { delimiter: ",[40,3071,3072],{"class":57},"';'",[40,3074,460],{"class":50},[40,3076,3077,3079,3082,3084,3087,3090],{"class":42,"line":61},[40,3078,71],{"class":46},[40,3080,3081],{"class":74}," reader",[40,3083,78],{"class":46},[40,3085,3086],{"class":50}," stream.",[40,3088,3089],{"class":84},"getReader",[40,3091,1252],{"class":50},[40,3093,3094],{"class":42,"line":68},[40,3095,65],{"emptyLinePlaceholder":64},[40,3097,3098],{"class":42,"line":91},[40,3099,3100],{"class":527},"\u002F\u002F or, when you need the status and headers too\n",[40,3102,3103,3105,3108,3110,3112,3114,3116,3118,3121,3124],{"class":42,"line":103},[40,3104,71],{"class":46},[40,3106,3107],{"class":74}," response",[40,3109,78],{"class":46},[40,3111,1526],{"class":46},[40,3113,321],{"class":84},[40,3115,324],{"class":50},[40,3117,2314],{"class":57},[40,3119,3120],{"class":50},", { query: {} }).",[40,3122,3123],{"class":84},"raw",[40,3125,1252],{"class":50},[10,3127,3128],{},"Two consequences follow from the client never parsing the response:",[483,3130,3131,3137],{},[486,3132,3133,3134,3136],{},"Every status of that route arrives as a stream, including a validated ",[22,3135,641],{}," the contract still declares. Those declarations remain true for the server and for OpenAPI; the client just hands you the bytes.",[486,3138,3139,3141],{},[22,3140,1333],{}," and the Vue Query factories are the wrong tools for such a route — an unread stream cannot be cached or serialized into the Nuxt payload. The build warns when one would get a query option factory.",[10,3143,3144,3145,3148],{},"Pass an explicit ",[22,3146,3147],{},"responseType"," when you want the fetcher to decode after all, which is the usual choice for a file download:",[31,3150,3152],{"className":33,"code":3151,"language":35,"meta":36,"style":36},"const blob = await $endpoint('downloadInvoice', { responseType: 'blob' })\n",[22,3153,3154],{"__ignoreMap":36},[40,3155,3156,3158,3161,3163,3165,3167,3169,3172,3175,3178],{"class":42,"line":43},[40,3157,71],{"class":46},[40,3159,3160],{"class":74}," blob",[40,3162,78],{"class":46},[40,3164,1526],{"class":46},[40,3166,321],{"class":84},[40,3168,324],{"class":50},[40,3170,3171],{"class":57},"'downloadInvoice'",[40,3173,3174],{"class":50},", { responseType: ",[40,3176,3177],{"class":57},"'blob'",[40,3179,2255],{"class":50},[14,3181,3183],{"id":3182},"response-validation","Response validation",[10,3185,3186],{},"Response validation is opt-in so production handlers can decide how strict their output boundary should be.",[31,3188,3190],{"className":33,"code":3189,"language":35,"meta":36,"style":36},"export const endpoint = defineEndpoint(\n  {\n    responses: { 200: User },\n  },\n  {\n    validation: {\n      response: true,\n    },\n  },\n)\n",[22,3191,3192,3206,3210,3218,3222,3226,3231,3240,3245,3249],{"__ignoreMap":36},[40,3193,3194,3196,3198,3200,3202,3204],{"class":42,"line":43},[40,3195,128],{"class":46},[40,3197,535],{"class":46},[40,3199,1593],{"class":74},[40,3201,78],{"class":46},[40,3203,134],{"class":84},[40,3205,1600],{"class":50},[40,3207,3208],{"class":42,"line":61},[40,3209,1620],{"class":50},[40,3211,3212,3214,3216],{"class":42,"line":68},[40,3213,584],{"class":50},[40,3215,220],{"class":74},[40,3217,589],{"class":50},[40,3219,3220],{"class":42,"line":91},[40,3221,1675],{"class":50},[40,3223,3224],{"class":42,"line":103},[40,3225,1620],{"class":50},[40,3227,3228],{"class":42,"line":114},[40,3229,3230],{"class":50},"    validation: {\n",[40,3232,3233,3236,3238],{"class":42,"line":120},[40,3234,3235],{"class":50},"      response: ",[40,3237,359],{"class":74},[40,3239,149],{"class":50},[40,3241,3242],{"class":42,"line":125},[40,3243,3244],{"class":50},"    },\n",[40,3246,3247],{"class":42,"line":140},[40,3248,1675],{"class":50},[40,3250,3251],{"class":42,"line":152},[40,3252,1272],{"class":50},[14,3254,3256],{"id":3255},"routes-registered-by-configuration","Routes registered by configuration",[10,3258,3259,3260,3263,3264,3267],{},"Discovery does not depend on file scanning. It reads Nitro's configured handlers alongside its scanned ones, so a route registered through ",[22,3261,3262],{},"nitro.handlers"," — or by another Nuxt module calling ",[22,3265,3266],{},"addServerHandler"," — is an ordinary endpoint: validated, in the generated client, typed identically, and in the OpenAPI document.",[31,3269,3271],{"className":33,"code":3270,"language":35,"meta":36,"style":36},"\u002F\u002F nuxt.config.ts\nexport default defineNuxtConfig({\n  nitro: {\n    handlers: [\n      {\n        route: '\u002Fcustom\u002Freport',\n        method: 'get',\n        handler: resolve('server\u002Fcustom-routes\u002Freport.get.ts'),\n      },\n    ],\n  },\n})\n",[22,3272,3273,3278,3289,3294,3299,3304,3314,3323,3339,3344,3349,3355],{"__ignoreMap":36},[40,3274,3275],{"class":42,"line":43},[40,3276,3277],{"class":527},"\u002F\u002F nuxt.config.ts\n",[40,3279,3280,3282,3284,3287],{"class":42,"line":61},[40,3281,128],{"class":46},[40,3283,131],{"class":46},[40,3285,3286],{"class":84}," defineNuxtConfig",[40,3288,88],{"class":137},[40,3290,3291],{"class":42,"line":68},[40,3292,3293],{"class":50},"  nitro: {\n",[40,3295,3296],{"class":42,"line":91},[40,3297,3298],{"class":50},"    handlers: [\n",[40,3300,3301],{"class":42,"line":103},[40,3302,3303],{"class":50},"      {\n",[40,3305,3306,3309,3312],{"class":42,"line":114},[40,3307,3308],{"class":50},"        route: ",[40,3310,3311],{"class":57},"'\u002Fcustom\u002Freport'",[40,3313,149],{"class":50},[40,3315,3316,3319,3321],{"class":42,"line":120},[40,3317,3318],{"class":50},"        method: ",[40,3320,338],{"class":57},[40,3322,149],{"class":50},[40,3324,3325,3328,3331,3333,3336],{"class":42,"line":125},[40,3326,3327],{"class":50},"        handler: ",[40,3329,3330],{"class":84},"resolve",[40,3332,324],{"class":50},[40,3334,3335],{"class":57},"'server\u002Fcustom-routes\u002Freport.get.ts'",[40,3337,3338],{"class":50},"),\n",[40,3340,3341],{"class":42,"line":140},[40,3342,3343],{"class":50},"      },\n",[40,3345,3346],{"class":42,"line":152},[40,3347,3348],{"class":50},"    ],\n",[40,3350,3351,3353],{"class":42,"line":162},[40,3352,298],{"class":50},[40,3354,149],{"class":137},[40,3356,3357],{"class":42,"line":172},[40,3358,117],{"class":137},[31,3360,3362],{"className":33,"code":3361,"language":35,"meta":36,"style":36},"\u002F\u002F server\u002Fcustom-routes\u002Freport.get.ts — outside every scanned directory\nexport default defineEndpoint({\n  operation: 'getCustomReport',\n  query: z.object({ id: z.string() }),\n  responses: {\n    200: z.object({ id: z.string(), source: z.literal('custom-route') }),\n  },\n  handler: ({ query, respond }) => {\n    return respond(200, { id: query.id, source: 'custom-route' })\n  },\n})\n",[22,3363,3364,3369,3379,3388,3402,3406,3432,3438,3456,3473,3479],{"__ignoreMap":36},[40,3365,3366],{"class":42,"line":43},[40,3367,3368],{"class":527},"\u002F\u002F server\u002Fcustom-routes\u002Freport.get.ts — outside every scanned directory\n",[40,3370,3371,3373,3375,3377],{"class":42,"line":61},[40,3372,128],{"class":46},[40,3374,131],{"class":46},[40,3376,134],{"class":84},[40,3378,88],{"class":137},[40,3380,3381,3383,3386],{"class":42,"line":68},[40,3382,392],{"class":50},[40,3384,3385],{"class":57},"'getCustomReport'",[40,3387,149],{"class":137},[40,3389,3390,3392,3394,3396,3398,3400],{"class":42,"line":91},[40,3391,183],{"class":50},[40,3393,85],{"class":84},[40,3395,2560],{"class":50},[40,3397,109],{"class":84},[40,3399,1949],{"class":50},[40,3401,149],{"class":137},[40,3403,3404],{"class":42,"line":103},[40,3405,2182],{"class":50},[40,3407,3408,3410,3412,3414,3416,3418,3421,3424,3426,3429],{"class":42,"line":114},[40,3409,2187],{"class":74},[40,3411,923],{"class":50},[40,3413,85],{"class":84},[40,3415,2560],{"class":50},[40,3417,109],{"class":84},[40,3419,3420],{"class":50},"(), source: z.",[40,3422,3423],{"class":84},"literal",[40,3425,324],{"class":50},[40,3427,3428],{"class":57},"'custom-route'",[40,3430,3431],{"class":50},") }),\n",[40,3433,3434,3436],{"class":42,"line":120},[40,3435,298],{"class":50},[40,3437,149],{"class":137},[40,3439,3440,3442,3444,3446,3448,3450,3452,3454],{"class":42,"line":125},[40,3441,231],{"class":84},[40,3443,234],{"class":50},[40,3445,243],{"class":137},[40,3447,240],{"class":50},[40,3449,709],{"class":137},[40,3451,246],{"class":50},[40,3453,249],{"class":46},[40,3455,252],{"class":50},[40,3457,3458,3460,3462,3464,3466,3469,3471],{"class":42,"line":140},[40,3459,258],{"class":46},[40,3461,716],{"class":84},[40,3463,324],{"class":50},[40,3465,220],{"class":74},[40,3467,3468],{"class":50},", { id: query.id, source: ",[40,3470,3428],{"class":57},[40,3472,2255],{"class":50},[40,3474,3475,3477],{"class":42,"line":152},[40,3476,298],{"class":50},[40,3478,149],{"class":137},[40,3480,3481],{"class":42,"line":162},[40,3482,117],{"class":137},[31,3484,3486],{"className":33,"code":3485,"language":35,"meta":36,"style":36},"const report = await $endpoint('getCustomReport', { query: { id: 'r_1' } })\n",[22,3487,3488],{"__ignoreMap":36},[40,3489,3490,3492,3495,3497,3499,3501,3503,3505,3508,3511],{"class":42,"line":43},[40,3491,71],{"class":46},[40,3493,3494],{"class":74}," report",[40,3496,78],{"class":46},[40,3498,1526],{"class":46},[40,3500,321],{"class":84},[40,3502,324],{"class":50},[40,3504,3385],{"class":57},[40,3506,3507],{"class":50},", { query: { id: ",[40,3509,3510],{"class":57},"'r_1'",[40,3512,460],{"class":50},[10,3514,3515,3516,3518],{},"One requirement: the handler entry's ",[22,3517,28],{}," must be a path to a real source file with a JS or TS extension. That is what discovery evaluates to read the contract, so a handler given as an inline function, or as a virtual module specifier, is skipped rather than guessed at — it still serves requests, it is just not an endpoint.",[10,3520,3521,3522,3525,3526,3530],{},"The route template is yours to choose and does not have to sit under ",[22,3523,3524],{},"\u002Fapi",". It is still subject to the ",[1167,3527,3529],{"href":3528},"\u002Fdocs\u002Flimits","route template limits",": no catch-all and no optional parameter, because the generated client could not build those URLs.",[14,3532,3534],{"id":3533},"separate-contract-files","Separate contract files",[10,3536,3537,3538,3540,3541,3543,3544,3547,3548,3550,3551,3553],{},"Reach for two calls — ",[22,3539,24],{}," without a ",[22,3542,28],{},", paired with ",[22,3545,3546],{},"defineEndpointHandler()"," — when the handler needs to live somewhere other than inline in the contract: in its own file, as this section covers, or shared by several routes that each attach it to their own contract. Omitting ",[22,3549,28],{}," returns a contract, and ",[22,3552,3546],{}," attaches a handler to it.",[10,3555,3556,3557,3560],{},"Endpoint metadata is collected during Nuxt type generation by evaluating the module that defines the contract. With a co-located contract, that module is the route file itself — so its top-level code runs at build time too. Routes whose top-level code is heavy (opens connections, reads required environment) can move the contract to a sibling ",[22,3558,3559],{},".endpoint-contract"," file instead, keeping it right next to the handler:",[31,3562,3564],{"className":33,"code":3563,"language":35,"meta":36,"style":36},"\u002F\u002F server\u002Fapi\u002Fusers\u002F[id].get.endpoint-contract.ts — evaluated during type generation; keep it side-effect free\nimport { defineEndpoint } from 'nuxt-endpoints\u002Fruntime'\nimport { z } from 'zod'\n\nexport const getUserEndpoint = defineEndpoint({\n  operation: 'getUser',\n  params: z.object({ id: z.coerce.number() }),\n  responses: { 200: z.object({ id: z.number(), name: z.string() }) },\n})\n",[22,3565,3566,3571,3583,3593,3597,3612,3620,3632,3652],{"__ignoreMap":36},[40,3567,3568],{"class":42,"line":43},[40,3569,3570],{"class":527},"\u002F\u002F server\u002Fapi\u002Fusers\u002F[id].get.endpoint-contract.ts — evaluated during type generation; keep it side-effect free\n",[40,3572,3573,3575,3578,3580],{"class":42,"line":61},[40,3574,47],{"class":46},[40,3576,3577],{"class":50}," { defineEndpoint } ",[40,3579,54],{"class":46},[40,3581,3582],{"class":57}," 'nuxt-endpoints\u002Fruntime'\n",[40,3584,3585,3587,3589,3591],{"class":42,"line":68},[40,3586,47],{"class":46},[40,3588,51],{"class":50},[40,3590,54],{"class":46},[40,3592,58],{"class":57},[40,3594,3595],{"class":42,"line":91},[40,3596,65],{"emptyLinePlaceholder":64},[40,3598,3599,3601,3603,3606,3608,3610],{"class":42,"line":103},[40,3600,128],{"class":46},[40,3602,535],{"class":46},[40,3604,3605],{"class":74}," getUserEndpoint",[40,3607,78],{"class":46},[40,3609,134],{"class":84},[40,3611,88],{"class":50},[40,3613,3614,3616,3618],{"class":42,"line":114},[40,3615,392],{"class":50},[40,3617,395],{"class":57},[40,3619,149],{"class":50},[40,3621,3622,3624,3626,3628,3630],{"class":42,"line":120},[40,3623,155],{"class":50},[40,3625,85],{"class":84},[40,3627,574],{"class":50},[40,3629,97],{"class":84},[40,3631,579],{"class":50},[40,3633,3634,3636,3638,3640,3642,3644,3646,3648,3650],{"class":42,"line":125},[40,3635,217],{"class":50},[40,3637,220],{"class":74},[40,3639,923],{"class":50},[40,3641,85],{"class":84},[40,3643,2560],{"class":50},[40,3645,97],{"class":84},[40,3647,2630],{"class":50},[40,3649,109],{"class":84},[40,3651,1615],{"class":50},[40,3653,3654],{"class":42,"line":140},[40,3655,117],{"class":50},[31,3657,3659],{"className":33,"code":3658,"language":35,"meta":36,"style":36},"\u002F\u002F server\u002Fapi\u002Fusers\u002F[id].get.ts — never evaluated at build time\nimport { getUserEndpoint } from '.\u002F[id].get.endpoint-contract'\n\nconst db = await connectToDatabase() \u002F\u002F top-level code is now safe\n\nexport default defineEndpointHandler(getUserEndpoint, ({ params }) => {\n  return db.users.find(params.id)\n})\n",[22,3660,3661,3666,3678,3682,3701,3705,3726,3740],{"__ignoreMap":36},[40,3662,3663],{"class":42,"line":43},[40,3664,3665],{"class":527},"\u002F\u002F server\u002Fapi\u002Fusers\u002F[id].get.ts — never evaluated at build time\n",[40,3667,3668,3670,3673,3675],{"class":42,"line":61},[40,3669,47],{"class":46},[40,3671,3672],{"class":50}," { getUserEndpoint } ",[40,3674,54],{"class":46},[40,3676,3677],{"class":57}," '.\u002F[id].get.endpoint-contract'\n",[40,3679,3680],{"class":42,"line":68},[40,3681,65],{"emptyLinePlaceholder":64},[40,3683,3684,3686,3689,3691,3693,3696,3698],{"class":42,"line":91},[40,3685,71],{"class":46},[40,3687,3688],{"class":74}," db",[40,3690,78],{"class":46},[40,3692,1526],{"class":46},[40,3694,3695],{"class":84}," connectToDatabase",[40,3697,1554],{"class":50},[40,3699,3700],{"class":527},"\u002F\u002F top-level code is now safe\n",[40,3702,3703],{"class":42,"line":103},[40,3704,65],{"emptyLinePlaceholder":64},[40,3706,3707,3709,3711,3714,3716,3719,3722,3724],{"class":42,"line":114},[40,3708,128],{"class":46},[40,3710,131],{"class":46},[40,3712,3713],{"class":84}," defineEndpointHandler",[40,3715,324],{"class":137},[40,3717,3718],{"class":50},"getUserEndpoint",[40,3720,3721],{"class":137},", ({ params }) ",[40,3723,249],{"class":46},[40,3725,252],{"class":50},[40,3727,3728,3731,3734,3737],{"class":42,"line":120},[40,3729,3730],{"class":46},"  return",[40,3732,3733],{"class":50}," db.users.",[40,3735,3736],{"class":84},"find",[40,3738,3739],{"class":50},"(params.id)\n",[40,3741,3742,3744],{"class":42,"line":125},[40,3743,1916],{"class":50},[40,3745,1272],{"class":137},[10,3747,3748,3749,3752,3753,3756,3757,3760,3761,3764],{},"The module registers ",[22,3750,3751],{},"**\u002F*.endpoint-contract.*"," in Nitro's ",[22,3754,3755],{},"ignore"," option, so these files never become Nitro routes even though they live inside ",[22,3758,3759],{},"server\u002Fapi",". (The same pattern also excludes matching filenames from Nitro's public-asset copying — avoid naming files under ",[22,3762,3763],{},"public\u002F"," this way.)",[10,3766,3767,3768,3771],{},"When the value passed to ",[22,3769,3770],{},"defineEndpointHandler"," is a statically imported identifier, discovery evaluates only the contract module and never imports the route file. Rules:",[483,3773,3774,3784,3794,3797],{},[486,3775,3776,3777,3779,3780,3783],{},"Import ",[22,3778,553],{}," explicitly from ",[22,3781,3782],{},"nuxt-endpoints\u002Fruntime"," in separate contract modules. Discovery can evaluate an auto-imported helper, but the ignored sibling file does not receive that helper's generated TypeScript declaration during standalone type-checking.",[486,3785,3786,3787,3789,3790,3793],{},"The import must be a plain static ",[22,3788,47],{}," of the identifier (named, aliased, or default). Namespace access (",[22,3791,3792],{},"contracts.getUser","), locally computed values, and auto-imports fall back to evaluating the route module.",[486,3795,3796],{},"The contract module's own import graph is evaluated with it, so keep it to schema definitions. Watch out for barrel files that re-export server runtime code.",[486,3798,3799,3800,832,3802,3805,3806,3808,3809,3812,3813,835],{},"Contracts can also live at any importable path outside ",[22,3801,3759],{},[22,3803,3804],{},"server\u002Froutes"," if you prefer collecting them elsewhere — the ",[22,3807,3559],{}," suffix is only required inside route directories, where every ordinary file becomes a route. Note the ownership split: contracts are your application's code wherever they live, while ",[22,3810,3811],{},"server\u002Fendpoints\u002F"," is where this module looks for its own convention files, such as the ",[1167,3814,1815],{"href":1814},[10,3816,3817],{},"Routes that define no endpoint at all are never evaluated during discovery, so this only matters for endpoint routes with heavy top-level code.",[3819,3820,3821],"style",{},"html pre.shiki code .swxxe, html code.shiki .swxxe{--shiki-light:#CF222E;--shiki-dark:#FF7B72}html pre.shiki code .saQ_J, html code.shiki .saQ_J{--shiki-light:#1F2328;--shiki-dark:#E6EDF3}html pre.shiki code .sZItA, html code.shiki .sZItA{--shiki-light:#0A3069;--shiki-dark:#A5D6FF}html pre.shiki code .sOOdx, html code.shiki .sOOdx{--shiki-light:#0550AE;--shiki-dark:#79C0FF}html pre.shiki code .s9HWX, html code.shiki .s9HWX{--shiki-light:#8250DF;--shiki-dark:#D2A8FF}html pre.shiki code .sVS1I, html code.shiki .sVS1I{--shiki-light:#953800;--shiki-dark:#FFA657}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 .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 .sA0OV, html code.shiki .sA0OV{--shiki-light:#6E7781;--shiki-dark:#8B949E}",{"title":36,"searchDepth":61,"depth":61,"links":3823},[3824,3825,3826,3827,3828,3832,3833,3834,3839,3840,3841],{"id":16,"depth":61,"text":17},{"id":480,"depth":61,"text":481},{"id":510,"depth":61,"text":511},{"id":867,"depth":61,"text":868},{"id":1380,"depth":61,"text":1381,"children":3829},[3830,3831],{"id":1683,"depth":68,"text":1684},{"id":1769,"depth":68,"text":1770},{"id":1829,"depth":61,"text":1830},{"id":2098,"depth":61,"text":2099},{"id":2288,"depth":61,"text":2289,"children":3835},[3836,3837,3838],{"id":2645,"depth":68,"text":2646},{"id":2947,"depth":68,"text":2948},{"id":3040,"depth":68,"text":3041},{"id":3182,"depth":61,"text":3183},{"id":3255,"depth":61,"text":3256},{"id":3533,"depth":61,"text":3534},"Write request and response schemas next to the handler.","md",{},"\u002Fdocs\u002Fendpoints",{"title":5,"description":3842},"docs\u002Fendpoints","l_mcHBPYSUKb_X9C6TNE90ZqXxmOuxxhf18pM75vG5Q",{"left":3850,"top":3850,"width":3851,"height":3851,"rotate":3850,"vFlip":3852,"hFlip":3852,"body":3853},0,24,false,"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401\"\u002F>",{"left":3850,"top":3850,"width":3851,"height":3851,"rotate":3850,"vFlip":3852,"hFlip":3852,"body":3855,"hidden":64},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5c.08-1.25-.27-2.48-1-3.5c.28-1.15.28-2.35 0-3.5c0 0-1 0-3 1.5c-2.64-.5-5.36-.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.4 5.4 0 0 0 4 9c0 3.5 3 5.5 6 5.5c-.39.49-.68 1.05-.85 1.65S8.93 17.38 9 18v4\"\u002F>\u003Cpath d=\"M9 18c-4.51 2-5-2-7-2\"\u002F>\u003C\u002Fg>",{"left":3850,"top":3850,"width":3851,"height":3851,"rotate":3850,"vFlip":3852,"hFlip":3852,"body":3857},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 5h16M4 12h16M4 19h16\"\u002F>",1787723882237]