ServiceStack APIs start from a different place than most frameworks. Instead of writing a method that returns JSON, you describe what the message is - and the routes, the docs, the validation, the API Explorer and the native clients are all generated from that one description.
This walkthrough creates a working API from scratch, then shows exactly what each file does and what you got for free.
That's it - you now have a running .NET 10 API. The template's home page is already calling it with typed DTOs!
How it works​
The important detail is what isn't in your Service: no HttpContext, no serialization, no routing code, no manual model binding. Your Service accepts a message and returns a message, which is what lets ServiceStack expose it over HTTP, MQs, gRPC or in-process without you changing a line.
The code​
What that one DTO gave you​
TIP
Change the return format on any API by adding ?format=json, ?format=csv or ?format=jsonl - or by sending the matching Accept header. See Formats for the full list.
The solution structure​
Every ServiceStack template scaffolds the same four projects. The layout isn't ceremony - it's what makes your API contract shareable and your logic testable:
Read more in Physical Project Structure.
Call your API from anywhere​
Your App publishes enough metadata to generate a native, typed client for any supported language - so there's no SDK project to write, version or document. Pick a language to see the two commands:
Re-run the generate command whenever your API changes. New fields show up in the generated DTOs, and removed or renamed members become compile errors in the consuming App instead of runtime surprises.
From a web page, with no build step​
The web template's home page uses your App's built-in JavaScript DTOs from /types/mjs with the @servicestack/client library, loaded from an importmap:
<script type="importmap">
{
"imports": {
"@servicestack/client":"https://unpkg.com/@servicestack/client/dist/servicestack-client.mjs"
}
}
</script>
Which lets you reference the package name in your source instead of its physical location:
<input type="text" id="txtName">
<div id="result"></div>
<script type="module">
import { JsonServiceClient, $1, on } from '@servicestack/client'
import { Hello } from '/types/mjs'
const client = new JsonServiceClient()
on('#txtName', {
async keyup(el) {
const api = await client.api(new Hello({ name:el.target.value }))
$1('#result').innerHTML = api.response.result
}
})
</script>
Enable static analysis and intelli-sense​
For IDE intelli-sense during development, save the annotated Typed DTOs to disk:
npm run dtos
Then reference the local file to enable static analysis when calling your typed APIs:
import { Hello } from '/js/dtos.mjs'
client.api(new Hello({ name }))
To also get type-checking for @servicestack/client, install the dependency-free library as a dev dependency:
npm install -D @servicestack/client
Only its TypeScript definitions are used by the IDE, so you get a rich typed authoring experience with no bundler and no additional build time:

From a component framework​
The same JsonServiceClient works in every JavaScript App, from SPAs to React Native to Node.js servers, e.g. with TypeScript & Vue Single-File Components:
<template>
<div v-if="api.error" class="ml-2 text-red-500">{{ error.message }}</div>
<div v-else class="ml-3 mt-2 text-2xl">{{ api.loading ? 'Loading...' : api.response.result }}</div>
</template>
<script setup lang="ts">
import { JsonServiceClient } from "@servicestack/client"
import { Hello } from "@/dtos"
const props = defineProps<{ name: string }>()
const client = new JsonServiceClient()
const api = client.api(new Hello({ name: props.name }))
</script>
Compare the same API call across the major front-end frameworks:
Native Mobile and Desktop Apps use the same approach - see Add ServiceStack Reference for Swift, Java, Kotlin, Dart and .NET clients.
Where to go next​
Start from a full-featured template​
The web template is deliberately empty. When you want a template that comes with an opinionated front-end, auth, a database and deployment already wired up, start from one of the full project templates instead:
C# Project Templates Overview​
For Blazor WASM and Server see our Blazor projects & Tailwind components, and the rich Vue 3 Tailwind Components library that all Vue templates are pre-configured with.
Other ways to create a project​
If you don't have the x dotnet tool installed, the quickest way to create a ServiceStack App is to download your preferred template from:
Empty Projects​
There are a few different ways you can create empty ServiceStack projects ordered by their level of emptiness.
To write a minimal .NET 10 Web App to your current directory, mix in the init gist files to your current directory:
npx add-in init
To create an empty Single Project Template solution use the empty template:
npx create-net empty ProjectName
To create an empty 4 Project solution that adopts ServiceStack's recommended project structure, use the web template:
npx create-net web ProjectName
INFO
You can omit the ProjectName in all above examples to use the Directory Name as the Project Name
Empty F# Template​
Like C# init there's also init-fsharp gist to create an empty F# Web App:
npx add-in init-fsharp
Empty VB .NET Template​
And init-vb to create an empty VB .NET Web App:
npx add-in init-vb