Hey! So I’ve been going back and forth on this
i was actually workong on a coustom dashboard for our client here are two approaches that actually work in v17, pick whichever fits your setup better., maybe1,
Option 1 Plain ControllerBase with backoffice route (simpler)
this is the cleanest approach. No bearer token needed, the backoffice session cookie handles auth:
[ApiController]
[Route("umbraco/backoffice/api/v1/[controller]")]
public class ScheduledContentController : ControllerBase
{
[HttpGet("getcontent")]
public IActionResult GetContent()
{
return Ok(new { message = "works" });
}
}
js
async function loadData() {
const response = await fetch('/umbraco/backoffice/api/v1/scheduledcontent/getcontent', {
method: 'GET',
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
});
if (!response.ok) throw new Error(`HTTP error! ${response.status}`);
const data = await response.json();
console.log(data);
}
The key thing here is the route prefix /umbraco/backoffice/api/v1/ — your current /api/ prefix is likely why you’re getting the 401.
Option 2 UmbControllerBase with proper auth context (TypeScript), maybe not but still good to include
If you’re open to TypeScript and the Umbraco component system, this is the more “correct” v17 way uses UMB_AUTH_CONTEXT to get the bearer token cleanly:
ts
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
import { UMB_AUTH_CONTEXT } from '@umbraco-cms/backoffice/auth';
export class ScheduledContentRepository extends UmbControllerBase {
private async getAuthHeaders(): Promise<HeadersInit> {
const authContext = await this.getContext(UMB_AUTH_CONTEXT);
const token = await authContext?.getLatestToken();
return {
'Content-Type': 'application/json',
...(token ? { 'Authorization': `Bearer ${token}` } : {}),
};
}
async getContent() {
const headers = await this.getAuthHeaders();
const response = await fetch('/umbraco/backoffice/api/v1/scheduledcontent/getcontent', {
headers,
credentials: 'include',
});
if (!response.ok) return null;
return await response.json();
}
}
Full working example of Option 2 in our TagManager package if it helps: Umbraco-Tag-Manager/TagManager/Client/src/api/tagmanager-repository.ts at main · ZAAKS/Umbraco-Tag-Manager · GitHub