Get started with the Content Delivery API.
The Content Delivery API delivers headless capabilities built directly into Umbraco. It allows you to retrieve your content items in a JSON format and lets you preset them in different channels, using your preferred technology stack. This feature preserves the friendly editing experience of Umbraco, while also ensuring a performant delivery of content in a headless fashion. And with its different extension points, you can tailor this API to fit a broad range of requirements.
When upgrading an existing project to Umbraco 12, you will need to opt-in explicitly for using the Delivery API. Below you will find the steps you need to take in order to configure it for your Umbraco project.
When you start with a fresh Umbraco 12 installation, the Delivery API is also disabled by default. To enable it, you can proceed directly to the Enable the Content Delivery API section, as the step below is already complete in this case.
Open your project's Startup.cs
file.
Register the API dependencies in the ConfigureServices
method by adding .AddDeliveryApi()
:
Open your project's appsettings.json
.
Insert the DeliveryApi
configuration section under Umbraco:CMS
.
Add the Enabled
key and set its value to true
:
Once the Content Delivery API is enabled, you will need to manually rebuild the Delivery API content index (DeliveryApiContentIndex). This can be done using the "Examine Management" dashboard in the "Settings" section. Once the index is rebuilt, the API will be able to serve the latest content from the multiple-items endpoint.
When the Delivery API is enabled in your project, all your published content will be made available to the public by default. However, a few additional configuration options will allow you to restrict access to the Delivery API endpoints and limit the content that is returned.
Umbraco:CMS:DeliveryApi:PublicAccess
determines whether the Delivery API (if enabled) should be publicly accessible or if access should require an API key.
Umbraco:CMS:DeliveryApi:ApiKey
specifies the API key to use for authorizing access to the API when public access is disabled. This setting is also used for accessing draft content for preview.
Are you using Umbraco Cloud?
When hosting your Umbraco website on Umbraco Cloud, security should always be prioritized for sensitive information like API keys. Rather than storing it as plain text in the appsettings.json
file, it is strongly encouraged to use Umbraco Cloud's built-in secrets management. This feature allows you to securely store and manage sensitive data, keeping your API key safe from potential exposure or unauthorized access. To learn more about implementing Secrets management, read the Secrets management documentation.
Umbraco:CMS:DeliveryApi:DisallowedContentTypeAliases
contains the aliases of the content types that should never be exposed through the Delivery API, regardless of any other configurations.
Another valuable configuration option to consider when working with the Delivery API is RichTextOutputAsJson
:
Umbraco:CMS:DeliveryApi:RichTextOutputAsJson
enables outputting rich text content as JSON rather than the default HTML output. JSON can be a preferred format in many scenarios, not least because it supports the routing of internal links better than HTML does.
To test the functionality of the API, you need to create some content first.
Before exploring the API endpoints detailed below, there are a few concepts to keep in mind.
The output produced by the Delivery API can either represent a specific content item or a paged list of multiple items.
When referring to a specific content item in your API requests, the id
parameter always refers to the item’s key (GUID). It does not refer to its integer node id.
GET
/umbraco/delivery/api/v1/content/item/{id}
Returns a single item.
GET
/umbraco/delivery/api/v1/content/item/{path}
Returns a single item.
GET
/umbraco/delivery/api/v1/content/item
Returns single or multiple items by id.
GET
/umbraco/delivery/api/v1/content
Returns single or multiple items.
All endpoints are documented in a Swagger document at {yourdomain}/umbraco/swagger
. Keep in mind that this document is not available in production mode by default. For more information check the API versioning and OpenAPI article.
The Content Delivery API provides a number of query parameters that allow you to customize the content returned by the API to fit your needs. For each endpoint, the relevant query parameters are already specified within their corresponding documentation above. In addition to standard parameters like skip
and take
, the API provides different possibilities for the value of expand
, fetch
, filter
and sort
parameters. Below are the options supported out of the box.
You can extend the built-in selector, filter, and sorting capabilities of the Delivery API by creating your own custom query handlers.
Refer to the Output expansion concept for more information about the benefits of this parameter.
?expand=all
All expandable properties on the retrieved content item will be expanded.
?expand=property:alias1
A specific expandable property with the property alias alias1
will be expanded.
?expand=property:alias1,alias2,alias3
Multiple expandable properties with the specified property aliases will be expanded.
To query content items based on their structure, you can apply a selector option to the /umbraco/delivery/api/v1/content
endpoint. The selector allows you to fetch different subsets of items based on a GUID or path of a specific content item. If no fetch
parameter is provided, the Delivery API will search across all available content items. The following built-in selectors can be used out-of-the-box:
?fetch=ancestors:id/path
All ancestors of a content item specified by either its id
or path
will be retrieved.
?fetch=children:id/path
All immediate children of a content item specified by either its id
or path
will be retrieved.
?fetch=descendants:id/path
All descendants of a content item specified by either its id
or path
will be retrieved.
Only one selector option can be applied to a query at a time. This means that you can't combine multiple fetch parameters in a single query.
For example, the following API call will attempt to retrieve all the content items that are directly below an item with the id dc1f43da-49c6-4d87-b104-a5864eca8152
:
Request
The filter query parameter allows you to specify one or more filters. These filters must match in order for a content item to be included in the response. The API provides a few built-in filters that you can use right away with the /umbraco/delivery/api/v1/content
endpoint:
?filter=contentType:alias
This filter restricts the results to only include content items that belong to the specified content type. Replace alias
with the alias of the content type you want to filter by.
?filter=name:nodeName
When this filter is applied, only content items whose name matches the specified value will be returned. Replace nodeName
with the name of the item that you want to filter by.
Additionally, filters support negation. By using an exclamation mark (!
) before the filter value, you can exclude content items from the result set that match the filter criteria. For example, to fetch all content items except those with the content type article
, you can use the filter parameter like this: ?filter=contentType:!article
.
Multiple filters can be applied to the same request in addition to other query parameters:
Request
Specifying how the results should be ordered, can be achieved using the sort
query option. You can use this parameter to sort the content items by different fields, including create date, level, name, sort order, and update date. For each field, you can specify whether the items should be sorted in ascending (asc) or descending (desc) order. Without a sort
query parameter, the order of the results will be determined by the relevance score of the DeliveryApiContentIndex for the given search term.
?sort=createDate:asc/desc
An option to sort the results based on the creation date of the content item in either asc
or desc
order.
?sort=level:asc/desc
An option to sort the results based on the level of the content item in the content tree in either asc
or desc
order.
?sort=name:asc/desc
An option to sort the results based on the name of the content item in either asc
or desc
order.
?sort=sortOrder:asc/desc
An option to sort the results based on the sort order of the content item in either asc
or desc
order.
?sort=updateDate:asc/desc
An option to sort the results based on the last update date of the content item in either asc
or desc
order.
Different sorting options can be combined for the /umbraco/delivery/api/v1/content
endpoint, allowing for more advanced sorting functionality. Here is an example:
Request
The Delivery API has been designed with extensibility in mind, offering multiple extension points that provide greater flexibility and customization options. These extension points allow you to tailor the API's behaviour and expand its capabilities to meet your specific requirements.
You'll find detailed information about the specific areas of extension in the articles below:
.NET imposes a limit on the depth of object nesting within rendered JSON. This is done in an effort to detect cyclic references. Learn more about it in the official .NET API docs.
If the limit is exceeded, .NET will throw a JsonException
.
In some cases the content models might be so deeply nested that the Delivery API produces JSON that exceeds this limit. If this happens, the JsonException
will be logged and shown in the Umbraco log viewer.
To handle this we have to change the limit. Since the Delivery API has its own JSON configuration, we can do so without affecting the rest of our site.
First, we have to add these using
statements to Startup.cs
:
Now we can add the following code snippet to the ConfigureServices()
method in Startup.cs
:
The Content Delivery API provides a powerful and flexible way to retrieve content from the Umbraco CMS. There are, however, certain limitations to be aware of.
In this section, we will discuss some of the known limitations of the API, and how to work around them if necessary.
The Delivery API supports protected content and member authentication. This is however an opt-in feature. You can read more about it in the Protected Content in the Delivery API article.
If member authentication is not explicitly enabled, protected content is ignored and never exposed by the Delivery API.
As a result, lifting protection from a content item requires an additional step to ensure it becomes accessible through the Delivery API. The recommended way is to publish the content item again. Alternatively, you can manually rebuild the DeliveryApiContentIndex to reflect the changes.
There are certain limitations associated with some of the built-in property editors in Umbraco. Let's go through these below:
The Legacy Grid in Umbraco is supported to a certain extent. However, keep in mind that it may not be suitable for headless content scenarios. Instead, we recommend using the Block Grid property editor.
The Delivery API is not going to support the rendering of Macros within the Rich Text Editor. Therefore, any Macros included in the content will not be executed or output when retrieving content through the API.
When outputting the Rich Text Editor content as HTML (the default format), be aware that internal links may be insufficient in a multi-site setup. There is a possibility that this limitation may be addressed in future updates. However, consider the alternative approach to rendering the Rich Text Editor content as JSON.
The Member Picker property editor is not supported in the Delivery API to avoid the risk of leaking member data.
The Multinode Treepicker property editor, when configured for members, is also unsupported in the Delivery API. This is due to the same concern of potentially leaking member data.
DisallowedContentTypeAliases
When changing the content type aliases in the Umbraco:CMS:DeliveryApi:DisallowedContentTypeAliases
configuration setting, the DeliveryApiContentIndex should be rebuilt. This ensures that the disallowed content types are not exposed through the Delivery API.
Alternatively the relevant content items can be republished. This will ensure that the changes are reflected, eliminating the need to rebuild the index.
Name | Type | Description |
---|---|---|
Name | Type | Description |
---|---|---|
Name | Type | Description |
---|---|---|
Name | Type | Description |
---|---|---|
Name | Type | Description |
---|---|---|
Name | Type | Description |
---|---|---|
Name | Type | Description |
---|---|---|
Name | Type | Description |
---|---|---|
Name | Type | Description |
---|---|---|
Name | Type | Description |
---|---|---|
id*
String
GUID of the content item
expand
String
Which properties to expand and therefore include in the output if they refer to another piece of content
Accept-Language
String
Requested culture
Api-Key
String
Access token
Preview
Boolean
Whether draft content is requested
Start-Item
String
URL segment or GUID of the root content item
path*
String
Path of the content item
expand
String
Which properties to expand and therefore include in the output if they refer to another piece of content
Accept-Language
String
Requested culture
Api-Key
String
Access token
Preview
Boolean
Whether draft content is requested
Start-Item
String
URL segment or GUID of the root content item
id*
String Array
GUIDs of the content items
expand
String
Which properties to expand in the response
Accept-Language
String
Requested culture
Api-Key
String
Access token
Preview
Boolean
Whether draft content is requested
Start-Item
String
URL segment or GUID of the root content item
fetch
String
Structural query string option (e.g. ancestors
, children
, descendants
)
filter
String Array
Filtering query string options (e.g. contentType
, name
)
sort
String Array
Sorting query string options (e.g. createDate
, level
, name
, sortOrder
, updateDate
)
skip
Integer
Amount of items to skip
take
Integer
Amount of items to take
expand
String
Which properties to expand and therefore include in the output if they refer to another piece of content
Accept-Language
String
Requested culture
Api-Key
String
Access token
Preview
Boolean
Whether draft content is requested
Start-Item
String
URL segment or GUID of the root content item
Discover how to customize the Content Delivery API's response for your custom property editors.
Out of the box, the Delivery API supports custom property editors, ensuring they are rendered alongside the built-in ones in Umbraco. However, if the output generated by your property editor isn't optimal for a headless context, you have the ability to customize the API response. This customization won't impact the Razor rendering, allowing you to tailor the Content Delivery API response according to your specific requirements.
In this article, we'll look into how you can work with the IDeliveryApiPropertyValueConverter
interface and implement custom output expansion for your custom property editors.
The examples in this article revolve around the fictional My.Custom.Picker
property editor. This property editor stores the key of a single content item and is backed by a property value converter.
We will not dive into the details of creating a custom property editor for Umbraco in this article. If you need guidance on that, please refer to the Creating a Property Editor and Property Value Converters articles.
To customize the output of a property value editor in the Delivery API, we need to opt-in by implementing the IDeliveryApiPropertyValueConverter
interface.
The code example below showcases the implementation of this interface in the property value converter for My.Custom.Picker
. Our focus will be on the methods provided by the IDeliveryApiPropertyValueConverter
, as they are responsible for customizing the Delivery API response.
Towards the end of the example, you will find the response models that we will be using.
The IsConverter()
and GetPropertyValueType()
methods are inherited from the PropertyValueConverterBase
class, which is covered in the Property Value Converters article.
The Implementation of the IDeliveryApiPropertyValueConverter
interface can be found in the following methods:
GetDeliveryApiPropertyCacheLevel()
: This method specifies the cache level used for our property representation in the Delivery API response.
GetDeliveryApiPropertyValueType()
: This method defines the value type of the custom property output for the Delivery API response.
ConvertIntermediateToDeliveryApiObject()
: This method converts the value from the property editor to the desired custom object in a headless context.
In the given example, the content key (Guid
value) is used when rendering with Razor. This is sufficient because Razor provides full access to the published content within the rendering context. In a headless context, we do not have the same access. To prevent subsequent round-trips to the server, we create a richer output model specifically for the Delivery API.
The following example request shows how our custom implementation is reflected in the resulting API response. In this case, our custom property editor is configured under the alias "pickedItem"
.
Request
Response
Output expansion allows us to conditionally add another level of detail to the Delivery API output. Usually, these additional details are "expensive" to retrieve (for example, requiring database access to populate). By applying output expansion, we provide the option for the caller of the API to opt-in explicitly to this "expensive" operation. From the caller's perspective, the alternative might be an even more expensive additional round-trip to the server.
In our example, output expansion is implemented within ConvertIntermediateToDeliveryApiObject()
. By considering the value of the expanding
parameter, we can modify the BuildDeliveryApiCustomPicker()
method as follows:
If the expanding
parameter is false
, the method returns the same shallow representation of the referenced content item as before. Otherwise, we retrieve the corresponding IPublishedContent
and construct our response object accordingly.
To see the expanded output in the API response, we need to add the expand
query parameter to our request. We can use either ?expand=all
to expand all properties or ?expand=property:pickedItem
to expand the specific 'pickedItem'
property.
Request
Response
The itemDetails
property of the pickedItem
in the JSON response contains the additional details of the selected content item.
Learn how to extend the Content Delivery API with custom selecting, filtering, and sorting options for the multi-item-based endpoint.
The Delivery API allows you to retrieve multiple items by utilizing the /umbraco/delivery/api/v1/content
endpoint. With the built-in query parameters, you have the flexibility to get any number of content nodes based on your needs. For a comprehensive list of supported query options, please refer to the Endpoints section.
For the query endpoint, we have created a new Examine index (DeliveryApiContentIndex) that facilitates fast retrieval of the desired content. This index ensures quick indexing and searching of data, with the possibility for future extensions.
In this article, we'll explore creating custom selecting, filtering, and sorting options to enhance the querying capabilities of the Delivery API.
Let's take a look at an example of using the query endpoint with query parameters for fetch
, filter
, and sort
. A request might look like this:
The placeholders in the example (xxx
, yyy
, etc.) represent the values that each query option evaluates in order to determine the suitable query handler.
You can include only one fetch
parameter, while multiple filter
and sort
parameters are allowed. Additionally, the order of the sort
parameters influences the sorting behaviour. Refer to the Query parameters section for the currently supported options.
The implementation of each querying option consists of a class for indexing the data into the DeliveryApiContentIndex and another one for handling the query. By implementing the IContentIndexHandler
interface, you can control how your relevant data is indexed and made available for querying through our index. And you can customize the querying behaviour to suit your needs by implementing the ISelectorHandler
, IFilterHandler
, and ISortHandler
interfaces.
In the following sections, we will explore the implementation details of creating custom querying functionality for the Delivery API.
Selectors handle the fetch
part of a query.
To showcase how to build a custom selector, consider a site structure with a few blog posts. A post is linked to an author, which is another content item.
Authors can be marked as 'Featured' using a toggle, granting them additional visibility and recognition. We will use this marker as part of the indexing implementation for our selector option.
The following example demonstrates the implementation of an AuthorSelector
, which allows you to customize the querying behaviour specifically for finding all featured authors. This class contains both indexing and querying responsibilities. However, keep in mind that it is generally recommended to separate these responsibilities into dedicated classes.
The AuthorSelector
class implements the ISelectorHandler
and IContentIndexHandler
interfaces.
ISelectorHandler
allows for handling the fetch
value in API queries through the CanHandle()
and BuildSelectorOption()
methods.
CanHandle()
determines if the given fetch
query corresponds to the "featuredAuthors"
value.
BuildSelectorOption()
constructs the selector option to search for authors with a positive value (for example, "y"
) in a "featured"
index field.
The GetFields()
and GetFieldValues()
methods each play a role in defining how the data should be indexed and made searchable.
GetFields()
defines the behaviour of fields that are added to the index. In this example, the "featured"
field is added as a "raw" string for efficient and accurate searching.
GetFieldValues()
is responsible for retrieving the values of the defined index fields. In this case, the "featured"
field of content items of type "author"
. It creates an IndexFieldValue
with the appropriate field value ("y"
for featured, "n"
otherwise), which will be added to the index.
Since our custom query option modifies the index structure, we will need to rebuild the DeliveryApiContentIndex. You can find it by navigating to the "Examine Management" dashboard in the "Settings" section. Once rebuilt, we can make a request to the Delivery API query endpoint as follows:
Request
Response
Filters handle the filter
part of a query.
Staying within the topic of blog posts and their authors, we will create a custom filter to find posts by specific author(s).
This filter allows specifying the desired author(s) by their key (Guid
) in an author:
filter option. Multiple authors can be included by listing their keys as comma-separated-values, like:
Request
The response will include the blog posts associated with the provided authors, enabling us to retrieve only the relevant results from the API.
Response
Our filter implementation follows a similar structure to the custom selector we discussed earlier. We continue to utilize the IContentIndexHandler
interface, but this time we introduce the IFilterHandler
. This combination gives us flexibility and control over the filtering behaviour.
The procedure remains the same - we store and query the author key in a new "authorId"
field within the index. Consequently, we will need to rebuild the index to reflect the changes.
To illustrate the implementation, consider the following code example:
The principal difference from the selector is that the filter implements BuildFilterOption()
instead of BuildSelectorOption()
. Here, the filter performs an exact match for any specified Guid
in the query. Efficiently, this makes the filter perform an OR
operation against the index.
Since we need to perform an exact match, the index field (authorId
) is once again defined as a "raw" string. Other options include "analyzed" and "sortable" strings. These support "contains" searches and alpha-numeric sorting, respectively.
To define your custom filter, you currently have four options: Is
, IsNot
, Contains
and DoesNotContain
.
It is possible to pass multiple values to each operator, and these values will be treated inclusively as an or operator. For example, if tag1
and tag2
were passed into a filter using the Is
operator, any document containing either tag1
or tag2
would return. The request for this might look like this:
GET /umbraco/delivery/api/v1/content?filter=customTagFilter:tag1,tag2
If you require this functionality to be restrictive i.e. tag1
and tag2
, then the current approach would be to chain the custom filter. The request would change to look more like this:
GET /umbraco/delivery/api/v1/content?filter=customTagFilter:tag1&filter=customTagFilter:tag2
Finally, we can also add custom handling for the sort
part of the query.
We'll add a custom sort handler that allows us to sort blog posts based on a custom "publishDate"
Date Picker property. The implementation will allow for sorting the posts in ascending or descending order.
This sorting should only be used with query results that have a published date to ensure accurate results.
To demonstrate this, consider the following implementation example:
The implementation follows the same structure as the other examples, defined by the IContentIndexHandler
and ISortHandler
interfaces.
One point to highlight is that we store the "publishDate"
value as a "date" field in the index, which allows for correct date sorting.
Once more, when adding fields to the index, we need to rebuild it to reflect the changes.
In the following example request, we also apply the author filter to retrieve only "blogpost"
content nodes, which we know have the "publishDate"
field.
Request
Response
How to use member authorization with the Delivery API to access protected content.
Umbraco allows for restricting access to content. Using the "Public access" feature, specific content items can be protected and made accessible only for authorized members. The same is possible in the Delivery API.
By default, protected content is ignored by the Delivery API, and is never exposed through any API endpoints. However, by enabling member authorization in the Delivery API, protected content can be accessed by means of access tokens.
Member authorization in the Delivery API was introduced in version 12.3.
If you are not familiar with members in Umbraco, please read the Members article.
Member authentication and authorization in the Delivery API is performed using the OpenId Connect flow Authorization Code Flow + Proof Key of Code Exchange (PKCE). This is a complex authorization flow, and it is beyond the scope of this article to explain it. Many articles can be found online that explain the flow in detail.
Most programming languages have OpenId Connect client libraries to handle the complexity for us. AppAuth
is a great example of such a library. In ASP.NET Core, OpenId Connect support is built into the framework.
Member authorization is an opt-in feature of the Delivery API. To enable it, configure MemberAuthorization:AuthorizationCodeFlow
in the DeliveryApi
section of appsettings.json
:
Enabled
must be true
.
One or more LoginRedirectUrls
must be configured. These specify where the server is allowed to redirect the client after a successful authorization.
Optionally one or more LogoutRedirectUrls
must be configured. These specify where the server is allowed to redirect the client after successfully terminating a session.
These are only necessary if logout is implemented in the client.
All redirect URLs must be absolute and contain the full path to the expected resource. It is not possible to use wildcards or to allow all paths under a given domain.
When changing the MemberAuthorization
configuration, Umbraco must be restarted to pick up on the changes.
When enabling or disabling member authentication, the DeliveryApiContentIndex
must be rebuilt to correctly reflect the existing content protection state.
The index can be rebuilt from the Examine Management dashboard.
Many client libraries support automatic discovery of the server OpenId endpoints. This is also supported by the Delivery API, so likely we do not have to worry about the server endpoints.
If automatic discovery is not applicable, the server endpoints must be configured manually. The server endpoints can be found at https://{server-host}/.well-known/openid-configuration
.
Keep in mind that the API versions can change over time, which might affect the configuration.
To connect the client and the server, we need to apply some configuration details to the connection:
The client_id
must be umbraco-member
.
The response_type
must be code
.
The redirect_uri
must be one of the configured LoginRedirectUrls
.
The scope
must either be empty, or be openid
and/or offline_access
.
PKCE must be enabled.
For inspiration, the samples section at the end of this article shows how to configure an ASP.NET Core client.
Authorization Code Flow + Proof Key of Code Exchange (PKCE) requires the authentication service (identity provider) to be separate from the client application. This is to ensure that credentials are never exposed directly to the client application.
As an authentication service, we can use both Umbraco's built-in member authentication and external identity providers. By default the Delivery API attempts to use the built-in member authentication.
First and foremost we need a login page. By ASP.NET Core defaults, this page should be located at /Account/Login
. However, we can change the default path by adding the following piece of code:
To invoke this code, we need to call SetCustomMemberLoginPath()
in Startup.cs
:
No matter the path to the login page, we still need a page to render the login screen. Create a content item located at the login page path, and use this template to render it:
With all this in place, it's time to test the setup. Use a browser to perform a request to https://{server-host}/umbraco/delivery/api/v1/security/member/authorize
with these query string parameters:
client_id=umbraco-member
redirect_uri=https://absolute.redirect.url/path/after/login
(replace the value with one of the configured login redirect URLs)
response_type=code
code_challenge=WZRHGrsBESr8wYFZ9sx0tPURuZgG2lmzyvWpwXPKz8U
code_challenge_method=S256
If everything works as expected, the request will yield a redirect to the login page. Completing the login form will cause a redirect to the specified redirect URL with a code
query string parameter. The code
can subsequently be exchanged for an access token, which can be used to access protected content.
Do not worry about the URL construction and subsequent handling of the code
parameter. This complexity is what the OpenId Connect client libraries handle for us.
For more inspiration on using the built-in member authentication, check the Members Registration and Login article. Here you will also learn how to create member sign-up functionality.
Umbraco allows adding external identity providers for both backoffice users and members. The process is documented in detail in the External Login Providers article.
The Delivery API supports the same functionality. In the following we'll be using GitHub to test this.
First, we need to create an OAuth App in GitHub. This is done in the GitHub Developer Settings. Use https://{server-host}/umbraco/signin-github
as authorization callback URL in the App.
Once the App is created, generate a new client secret within the App. Make sure to copy both the client ID of your App and the generated secret.
Now we need to connect Umbraco members with the App:
Add the NuGet package AspNet.Security.OAuth.GitHub
to your Umbraco project.
Add the code below to configure the connection to the App. Remember to update the OAuth client ID and secret.
Finally, we need to invoke the connection configuration by calling AddGitHubAuthentication()
in Startup.cs
.
Now we can test the setup. We'll be calling https://{server-host}/umbraco/delivery/api/v1/security/member/authorize
as described previously, but we need to add one more query string parameter:
identity_provider=UmbracoMembers.GitHub
If the setup is correct, the request will yield a redirect to the GitHub login page. Here we need to authorize the GitHub OAuth App we created earlier, in order to complete the login. Upon completion, a series of redirects will once more take us to the specified redirect URL with a code
query string parameter.
Different client libraries have different ways of declaring the identity_provider
in the authorization request. The samples section shows how to configure this in an ASP.NET Core client.
We can also add the external identity providers to the member authentication login screen. This way the end user can decide whether to log in as a registered member, or use an external identity provider.
The Login partial view features an implementation of this combined login experience.
When the authorization flow completes we'll obtain an access token. This token can be used as a bearer token to access protected content for the logged-in member:
Access tokens expire after one hour. Once expired, a new access token must be obtained to continue accessing protected content.
Refresh tokens provide a means to obtain a new access token without having to go through the authentication flow. A refresh token is issued automatically by the Delivery API when the offline_access
scope is specified in the authorization request.
Refresh tokens are subject to certain limitations and can result in security issues if not applied correctly. All this is beyond the scope of this article to explain in detail. Please familiarize yourself with the inner workings of refresh tokens before applying them in a solution.
The member authorization is tied to the access and refresh tokens obtained in the authorization flow. Discarding these tokens efficiently terminates the access to protected content.
However, the tokens are still valid and can be reapplied until they expire. Depending on your scenario, it might be prudent to revoke the tokens and maybe even terminate the session on the server.
Access and refresh tokens can be revoked by performing a POST
request containing the token:
When terminating a session on the server, the member is logged out of Umbraco. This means any subsequent authorization attempt will require an explicit login.
To terminate the active session for any given member, you must redirect the browser to the signout endpoint. The request must contain one of the white-listed LogoutRedirectUrls
from the appsettings.json
:
The Delivery API Swagger document can be configured to support member authentication.
Before we can do that, we need two things in place:
We have to implement a login page as described above.
We must add https://{server-host}/umbraco/swagger/oauth2-redirect.html
to the configured LoginRedirectUrls
.
With these in place, we can enable member authentication in Swagger for the Delivery API by adding the following to Startup.cs
:
The Swagger UI will now feature authorization.
Remember to use umbraco-member
as client_id
when authorizing. client_secret
can be omitted, as it is not used by the authorization flow.
The following samples show how to configure an ASP.NET Core client to utilize member authorization in the Delivery API.
To put these samples into context, please refer to the article above.
When using external identity providers, Umbraco still allows for performing local two-factor authentication for members. This feature is not available in the Delivery API. Instead, two-factor authentication should be performed at the identity provider.
Configure custom preview URLs to provide editors with seamless access to external preview environments for the Content Delivery API data.
With Umbraco, you can save and preview draft content before going live. The preview feature allows you to visualize how a page will look once it is published, directly from within the backoffice. This is also possible for the Content Delivery API data. You can extend the preview functionality in the backoffice by configuring external preview URLs for client libraries consuming the Content Delivery API.
To get familiar with the preview functionality in the Delivery API, please refer to the Preview concept section.
The support for configuring additional preview environments in the Delivery API was introduced in version 12.3.
If your client libraries feature preview functionality, you can enable editors in Umbraco to navigate directly to their preferred preview environments. To achieve this, start by generating the necessary URLs for each environment you wish to allow for preview. These URLs need to trigger preview mode within your application, which will fetch and present draft content from the Delivery API.
Once you have these preview URLs, you will need to register them through code in Umbraco.
Additionally, there are plans to simplify this process further. In an upcoming major version of Umbraco, a UI will be introduced, allowing you to configure these custom preview URLs directly from the backoffice.
Here is an example of how to register such preview URLs for both variant and invariant content using a notification handler:
The purpose of this notification handler is to dynamically generate additional preview URLs for published content items only (for the sake of simplicity). It constructs two custom preview URLs, one for a development environment and another for a staging environment. These URLs include the content's route, culture variant, and a preview
query parameter to enable preview mode in the client application.
You can then register your notification handler in a composer like this:
Now that we have set up additional preview URLs for the Delivery API data, you can access them from the Content section. When you open a content node, you will see new preview options for the external environments you have configured. Next to the regular "Save and preview" button, there is an arrow for the multiple URLs that have been added. Click it to see all the available preview URLs, as shown below:
Below is an example with variants, showcasing both the English and Danish versions of a content node.
Using the Media Delivery API.
The Media Delivery API allows for accessing the Umbraco media items in a headless manner. This API applies many of the same concepts as its content counterpart, although with fewer options. If you haven't already, please familiarize yourself with the Content Delivery API before reading this article.
The Media Delivery API specification is created to mimic that of the Content Delivery API. However, the default implementation of this specification is limited and does not support the entire specification.
Unlike the Content Delivery API, the Media Delivery API does not feature an extension model for querying.
The reasoning behind is that third-party media systems might support a complete implementation of the specification. If the demand rises, the default implementation might eventually cover the entire specification.
To use the Media Delivery API you must first enable it. Even if the Content Delivery API is enabled, the Media Delivery API remains disabled by default.
The Media Delivery API is enabled by adding the Media
section to the DeliveryApi
configuration in appsettings.json
:
As this configuration sample illustrates, it is possible to restrict public access to media independently from content. As with the Content Delivery API, media is publicly accessible by default when the Media Delivery API is enabled.
The Media
configuration can only become more restrictive than the DeliveryApi
configuration:
If DeliveryApi:Enabled
is false
, the DeliveryApi:Media:Enabled
configuration option has no effect. The Media Delivery API cannot be enabled on its own.
If DeliveryApi:PublicAccess
is false
, the DeliveryApi:Media:PublicAccess
configuration option has no effect. The Media Delivery API cannot be publicly available if the Content Delivery API is not.
The Media Delivery API can either be queried for a specific media item or a paged list of multiple items.
In the Media Delivery API, id
parameters always refer to media item keys (Guid
), not node ids (integer
).
GET
/umbraco/delivery/api/v1/media/item/{id}
Returns a single item.
GET
/umbraco/delivery/api/v1/media/item/{path}
Returns a single item.
GET
/umbraco/delivery/api/v1/media/item
Returns single or multiple items by id.
GET
/umbraco/delivery/api/v1/media
Returns single or multiple items.
Fetch a media item by its ID:
Fetch a media item inside a folder structure by its full path, and expand its author
property:
Fetch two media items by their ids:
Fetch the first 10 media items of type Image
at root level. Return the found items sorted by name ascending:
Fetch the first 5 media items inside a folder structure. Return only items of type Image
whose item names contain "size".
The Media Delivery API outputs the JSON structure outlined below to represent media items:
Item path
, createDate
, updateDate
, id
, name
, and mediaType
are always included in the response.
url
, extension
and the size in bytes
are included for all files (not for folders).
width
and height
(in pixels) are included for most images.
Depending on Umbraco Data Type configuration, focalPoint
and crops
are included for most images.
Additional editorial properties from the media type can be found in the properties
collection.
Name | Type | Description |
---|---|---|
Name | Type | Description |
---|---|---|
Name | Type | Description |
---|---|---|
Name | Type | Description |
---|---|---|
Name | Type | Description |
---|---|---|
Name | Type | Description |
---|---|---|
Name | Type | Description |
---|---|---|
Name | Type | Description |
---|---|---|
Name | Type | Description |
---|---|---|
Name | Type | Description |
---|---|---|
id*
String
GUID of the media item
expand
String
Which properties to expand in the response
Api-Key
String
Access token
path*
String
Path of the media item. The path is composed by the names of any ancestor folders and the name of the media item itself, separated by
/
.
expand
String
Which properties to expand in the response
Api-Key
String
Access token
id*
String Array
GUIDs of the media items
expand
String
Which properties to expand in the response
Api-Key
String
Access token
fetch*
String
Structural query string option (e.g. ancestors
, children
, descendants
).
Please note: The default API implementation only supports children
.
filter
String Array
Filtering query string options (e.g. mediaType
, name
)
sort
String Array
Sorting query string options (e.g. createDate
, name
, sortOrder
, updateDate
)
skip
Integer
Amount of items to skip
take
Integer
Amount of items to take
expand
String
Which properties to expand in the response
Api-Key
String
Access token