--- title: API Explorer --- API Explorer is a Postman & Swagger UI alternative built into every ServiceStack **v6+** App that lets you explore, discover & call your APIs with an Auto UI dynamically generated from your APIs typed C# classes. It's built from the ground up with multiple levels of customizations, supporting both declarative & programmatic models for customizing each properties Input UI control, each APIs form grid layout whilst also providing the ability to provide rich interactive HTML Components to document each of your APIs & their Types. This video provides a quick overview of API Explorer's v1 featureset: ::: info DEMO A Live demo is available at **/ui** in all ServiceStack **v6+** Apps, e.g: [blazor-vue.web-templates.io/ui](https://blazor-vue.web-templates.io/ui) ::: The entire API Explorer UI is driven by the **rich metadata** around your APIs typed Service Contracts and AppHost's **registered plugins**. - The **Sidebar** - Displaying a list of APIs each user has access to - The **API** tab - Providing dynamic form to call & inspect your APIs - The **Details** tab - Containing a complete description of your APIs & its dependent types - The **Code** tab - Letting API consumers browse API Service contracts in their preferred language ([11 languages supported](https://servicestack.net/service-reference))

Lets learn about each feature with screenshots 📷

If your AppHost has the ServiceStack [AuthFeature](/auth/authentication-and-authorization) plugin registered, the home page will display a **Sign In** dialog based on the its **configured Auth Providers**. This is what you'll see in a new [Vue Vite](https://blazor-vue.web-templates.io/ui) project which has **Credentials** Auth, **JWT** as well as **Facebook**, **Google** and **Microsoft** OAuth providers registered in `Configure.Auth.cs`: ```csharp Plugins.Add(new AuthFeature(() => new CustomUserSession(), new IAuthProvider[] { new JwtAuthProvider(appSettings) { AuthKeyBase64 = appSettings.GetString("AuthKeyBase64"), }, new CredentialsAuthProvider(appSettings), new FacebookAuthProvider(appSettings), new GoogleAuthProvider(appSettings), new MicrosoftGraphAuthProvider(appSettings), }) { IncludeDefaultLogin = false }); ``` ## Integrated Sign In Where it will dynamically render the **Sign Up** form with the App's enabled Auth capabilities. Custom Auth Providers can provide their own Form Layout by overriding the `FormLayout`, e.g. the above Credentials UI is creatable with: ```csharp public class CustomCredentialsAuthProvider : CredentialsAuthProvider { public CustomCredentialsAuthProvider() { FormLayout = new() { Input.For(x => x.UserName, c => { c.Label = "Email address"; c.Required = true; }), Input.For(x => x.Password, c => { c.Type = "Password"; c.Required = true; }), Input.For(x => x.RememberMe), }; } //... } ``` Where the `Input` utility can be used to configure most HTML Form Input control properties that automatically configures to use the desired Input control for each property Type. You can Sign In with any of the users in the [Vue Vite Sign In](https://blazor-vue.web-templates.io/signin) page configured in `Configure.AuthRepository.cs`, i.e: | Username | Password | Role | | ------------------ | -------- | -------- | | admin@email.com | p@55wOrd | Admin | | manager@email.com | p@55wOrd | Manager | | employee@email.com | p@55wOrd | Employee | If signed in with the **Admin** User and the [Admin Users](/admin-ui-users) plugin is configured: ```csharp Plugins.Add(new AdminUsersFeature()); ``` It also displays **Admin UI** links that only **Admin** Users have access to. If you'd like to, you can add personalized links for users in different roles, e.g. this is what's used to populate the above UI for Admins: ```csharp appHost.AddToAppMetadata(meta => { meta.Plugins.Auth.RoleLinks[RoleNames.Admin] = new List { new() { Href = "../admin-ui", Label = "Dashboard", Icon = Svg.ImageSvg(Svg.Create(Svg.Body.Home)) }, new() { Href = "../admin-ui/users", Label = "Manage Users", Icon = Svg.ImageSvg(Svg.GetImage(Svg.Icons.Users, "currentColor")) }, }; }); ``` Once signed in, API Explorer expands to include all the protected APIs the signed in user has access to, identifiable with the padlock icon. ### Disable API Explorer ::: info API Explorer is powered by the rich API metadata provided by the `MetadataFeature` and can be customized through the `UiFeature` plugin. Removing either plugin disables API Explorer. ```csharp Plugins.RemoveAll(x => x is UiFeature); ``` ::: ## API Tab After selecting an API to use from the left-hand menu, you will be greeted with a way to **call APIs** through an **Auto UI** generated based on the **Request DTO** schema. Submitting the form returns API results with: - **Body** displaying a syntax highlighted JSON response - **Raw** showing raw JSON output in a textarea - **Preview** tab displaying results in a human-friendly view ::: info The `Raw` response forces a `CamelCase` response since the API Explorer interface needs consistent casing outside your applications default `TextCase`. Those using `SnakeCase` or `PascalCase` will see a different response outside of API Explorer. ::: Control types are based on the property types in your DTOs. | UI Input | Data Types | | ----------------------- | ---------- | | `` | Numeric Types | | `` | DateTime, DateTimeOffset, DateOnly | | `` | TimeSpan, TimeOnly | | `` | Boolean | | `` | default | Where the `CreateBooking` Request DTO defined in [Bookings.cs](https://github.com/NetCoreTemplates/blazor-vue/blob/main/MyApp.ServiceModel/Bookings.cs): ```csharp [Tag("bookings"), Description("Create a new Booking")] [Route("/bookings", "POST")] [ValidateHasRole("Employee")] [AutoApply(Behavior.AuditCreate)] public class CreateBooking : ICreateDb, IReturn { [Description("Name this Booking is for"), ValidateNotEmpty] public string Name { get; set; } public RoomType RoomType { get; set; } [ValidateGreaterThan(0)] public int RoomNumber { get; set; } [ValidateGreaterThan(0)] public decimal Cost { get; set; } public DateTime BookingStartDate { get; set; } public DateTime? BookingEndDate { get; set; } [Input(Type = "textarea")] public string? Notes { get; set; } } ``` Generates the following UI: This also shows how we can use the [[Input]](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.Interfaces/InputAttribute.cs) attribute to further customize the Input UI control for each property as a **declarative alternative** to using `Input.For()` above that the `Notes` property utilizes to change to use a **textarea** control instead. API Form also supports auto binding [Argument Exceptions](/error-handling) or [Fluent](/validation) & [Declarative](/declarative-validation) Validation rules where any validation errors will be contextually displayed next to the invalid property. Here's both the resulting invalid UI & the Error Response DTO that generated it: Contextual validation errors is used where possible, otherwise an **Error Summary** notification is displayed along with the API Response body containing the full API error information. ### JSON Form Another useful API form feature is being able to call APIs with a **JSON request payload** which maintains a **2-way sync** with the Form's UI allowing you to quickly cycle between input modes to quickly construct your API request. Real-time JSON validation is also displayed for added assistance, warning you whenever the JSON is malformed. ## Details Tab API Explorer also provides a place for users to find out more about your API through documentation generated by metadata about in your API and optionally custom HTML modules to give additional context. This is where API consumers would go to learn about each API where it displays all relevant information about the API at a glance. For `CreateBooking` it shows that: - **POST** is the APIs **preferred** HTTP Method - List its **user-defined** and **pre-defined** routes - It's a **protected** API limited to Authenticated Users with the **Employee** role - It's categorized in the **bookings** tag group - It's an [AutoQuery CRUD](/autoquery/crud) API implementing `ICreateDb` indicating it creates entries in the **Booking** RDBMS Table - It returns an `IdResponse` which we can intuitively infer returns the new Booking **Id** for successfully created Bookings This API Definition was generated from the `CreateBooking` DTO shows that the **Required** column used to document the APIs required properties is required for all properties except for the **nullable** Value and Reference Types when `#nullable` is enabled. ```csharp public class CreateBooking : ICreateDb, IReturn { [Description("Name this Booking is for"), ValidateNotEmpty] public string Name { get; set; } public RoomType RoomType { get; set; } [ValidateGreaterThan(0)] public int RoomNumber { get; set; } [ValidateGreaterThan(0)] public decimal Cost { get; set; } public DateTime BookingStartDate { get; set; } public DateTime? BookingEndDate { get; set; } [Input(Type = "textarea")] public string? Notes { get; set; } } ``` ::: info Importantly **Required** annotations are only documentative, your API still has to validate **required reference types** like `string` using your preferred validation method, e.g. Using the `[ValidateNotEmpty]` declarative attribute, [Fluent Validation](/validation) or manual verification in your Service C# implementation and throwing `ArgumentException` for invalid properties ::: All this data is inferred from your services, with the ability to present data from additional metadata attributes such as: | Attribute name | Description | |-------------------------|-----------------------------------------------------------------| | `[Description]` | Class and properties text only description. | | `[Notes]` | Class only text and HTML description. | | `[Tag]` | Class only categorization of services, a way to group services. | | `[Input]` | Properties only presentation data for input fields. | If services require authentication using `Authenticate` or validation checking for role or permission, services will be shown with a padlock (🔒) signifying requiring authentication. Request and response names are links to show C# generated code representations of your DTOs and dependent types. Text metadata such as `[Description]` will also flow down into the generated code as comments for additional context. ## Code Tab The **Code** tab allows developers consuming your APIs from different programming backgrounds explore each APIs in their **preferred programming language** - currently supporting [11 different languages](https://servicestack.net/service-reference). It includes the necessary steps to call your APIs from client Apps, following the same pattern for each language: 1. Copy your API DTOs 2. Copy and install the package containing ServiceStack's generic JSON Service Client 3. Copy the initial source code pre-configured to call the API they want At which point without any code-gen or build tools, they'll end up with an Typed API configured to your APIs endpoint. E.g. this is what it looks like to **Python** developers utilizing our [most recently supported language](/releases/v5_12): That they can follow to quickly incorporate your API into their existing Apps, in addition **Python**, **C#** or **F#** developers could also copy this source code to their [Jupyter Notebooks](/jupyter-notebooks) for an instant typed visual REPL to explore your APIs. This is driven by the services that power the [Add ServiceStack Reference](./add-servicestack-reference.md) feature. This growing list of support languages shows example code using the specific API as well as required ServiceStack client libraries to use, and how to update the APIs DTOs. ## Responsive Design API Explorer's responsive layout works well in Smart Phones and Tablets letting you comfortably browse and call APIs on the go:
## API Customizations To become the preferred solution to document APIs, API Explorer was designed from scratch to support multiple customization levels, from being able to customize each properties Input control, its Form Grid Layout and further annotating each API or Type with declarative attributes & rich markup. ### API Annotations Whilst the capability of adding rich API Docs is essential when needed, we expect plain C# attributes will often be used to document APIs where `[Description]` can be used to provide a short summary on a **Type** and its **Properties** whilst richer HTML markup can be added to any Type using `[Notes]` as done in [Bookings.cs](https://github.com/NetCoreTemplates/blazor-vue/blob/main/MyApp.ServiceModel/Bookings.cs): ```csharp [Tag("bookings"), Description("Find Bookings")] [Notes("Find out how to quickly create a C# Bookings App from Scratch")] [Route("/bookings", "GET")] [Route("/bookings/{Id}", "GET")] [AutoApply(Behavior.AuditQuery)] public class QueryBookings : QueryDb { public int? Id { get; set; } } [Description("Booking Details")] [Notes("Captures a Persons Name & Room Booking information")] public class Booking : AuditBase { [AutoIncrement] public int Id { get; set; } //... } ``` Where it generates clean API docs displayed in a human-friendly table layout containing properties of its **Request DTO** Type and inherited **base class** properties, starting with the APIs Request DTO followed by all its referenced dependent types - resulting in the details page containing a complete snapshot of all types used in the API: ## API Docs We can further enhance API Explorer with our own custom [Vue.js Components](https://vuejs.org/guide/essentials/component-basics.html) by adding them to your Host projects local `/modules/ui/docs` folder which the Blazor WASM project template utilizes to showcase some customization examples: Where you can enhance any of your APIs or DTOs with rich API docs by adding **Vue Components** to `/modules/ui/docs/*.mjs` which gets included together with API Explorers own components in its single file download. API Explorer is built using [Vue.js](https://vuejs.org/guide/introduction.html) which is a popular JavaScript framework that's optimal for progressive enhancement that your components can also take advantage of to enhance it with rich dynamic UIs. For auto registration of components the `*.mjs` should match the API doc component which needs to be named `{Type}Docs`. Here's a simple [CreateBookingDocs.mjs](https://github.com/ServiceStack/ServiceStack/blob/main/ServiceStack.Blazor/tests/ServiceStack.Blazor.Bootstrap.Tests/Server/modules/ui/docs/CreateBookingDocs.mjs) component example used to generate API Docs for the `CreateBooking` API which just references **server** [AppMetadata](https://api.locode.dev/classes/shared.AppMetadata.html) to access server API info from the `/metadata/app.json` endpoint: ```js import { inject } from "vue" export const CreateBookingDocs = { template:`

Create Bookings API

Create a new room Booking for our {{serviceName}} hotels.

Here are some good tips on making room reservations

`, setup() { const server = inject('server') return { serviceName: server.app.serviceName } } } ``` ### Dynamic Components [QueryTodos](https://blazor-vue.web-templates.io/ui/QueryTodos?tab=details) is a more advanced example that generates a dynamic UI shared by all TODO APIs that generate its reactive **Mini Navigation UI** users can use to cycle through **all TODO API docs** with a `v-href="{ op }"` custom directive: Where instead of registering a single component, it exports a `install(app)` function to register API Doc components for all TODO CRUD APIs, all registered with the same `TodosDocs` component: ```js import { inject, computed } from "vue" import { humanize } from "@servicestack/client" export function install(app) { const apis = { QueryTodos: 'Query Todos, returns all Todos by default', CreateTodo: 'Create a Todo', UpdateTodo: 'Update a Todo', DeleteTodo: 'Delete Todo by Id', DeleteTodos: 'Delete multiple Todos by Ids', } const apiNames = Object.keys(apis) const TodosDocs = { template:`

{{humanize(op.request.name)}}

{{apis[op.request.name]}}

Other Todo APIs
{{humanize(name)}} {{info}}
`, setup() { const store = inject('store') const op = computed(() => store.op) const otherApis = computed(() => apiNames.filter(x => x !== store.op.request.name) .reduce((acc,x) => { acc[x] = apis[x]; return acc }, {})) return { op, apis, otherApis, humanize, } } } const components = apiNames.reduce((acc, x) => { acc[x + 'Docs'] = TodosDocs; return acc }, {}) app.components(components) } ``` ## Built-in App functionality ### JavaScript Libraries Your custom components can utilize built in libraries embedded in ServiceStack.dll where they will have access to the latest [Vue 3](https://vuejs.org/guide/introduction.html) reactive fx, [@servicestack/client](/javascript-client) client library and [Vue 3 Tailwind Component library](/vue/) which they can import by package name, e.g: ```js import { ref } from "vue" import { useClient } from "@servicestack/vue" import { humanify } from "@servicestack/client" ``` **Static Analysis** As all package dependencies are written in TypeScript you can install them as dev dependencies to get static analysis from its TypeScript definitions at dev time: ```bash npm install -D vue npm install -D @servicestack/client npm install -D @servicestack/vue ``` Your components can access your Apps Typed DTOs directly from the [ES6 Module DTO endpoint](/javascript-add-servicestack-reference) at `/types/mjs`, e.g: ```js import { QueryCoupons } from "/types/mjs" ``` #### App functionality Your components access to most App functionality via the injected dependencies for functionality defined in API Explorer's [app.mjs](https://github.com/ServiceStack/ServiceStack/blob/main/ServiceStack/tests/NorthwindAuto/ui/lib/app.mjs): ```js const app = inject('app') // App for customizing Vue App, register components, providers, plugins, etc const client = inject('client') // JsonServiceClient for API Calls const server = inject('server') // AppMetadata (metadata for your Server App and APIs) const store = inject('store') // API Explorer's Reactive object model const routes = inject('routes') // usePageRoutes() Reactive store to manage its SPA routing const breakpoints = inject('breakpoints') // useBreakpoints() Reactive store to Tailwind responsive breakpoints ``` Most of which creates instance of common library features in [core.mjs](https://github.com/ServiceStack/ServiceStack/blob/main/ServiceStack/tests/NorthwindAuto/wwwroot/js/core.mjs) that are documented at [api.locode.dev/modules/explorer.html](https://api.locode.dev/modules/explorer.html). You're also not limited with what's in API Explorer, with full access to [JavaScript Modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) you can import external 3rd Party packages the same way you import built-in packages. ### Built-in API Docs ServiceStack's own built-in APIs uses custom API Doc components itself to document its APIs, e.g. [/ui/docs/RegisterDocs.mjs](https://github.com/ServiceStack/ServiceStack/blob/main/ServiceStack/src/ServiceStack/modules/ui/docs/RegisterDocs.mjs) ```js export const RegisterDocs = { template:`

Register API

Public API users can use to create a new User Account, can be added to your AppHost with:

` } ``` Generates docs for the built-in **Register** API that includes **C#** Syntax highlighting using the pre-configured [highlightjs](https://highlightjs.org) directive: Whilst [/ui/docs/AuthenticateDocs.mjs](https://github.com/ServiceStack/ServiceStack/blob/main/ServiceStack/src/ServiceStack/modules/ui/docs/AuthenticateDocs.mjs) demonstrates a more advanced example in generating a responsive dynamic tab layout containing multiple relevant ServiceStack Auth YouTube videos: ### Live Reload When your App is run with `dotnet watch` it takes advantage ASP .NET Core's built-in file watcher to enable an instant **live reload** developer UX when contributing API Docs. Which results in being more productive then using C# attributes as changes are immediately visible without a restart. ## Customizing API Explorer You can override each built-in Component in API Explorer by maintaining local customized versions in `/wwwroot/modules/ui` where each API can be documented by adding [Custom API Docs](/api-explorer#api-docs) to `/docs/*.mjs`, whilst existing components can be overridden in [/components/*.mjs](https://github.com/ServiceStack/ServiceStack/tree/main/ServiceStack/src/ServiceStack/modules/ui/components) and custom UI added to `custom.*` ```files /wwwroot/modules/ui /docs *.mjs /components *.mjs custom.js custom.css custom.html ``` The `custom.html` and `custom.js` allows for further customization by including custom scripts and HTML fragments at the bottom of API Explorer which will let you modify API Explorer after it's loaded. ### Override built-in Components The built-in UIs also lets you override existing components by adding custom versions in [/js/components](https://github.com/ServiceStack/ServiceStack/tree/main/ServiceStack/src/ServiceStack/js/components), e.g: ```js const Brand = { template:` ` } export default Brand ``` Which override's the built-in `Brand` component to replace the Logo on the top-right of API Explorer, [Locode](/locode/) and the [Admin UI](/admin-ui) with the custom version below: Although a less invasive option if you just want to use your own logo is to configure the `UiFeature` plugin to override the default `BrandIcon` as the other Jamstack templates do in their [Configure.AppHost.cs](https://github.com/NetCoreTemplates/nextjs/blob/main/api/MyApp/Configure.AppHost.cs): ```csharp ConfigurePlugin(feature => { feature.Info.BrandIcon.Uri = "/assets/img/logo.svg"; feature.Info.BrandIcon.Cls = "inline-block w-8 h-8 mr-2"; }); ``` ## Custom Form Layouts Generated forms default to a two column layout, but this can be controlled using `FormLayout` for a specific operation. The `appHost.ConfigureOperation` method can be used to change the layout and order of the form used in API Explorer. For example, a `CreateCustomer` operation by default has the following properties. ```csharp [Route("/customers", "POST")] public class CreateCustomers : IReturn, IPost, ICreateDb { public string FirstName { get; set; } public string LastName { get; set; } public string Company { get; set; } public string Address { get; set; } public string City { get; set; } public string State { get; set; } public string Country { get; set; } public string PostalCode { get; set; } public string Phone { get; set; } public string Fax { get; set; } public string Email { get; set; } public long? SupportRepId { get; set; } } ``` ### Default Form UI And is presented in API Explorer using the following generated form by default. ### Custom Form Layout Customizing this layout using `ConfigureOperation`, we can control the placement and other attributed of each `InputInfo`. When overriding the `FormLayout`, it is in the structure of Rows, then columns in the nested list. So grouping controls like `City`, `State` and `PostalCode` in the same row allows us to control the presentation. ```csharp appHost.ConfigureOperation(operation => operation.FormLayout = new() { Input.For(x => x.FirstName, c => c.FieldsPerRow(2)), Input.For(x => x.LastName, c => c.FieldsPerRow(2)), Input.For(x => x.Email), Input.For(x => x.Company), Input.For(x => x.Address), Input.For(x => x.City, c => c.FieldsPerRow(3)), Input.For(x => x.State, c => c.FieldsPerRow(3)), Input.For(x => x.PostalCode, c => c.FieldsPerRow(3)), Input.For(x => x.Country), Input.For(x => x.Phone, c => c.FieldsPerRow(2)), Input.For(x => x.Fax, c => c.FieldsPerRow(2)), Input.For(x => x.SupportRepId), }); ``` Gives us the updated layout in API Explorer. ### Custom Input Controls Each input field can be customized with client side visual and behavioural changes by using `InputInfo` when customizing `FormLayout`. ```csharp Input.For(x => x.Email, info => { info.Label = "Personal Email Address"; info.Placeholder = "me@email.com"; info.Type = "email"; }) ``` Now our `label` and `placeholder` changes are visible and trying to submit a value without an `@` we get a client side warning. Values for `InputInfo` are merged with the `[Input]` attribute that can be used on Request DTO class properties. This allows you to keep the default layout while still controlling `Input` options directly on your Request DTO class. ```csharp public class CreateCustomers : IReturn, IPost, ICreateDb { [Input(Placeholder = "me@email.com", Type = "email", Label = "Personal Email Address")] public string Email { get; set; } } ``` ### Register Form Layout The built-in `RegistrationFeature` also uses a custom Form layout to mask its password fields: ```csharp appHost.ConfigureOperation(op => op.FormLayout = new() { Input.For(x => x.DisplayName, x => x.Help = "Your first and last name"), Input.For(x => x.Email, x => x.Type = Input.Types.Email), Input.For(x => x.Password, x => x.Type = Input.Types.Password), Input.For(x => x.ConfirmPassword, x => x.Type = Input.Types.Password), }); ``` Which overrides the default Auto UI Form to use this custom layout: