Set up OpenAPI client for authenticated API calls in Umbraco backoffice (REQUIRED for custom APIs)
version
1.0.0
location
managed
allowed-tools
Read, Write, Edit, Bash
Umbraco OpenAPI Client Setup
CRITICAL: Why This Matters
NEVER use raw fetch() calls for Umbraco backoffice API communication. Raw fetch calls will result in 401 Unauthorized errors because they don't include the bearer token authentication that Umbraco requires.
ALWAYS use a generated OpenAPI client configured with Umbraco's auth context. This ensures:
Proper bearer token authentication
Type-safe API calls
Automatic token refresh handling
When to Use This
Use this pattern whenever you:
Create custom C# API controllers with [BackOfficeRoute]
Need to call your custom APIs from the backoffice frontend
Build trees, workspaces, or any UI that loads data from custom endpoints
Setup Overview
The setup has 4 parts:
: Controller with Swagger/OpenAPI documentation
C# Backend
Client Dependencies: @hey-api/openapi-ts (the @hey-api/client-fetch plugin is bundled with it)
Generation Script: Fetches swagger.json and generates TypeScript client
Entry Point Configuration: Configures client with Umbraco auth
Step-by-Step Implementation
1. C# Backend Setup (Swagger/OpenAPI)
Your API must be exposed as a backoffice OpenAPI document. Create a composer:
Umbraco 18+: The OpenAPI stack moved off Swashbuckle's SwaggerGenOptions
(and the BackOfficeSecurityRequirementsOperationFilterBase / OperationIdHandler
types) to a fluent AddBackOfficeOpenApiDocument(...) builder. Use the pattern
below; the old SwaggerGenOptions approach no longer compiles on v18.
// Composers/MyApiComposer.csusing Umbraco.Cms.Api.Common.OpenApi;
using Umbraco.Cms.Api.Management.OpenApi;
using Umbraco.Cms.Core.Composing;
using Umbraco.Cms.Core.DependencyInjection;
namespaceMyExtension.Composers;
publicclassMyApiComposer : IComposer
{
publicvoidCompose(IUmbracoBuilder builder) =>
// Registers a dedicated backoffice OpenAPI document, served at// /umbraco/swagger/{ApiName}/swagger.json and browsable via Swagger UI.// See https://docs.umbraco.com/umbraco-cms/extend-your-project/tutorials/creating-a-backoffice-api
builder.AddBackOfficeOpenApiDocument(
Constants.ApiName,
document => document
.WithTitle("My Extension API")
.WithBackOfficeAuthentication()
.WithJsonOptions(Umbraco.Cms.Core.Constants.JsonOptionsNames.BackOffice)
.ConfigureOpenApiOptions(options =>
options.AddDocumentTransformer((doc, _, _) =>
{
doc.Info.Version = "1.0";
return Task.CompletedTask;
})));
}
// ConstantspublicstaticclassConstants
{
publicconststring ApiName = "myextension";
}