[{"data":1,"prerenderedAt":772},["ShallowReactive",2],{"docs:\u002Fdocs\u002Fgetting-started":3,"i-lucide:moon":763,"i-lucide:github":768,"i-lucide:menu":770},{"id":4,"title":5,"body":6,"description":756,"extension":757,"meta":758,"navigation":166,"path":759,"seo":760,"stem":761,"__hash__":762},"docs\u002Fdocs\u002Fgetting-started.md","Getting Started",{"type":7,"value":8,"toc":749},"minimark",[9,13,18,21,24,28,31,63,66,82,85,99,102,116,120,131,300,303,409,420,427,430,457,461,475,590,618,625,640,696,707,711,738,745],[10,11,12],"p",{},"In a few minutes you will have a Nuxt route that validates its input at runtime, a client call with fully inferred types, and an OpenAPI document — all from one endpoint definition.",[14,15,17],"h2",{"id":16},"compatibility","Compatibility",[10,19,20],{},"Nuxt Endpoints currently targets Nuxt 4.5+ with Nitro 2 and H3 1. Nuxt 5, Nitro 3, and H3 2 support is not claimed until those combinations are covered by the package test matrix. This is a support statement, not a claim that newer combinations are known to fail.",[10,22,23],{},"This section is the single source for the supported platform line; other pages link here instead of restating it.",[14,25,27],{"id":26},"install","Install",[10,29,30],{},"Add Nuxt Endpoints through the Nuxt CLI:",[32,33,38],"pre",{"className":34,"code":35,"language":36,"meta":37,"style":37},"language-bash shiki shiki-themes github-light-default github-dark-default","npx nuxt module add nuxt-endpoints\n","bash","",[39,40,41],"code",{"__ignoreMap":37},[42,43,46,50,54,57,60],"span",{"class":44,"line":45},"line",1,[42,47,49],{"class":48},"sVS1I","npx",[42,51,53],{"class":52},"sZItA"," nuxt",[42,55,56],{"class":52}," module",[42,58,59],{"class":52}," add",[42,61,62],{"class":52}," nuxt-endpoints\n",[10,64,65],{},"Then install the schema library you want to use in endpoint definitions — Zod, Valibot, and Effect are optional peer dependencies:",[32,67,69],{"className":34,"code":68,"language":36,"meta":37,"style":37},"npm install zod\n",[39,70,71],{"__ignoreMap":37},[42,72,73,76,79],{"class":44,"line":45},[42,74,75],{"class":48},"npm",[42,77,78],{"class":52}," install",[42,80,81],{"class":52}," zod\n",[10,83,84],{},"Install with Valibot:",[32,86,88],{"className":34,"code":87,"language":36,"meta":37,"style":37},"npm install valibot\n",[39,89,90],{"__ignoreMap":37},[42,91,92,94,96],{"class":44,"line":45},[42,93,75],{"class":48},[42,95,78],{"class":52},[42,97,98],{"class":52}," valibot\n",[10,100,101],{},"Install with Effect Schema:",[32,103,105],{"className":34,"code":104,"language":36,"meta":37,"style":37},"npm install effect\n",[39,106,107],{"__ignoreMap":37},[42,108,109,111,113],{"class":44,"line":45},[42,110,75],{"class":48},[42,112,78],{"class":52},[42,114,115],{"class":52}," effect\n",[14,117,119],{"id":118},"your-first-endpoint","Your first endpoint",[10,121,122,123,126,127,130],{},"Create an ordinary Nuxt server route and default-export a ",[39,124,125],{},"defineEndpoint()"," call with a ",[39,128,129],{},"handler"," property:",[32,132,136],{"className":133,"code":134,"language":135,"meta":37,"style":37},"language-ts shiki shiki-themes github-light-default github-dark-default","\u002F\u002F server\u002Fapi\u002Fusers\u002F[id].get.ts\nimport { z } from 'zod'\n\nexport default defineEndpoint({\n  summary: 'Get a user',\n  params: z.object({ id: z.coerce.number() }),\n  responses: { 200: z.object({ id: z.number(), name: z.string() }) },\n  handler: ({ params }) => {\n    return { id: params.id, name: 'Tom' } \u002F\u002F params.id is a number — validated and coerced\n  },\n})\n","ts",[39,137,138,144,161,168,184,196,216,247,268,286,294],{"__ignoreMap":37},[42,139,140],{"class":44,"line":45},[42,141,143],{"class":142},"sA0OV","\u002F\u002F server\u002Fapi\u002Fusers\u002F[id].get.ts\n",[42,145,147,151,155,158],{"class":44,"line":146},2,[42,148,150],{"class":149},"swxxe","import",[42,152,154],{"class":153},"saQ_J"," { z } ",[42,156,157],{"class":149},"from",[42,159,160],{"class":52}," 'zod'\n",[42,162,164],{"class":44,"line":163},3,[42,165,167],{"emptyLinePlaceholder":166},true,"\n",[42,169,171,174,177,181],{"class":44,"line":170},4,[42,172,173],{"class":149},"export",[42,175,176],{"class":149}," default",[42,178,180],{"class":179},"s9HWX"," defineEndpoint",[42,182,183],{"class":48},"({\n",[42,185,187,190,193],{"class":44,"line":186},5,[42,188,189],{"class":153},"  summary: ",[42,191,192],{"class":52},"'Get a user'",[42,194,195],{"class":48},",\n",[42,197,199,202,205,208,211,214],{"class":44,"line":198},6,[42,200,201],{"class":153},"  params: z.",[42,203,204],{"class":179},"object",[42,206,207],{"class":153},"({ id: z.coerce.",[42,209,210],{"class":179},"number",[42,212,213],{"class":153},"() })",[42,215,195],{"class":48},[42,217,219,222,226,229,231,234,236,239,242,245],{"class":44,"line":218},7,[42,220,221],{"class":153},"  responses: { ",[42,223,225],{"class":224},"sOOdx","200",[42,227,228],{"class":153},": z.",[42,230,204],{"class":179},[42,232,233],{"class":153},"({ id: z.",[42,235,210],{"class":179},[42,237,238],{"class":153},"(), name: z.",[42,240,241],{"class":179},"string",[42,243,244],{"class":153},"() }) }",[42,246,195],{"class":48},[42,248,250,253,256,259,262,265],{"class":44,"line":249},8,[42,251,252],{"class":179},"  handler",[42,254,255],{"class":153},": ({ ",[42,257,258],{"class":48},"params",[42,260,261],{"class":153}," }) ",[42,263,264],{"class":149},"=>",[42,266,267],{"class":153}," {\n",[42,269,271,274,277,280,283],{"class":44,"line":270},9,[42,272,273],{"class":149},"    return",[42,275,276],{"class":153}," { id: params.id, name: ",[42,278,279],{"class":52},"'Tom'",[42,281,282],{"class":153}," } ",[42,284,285],{"class":142},"\u002F\u002F params.id is a number — validated and coerced\n",[42,287,289,292],{"class":44,"line":288},10,[42,290,291],{"class":153},"  }",[42,293,195],{"class":48},[42,295,297],{"class":44,"line":296},11,[42,298,299],{"class":48},"})\n",[10,301,302],{},"Call it from any component. Request options and the response type are inferred — there is no codegen step to run and no types to import:",[32,304,308],{"className":305,"code":306,"language":307,"meta":37,"style":37},"language-vue shiki shiki-themes github-light-default github-dark-default","\u003Cscript setup lang=\"ts\">\nconst user = await $endpoint('\u002Fapi\u002Fusers\u002F:id', {\n  method: 'get',\n  params: { id: '1' },\n})\n\nuser.name.toUpperCase()\n\u003C\u002Fscript>\n","vue",[39,309,310,334,360,370,381,385,389,400],{"__ignoreMap":37},[42,311,312,315,319,322,325,328,331],{"class":44,"line":45},[42,313,314],{"class":153},"\u003C",[42,316,318],{"class":317},"snZHK","script",[42,320,321],{"class":224}," setup",[42,323,324],{"class":224}," lang",[42,326,327],{"class":153},"=",[42,329,330],{"class":52},"\"ts\"",[42,332,333],{"class":153},">\n",[42,335,336,339,342,345,348,351,354,357],{"class":44,"line":146},[42,337,338],{"class":149},"const",[42,340,341],{"class":224}," user",[42,343,344],{"class":149}," =",[42,346,347],{"class":149}," await",[42,349,350],{"class":179}," $endpoint",[42,352,353],{"class":153},"(",[42,355,356],{"class":52},"'\u002Fapi\u002Fusers\u002F:id'",[42,358,359],{"class":153},", {\n",[42,361,362,365,368],{"class":44,"line":163},[42,363,364],{"class":153},"  method: ",[42,366,367],{"class":52},"'get'",[42,369,195],{"class":153},[42,371,372,375,378],{"class":44,"line":170},[42,373,374],{"class":153},"  params: { id: ",[42,376,377],{"class":52},"'1'",[42,379,380],{"class":153}," },\n",[42,382,383],{"class":44,"line":186},[42,384,299],{"class":153},[42,386,387],{"class":44,"line":198},[42,388,167],{"emptyLinePlaceholder":166},[42,390,391,394,397],{"class":44,"line":218},[42,392,393],{"class":153},"user.name.",[42,395,396],{"class":179},"toUpperCase",[42,398,399],{"class":153},"()\n",[42,401,402,405,407],{"class":44,"line":249},[42,403,404],{"class":153},"\u003C\u002F",[42,406,318],{"class":317},[42,408,333],{"class":153},[10,410,411,412,415,416,419],{},"Requests that do not match the contract are rejected before your handler runs — try ",[39,413,414],{},"\u002Fapi\u002Fusers\u002Fabc"," and the ",[39,417,418],{},"z.coerce.number()"," param fails validation.",[10,421,422,423,426],{},"While the dev server is running, the generated OpenAPI 3.1 document for this route is served at ",[39,424,425],{},"\u002F_endpoints\u002Fschema",".",[10,428,429],{},"From here:",[431,432,433,442],"ul",{},[434,435,436,441],"li",{},[437,438,440],"a",{"href":439},"\u002Fdocs\u002Fendpoints","Define Endpoints"," covers the full contract surface: validated request parts, multiple response statuses, and response validation.",[434,443,444,448,449,452,453,456],{},[437,445,447],{"href":446},"\u002Fdocs\u002Fclient","Generated Client"," covers everything ",[39,450,451],{},"$endpoint"," and ",[39,454,455],{},"useEndpoint"," can do.",[14,458,460],{"id":459},"configure-nuxt","Configure Nuxt",[10,462,463,464,467,468,471,472,426],{},"The Nuxt CLI adds ",[39,465,466],{},"nuxt-endpoints"," to ",[39,469,470],{},"modules",". The generated OpenAPI route and optional client helpers can be configured through ",[39,473,474],{},"endpoints",[32,476,478],{"className":133,"code":477,"language":135,"meta":37,"style":37},"export default defineNuxtConfig({\n  modules: ['nuxt-endpoints'],\n  endpoints: {\n    openApi: {\n      path: '\u002F_endpoints\u002Fschema',\n      title: 'Example API',\n      version: '1.0.0',\n    },\n    client: {\n      result: true,\n      raw: true,\n    },\n  },\n})\n",[39,479,480,491,504,509,514,524,534,544,549,554,564,573,578,585],{"__ignoreMap":37},[42,481,482,484,486,489],{"class":44,"line":45},[42,483,173],{"class":149},[42,485,176],{"class":149},[42,487,488],{"class":179}," defineNuxtConfig",[42,490,183],{"class":48},[42,492,493,496,499,502],{"class":44,"line":146},[42,494,495],{"class":153},"  modules: [",[42,497,498],{"class":52},"'nuxt-endpoints'",[42,500,501],{"class":153},"]",[42,503,195],{"class":48},[42,505,506],{"class":44,"line":163},[42,507,508],{"class":153},"  endpoints: {\n",[42,510,511],{"class":44,"line":170},[42,512,513],{"class":153},"    openApi: {\n",[42,515,516,519,522],{"class":44,"line":186},[42,517,518],{"class":153},"      path: ",[42,520,521],{"class":52},"'\u002F_endpoints\u002Fschema'",[42,523,195],{"class":153},[42,525,526,529,532],{"class":44,"line":198},[42,527,528],{"class":153},"      title: ",[42,530,531],{"class":52},"'Example API'",[42,533,195],{"class":153},[42,535,536,539,542],{"class":44,"line":218},[42,537,538],{"class":153},"      version: ",[42,540,541],{"class":52},"'1.0.0'",[42,543,195],{"class":153},[42,545,546],{"class":44,"line":249},[42,547,548],{"class":153},"    },\n",[42,550,551],{"class":44,"line":270},[42,552,553],{"class":153},"    client: {\n",[42,555,556,559,562],{"class":44,"line":288},[42,557,558],{"class":153},"      result: ",[42,560,561],{"class":224},"true",[42,563,195],{"class":153},[42,565,566,569,571],{"class":44,"line":296},[42,567,568],{"class":153},"      raw: ",[42,570,561],{"class":224},[42,572,195],{"class":153},[42,574,576],{"class":44,"line":575},12,[42,577,548],{"class":153},[42,579,581,583],{"class":44,"line":580},13,[42,582,291],{"class":153},[42,584,195],{"class":48},[42,586,588],{"class":44,"line":587},14,[42,589,299],{"class":48},[10,591,592,595,596,599,600,603,604,607,608,452,611,614,615,617],{},[39,593,594],{},"openApi"," can also be set to ",[39,597,598],{},"false"," to disable the generated schema route. By default, the schema route is only served in development; set ",[39,601,602],{},"openApi: true"," or ",[39,605,606],{},"openApi.enabled: true"," to also serve it in production. ",[39,609,610],{},"client.result",[39,612,613],{},"client.raw"," control which optional methods are generated on ",[39,616,451],{}," calls.",[10,619,620,621,624],{},"To generate typed query, mutation, and infinite-query options for Vue Query, install\nthe optional peer and enable ",[39,622,623],{},"client.query",":",[32,626,628],{"className":34,"code":627,"language":36,"meta":37,"style":37},"vp add @tanstack\u002Fvue-query\n",[39,629,630],{"__ignoreMap":37},[42,631,632,635,637],{"class":44,"line":45},[42,633,634],{"class":48},"vp",[42,636,59],{"class":52},[42,638,639],{"class":52}," @tanstack\u002Fvue-query\n",[32,641,643],{"className":133,"code":642,"language":135,"meta":37,"style":37},"export default defineNuxtConfig({\n  modules: ['nuxt-endpoints'],\n  endpoints: {\n    client: {\n      query: true,\n    },\n  },\n})\n",[39,644,645,655,665,669,673,682,686,692],{"__ignoreMap":37},[42,646,647,649,651,653],{"class":44,"line":45},[42,648,173],{"class":149},[42,650,176],{"class":149},[42,652,488],{"class":179},[42,654,183],{"class":48},[42,656,657,659,661,663],{"class":44,"line":146},[42,658,495],{"class":153},[42,660,498],{"class":52},[42,662,501],{"class":153},[42,664,195],{"class":48},[42,666,667],{"class":44,"line":163},[42,668,508],{"class":153},[42,670,671],{"class":44,"line":170},[42,672,553],{"class":153},[42,674,675,678,680],{"class":44,"line":186},[42,676,677],{"class":153},"      query: ",[42,679,561],{"class":224},[42,681,195],{"class":153},[42,683,684],{"class":44,"line":198},[42,685,548],{"class":153},[42,687,688,690],{"class":44,"line":218},[42,689,291],{"class":153},[42,691,195],{"class":48},[42,693,694],{"class":44,"line":249},[42,695,299],{"class":48},[10,697,698,701,702,706],{},[39,699,700],{},"query: true"," leaves QueryClient setup to the application. See\n",[437,703,705],{"href":704},"\u002Fdocs\u002Ftanstack-query","Vue Query"," for generated factories and the opt-in\nautomatic Nuxt SSR setup.",[14,708,710],{"id":709},"what-gets-generated","What gets generated",[431,712,713,718,724,733],{},[434,714,715,717],{},[39,716,451],{},": a generated path\u002Fmethod client available in Nuxt app code.",[434,719,720,723],{},[39,721,722],{},"#endpoints",": helper types for paths, optional operation targets, calls, status-aware typed results, and raw Web Responses.",[434,725,726,729,730,732],{},[39,727,728],{},"#endpoints\u002Fquery",": Query, Mutation, Infinite Query, and key factories when ",[39,731,623],{}," is enabled.",[434,734,735,737],{},[39,736,425],{},": the default OpenAPI 3.1 document route when OpenAPI generation is enabled.",[10,739,740,741,426],{},"Adding the module changes nothing by itself: only routes that export an endpoint definition are affected. Existing routes keep working unchanged — see ",[437,742,744],{"href":743},"\u002Fdocs\u002Fincremental-adoption","Incremental Adoption",[746,747,748],"style",{},"html pre.shiki code .sA0OV, html code.shiki .sA0OV{--shiki-light:#6E7781;--shiki-dark:#8B949E}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 .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 pre.shiki code .sOOdx, html code.shiki .sOOdx{--shiki-light:#0550AE;--shiki-dark:#79C0FF}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 .snZHK, html code.shiki .snZHK{--shiki-light:#116329;--shiki-dark:#7EE787}",{"title":37,"searchDepth":146,"depth":146,"links":750},[751,752,753,754,755],{"id":16,"depth":146,"text":17},{"id":26,"depth":146,"text":27},{"id":118,"depth":146,"text":119},{"id":459,"depth":146,"text":460},{"id":709,"depth":146,"text":710},"Install the module, define your first endpoint, and call it with types.","md",{},"\u002Fdocs\u002Fgetting-started",{"title":5,"description":756},"docs\u002Fgetting-started","6ekXcR3PXOXaZGHBeXkj7OVhFxjxY5FnkW9vzgsr4IM",{"left":764,"top":764,"width":765,"height":765,"rotate":764,"vFlip":766,"hFlip":766,"body":767},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":764,"top":764,"width":765,"height":765,"rotate":764,"vFlip":766,"hFlip":766,"body":769,"hidden":166},"\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":764,"top":764,"width":765,"height":765,"rotate":764,"vFlip":766,"hFlip":766,"body":771},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 5h16M4 12h16M4 19h16\"\u002F>",1787723882224]