From 709cdd8c1c6a24befad1aceab0db36c7ac78344d Mon Sep 17 00:00:00 2001 From: kjac Date: Fri, 10 Nov 2023 12:37:25 +0100 Subject: [PATCH 1/8] Docs for Delivery API V2 incl. new property expansion and limiting --- 13/umbraco-cms/SUMMARY.md | 10 + .../reference/content-delivery-api/README.md | 192 +-- .../custom-property-editors-support.md | 14 +- .../extension-api-for-querying.md | 10 +- .../media-delivery-api.md | 36 +- .../property-expansion-and-limiting.md | 1374 +++++++++++++++++ 6 files changed, 1487 insertions(+), 149 deletions(-) create mode 100644 13/umbraco-cms/reference/content-delivery-api/property-expansion-and-limiting.md diff --git a/13/umbraco-cms/SUMMARY.md b/13/umbraco-cms/SUMMARY.md index 1ab5a1f4bee..b5ed76bf637 100644 --- a/13/umbraco-cms/SUMMARY.md +++ b/13/umbraco-cms/SUMMARY.md @@ -14,6 +14,16 @@ * [Upgrade your project](fundamentals/setup/upgrading/README.md) * [Version Specific Upgrades](fundamentals/setup/upgrading/version-specific/README.md) +## Reference + +* [Content Delivery API](reference/content-delivery-api/README.md) + * [Custom property editors support](reference/content-delivery-api/custom-property-editors-support.md) + * [Extension API for querying](reference/content-delivery-api/extension-api-for-querying.md) + * [Media Delivery API](reference/content-delivery-api/media-delivery-api.md) + * [Protected content in the Delivery API](reference/content-delivery-api/protected-content-in-the-delivery-api.md) + * [Additional preview environments support](reference/content-delivery-api/additional-preview-environments-support.md) + * [Property expansion and limiting](reference/content-delivery-api/property-expansion-and-limiting.md) + ## Tutorials diff --git a/13/umbraco-cms/reference/content-delivery-api/README.md b/13/umbraco-cms/reference/content-delivery-api/README.md index 6ae7fcde0a3..08d9fb73deb 100644 --- a/13/umbraco-cms/reference/content-delivery-api/README.md +++ b/13/umbraco-cms/reference/content-delivery-api/README.md @@ -180,7 +180,7 @@ This means that the content item resides under the `docs-portal` root node and c The start item can also be helpful through the `Start-Item` request header when obtaining content from the Delivery API. Supplying a root node `id` or `path` as the header value, allows you to specify which is the starting point for the requested content operation: ```http -GET /umbraco/delivery/api/v1/content/item/articles/2023/getting-started +GET /umbraco/delivery/api/v2/content/item/articles/2023/getting-started Start-Item: docs-portal ``` @@ -188,122 +188,23 @@ Start-Item: docs-portal
-Output expansion +Property expansion and limiting -**Output expansion** allows you to retrieve additional data about related content or media in the API output for a given content item. +Property expansion and limiting allows you to: +- Include properties from related content or media in the API output for a given content item. +- Limit the content properties in the API output. -By default, a content property that allows picking a different content item (like a content picker property) outputs a shallow representation of the item. That means, only the basic information about the picked item, without the item properties. However, with output expansion, it is possible to include the properties of the picked item in the API output. Similar shallow representation applies to media items, as well. +By default, a content property that allows picking a different content item (i.e. a content picker) outputs a "shallow" representation of the picked item. This means that the output only includes basic information about the picked item, without the item properties. -{% hint style="info" %} -Currently, output expansion allows you to retrieve one level of property data from the point of view of the requested content node. This means that you can expand the properties of the chosen content item, but not the properties of other related items within that item. -{% endhint %} - -This feature can be used when querying for both single and multiple content items by adding an `expand` parameter to the query. The value of this parameter can be either `"all"` to expand all properties of the requested content item or `"property:alias, alias, alias"` to expand specific ones. - -The following JSON snippet demonstrates the default output of a content item (without expanding any properties). - -**Request** - -```http -GET /umbraco/delivery/api/v1/content/item/9bdac0e9-66d8-4bfd-bba1-e954ed9c780d -``` - -**Response** - -{% code title="Shallow output for " %} -```json -{ - "name": "My post", - "createDate": "2023-05-11T00:05:31.878211", - "updateDate": "2023-05-15T11:25:53.912058", - "route": {... - }, - "id": "9bdac0e9-66d8-4bfd-bba1-e954ed9c780d", - "contentType": "blogpost1", - "properties": { - "title": "My post page", - "blogPostNumber": 11, - "bodyContent": "Congue, sollicitudin? Est fames maiores, sociis suspendisse et aliquet tristique excepturi, aliquam, nihil illum pretium penatibus exercitationem lacinia! Dolorem tempus convallis, nulla! Eius scelerisque voluptatum penatibus, dignissimos molestiae, soluta eum. Voluptatibus quod? Temporibus potenti voluptates dictumst? Cillum metus, nec asperiores? Impedit sit! Eum tellus cillum facilisis ullamco tempor? Sint nostrum luctus? Neque dictumst diam, minus? Itaque, minus, etiam dignissimos debitis occaecat aptent tempus! Praesent molestiae duis nihil recusandae, eius imperdiet aspernatur natus. Tempus mattis at architecto, augue, consequuntur ultricies eligendi, litora morbi ante nesciunt pretium laoreet quidem recusandae voluptates dapibus, iure sagittis donec ipsum mollit? Blanditiis! Laborum sit assumenda beatae.", - "linkedItem": { - "name": "Demo blog", - "createDate": "2023-05-11T00:26:52.591927", - "updateDate": "2023-05-16T12:43:41.339963", - "route": { - "path": "/demo-blog/", - "startItem": { - "id": "5d5ae914-9885-4ee0-a14b-0ab57f501a55", - "path": "demo-blog" - } - }, - "id": "5d5ae914-9885-4ee0-a14b-0ab57f501a55", - "contentType": "blog", - "properties": {} - } - }, - "cultures": {} -} -``` -{% endcode %} +If we apply property expansion to the content property, the properties of the picked item are included in the output. This functionality applies to media items and block editors, as well. -Below is an example of how an expanded representation might look for the `linkedItem` property that references another content item with properties `title` and `description`: +Property expansion can be applied to expanded properties too, thus obtaining nested property expansion. As a consequence the output grows in size, and this is where property limiting comes into the picture. -**Request** - -```http -GET /umbraco/delivery/api/v1/content/item/9bdac0e9-66d8-4bfd-bba1-e954ed9c780d?expand=property:linkedItem -``` - -**Response** - -{% code title="Expanded output for " %} -```json -{ - "name": "My post", - "createDate": "2023-05-11T00:05:31.878211", - "updateDate": "2023-05-15T11:25:53.912058", - "route": { - "path": "/my-post/", - "startItem": { - "id": "5d5ae914-9885-4ee0-a14b-0ab57f501a55", - "path": "demo-blog" - } - }, - "id": "9bdac0e9-66d8-4bfd-bba1-e954ed9c780d", - "contentType": "blogpost1", - "properties": { - "title": "My post page", - "blogPostNumber": 11, - "bodyContent": "Congue, sollicitudin? Est fames maiores, sociis suspendisse et aliquet tristique excepturi, aliquam, nihil illum pretium penatibus exercitationem lacinia! Dolorem tempus convallis, nulla! Eius scelerisque voluptatum penatibus, dignissimos molestiae, soluta eum. Voluptatibus quod? Temporibus potenti voluptates dictumst? Cillum metus, nec asperiores? Impedit sit! Eum tellus cillum facilisis ullamco tempor? Sint nostrum luctus? Neque dictumst diam, minus? Itaque, minus, etiam dignissimos debitis occaecat aptent tempus! Praesent molestiae duis nihil recusandae, eius imperdiet aspernatur natus. Tempus mattis at architecto, augue, consequuntur ultricies eligendi, litora morbi ante nesciunt pretium laoreet quidem recusandae voluptates dapibus, iure sagittis donec ipsum mollit? Blanditiis! Laborum sit assumenda beatae.", - "linkedItem": { - "name": "Demo blog", - "createDate": "2023-05-11T00:26:52.591927", - "updateDate": "2023-05-16T12:43:41.339963", - "route": { - "path": "/demo-blog/", - "startItem": { - "id": "5d5ae914-9885-4ee0-a14b-0ab57f501a55", - "path": "demo-blog" - } - }, - "id": "5d5ae914-9885-4ee0-a14b-0ab57f501a55", - "contentType": "blog", - "properties": { - "title": "My demo blog", - "description": "Nihil incididunt dolores adipisicing placeat quisque imperdiet interdum autem, dolorem fusce rhoncus sunt leo inventore dictumst quisque, voluptatem, magni justo nostrud deserunt! Natus ipsam commodi dignissimos, sodales ab.\n" - } - } - }, - "cultures": {} -} -``` -{% endcode %} +By default, all content properties (including expanded properties) are included in the output. Property limiting allows us to specify exactly which content properties to include in the output. This means we can tailor the output specifically to concrete use cases without over-fetching. -The built-in property editors in Umbraco that allow for output expansion are: +Property expansion and limiting can be used when querying for both single and multiple content or media items. -* `Umbraco.ContentPicker` -* `Umbraco.MediaPicker` -* `Umbraco.MediaPicker3` -* `Umbraco.MultiNodeTreePicker` +Please refer to [this article](./property-expansion-and-limiting) for an in-depth explanation of this feature.
@@ -314,7 +215,7 @@ The built-in property editors in Umbraco that allow for output expansion are: Similar to the preview concept in Umbraco, the Delivery API allows for requesting unpublished content through its endpoints. This can be done by setting a `Preview` header to `true` in the API request. However, accessing draft versions of your content nodes requires authorization via an API key configured in `appsettings.json` file - `Umbraco:CMS:DeliveryApi:ApiKey` setting. To obtain preview data, you must add the `Api-Key` request header containing the configured API key to the appropriate endpoints, like: ```http -GET /umbraco/delivery/api/v1/content/item/11fb598b-5c51-4d1a-8f2e-0c7594361d15 +GET /umbraco/delivery/api/v2/content/item/11fb598b-5c51-4d1a-8f2e-0c7594361d15 Preview: true Api-Key: my-api-key ``` @@ -330,7 +231,7 @@ Draft content is not going to be included in the JSON response otherwise. If your content is available in multiple languages, the Delivery API can resolve localized content. When querying content by `id`, the `Accept-Language` header can be used to request variant content. ```http -GET /umbraco/delivery/api/v1/content/item/11fb598b-5c51-4d1a-8f2e-0c7594361d15 +GET /umbraco/delivery/api/v2/content/item/11fb598b-5c51-4d1a-8f2e-0c7594361d15 Accept-Language: en-US ``` @@ -346,7 +247,7 @@ The output produced by the Delivery API can either represent a specific content When referring to a specific content item in your API requests, the `id` parameter always refers to the item’s key (GUID) and not its integer node id. {% endhint %} -{% swagger method="get" path="/content/item/{id}" baseUrl="/umbraco/delivery/api/v1" summary="Gets a content item by id" %} +{% swagger method="get" path="/content/item/{id}" baseUrl="/umbraco/delivery/api/v2" summary="Gets a content item by id" %} {% swagger-description %} Returns a single item. {% endswagger-description %} @@ -375,6 +276,10 @@ URL segment or GUID of the root content item Which properties to expand and therefore include in the output if they refer to another piece of content {% endswagger-parameter %} +{% swagger-parameter in="query" name="fields" type="String" required="false" %} +Explicitly defines which properties that should be included in the response (by default all properties are included) +{% endswagger-parameter %} + {% swagger-response status="200: OK" description="Content item" %} {% endswagger-response %} @@ -388,7 +293,7 @@ Which properties to expand and therefore include in the output if they refer to {% endswagger-response %} {% endswagger %} -{% swagger method="get" path="/content/item/{path}" baseUrl="/umbraco/delivery/api/v1" summary="Gets a content item by route" %} +{% swagger method="get" path="/content/item/{path}" baseUrl="/umbraco/delivery/api/v2" summary="Gets a content item by route" %} {% swagger-description %} Returns a single item. {% endswagger-description %} @@ -417,6 +322,10 @@ URL segment or GUID of the root content item Which properties to expand and therefore include in the output if they refer to another piece of content {% endswagger-parameter %} +{% swagger-parameter in="query" name="fields" type="String" required="false" %} +Explicitly defines which properties that should be included in the response (by default all properties are included) +{% endswagger-parameter %} + {% swagger-response status="200: OK" description="Content item" %} {% endswagger-response %} @@ -430,7 +339,7 @@ Which properties to expand and therefore include in the output if they refer to {% endswagger-response %} {% endswagger %} -{% swagger method="get" path="/content/item" baseUrl="/umbraco/delivery/api/v1" summary="Gets content item(s) by id" %} +{% swagger method="get" path="/content/items" baseUrl="/umbraco/delivery/api/v2" summary="Gets content item(s) by id" %} {% swagger-description %} Returns single or multiple items by id. {% endswagger-description %} @@ -459,6 +368,10 @@ URL segment or GUID of the root content item Which properties to expand in the response {% endswagger-parameter %} +{% swagger-parameter in="query" name="fields" type="String" required="false" %} +Explicitly defines which properties that should be included in the response (by default all properties are included) +{% endswagger-parameter %} + {% swagger-response status="200: OK" description="List of content items" %} {% endswagger-response %} @@ -468,7 +381,7 @@ Which properties to expand in the response {% endswagger-response %} {% endswagger %} -{% swagger method="get" path="/content" baseUrl="/umbraco/delivery/api/v1" summary="Gets content item(s) from a query" %} +{% swagger method="get" path="/content" baseUrl="/umbraco/delivery/api/v2" summary="Gets content item(s) from a query" %} {% swagger-description %} Returns single or multiple items. {% endswagger-description %} @@ -513,6 +426,10 @@ URL segment or GUID of the root content item Which properties to expand and therefore include in the output if they refer to another piece of content {% endswagger-parameter %} +{% swagger-parameter in="query" name="fields" type="String" required="false" %} +Explicitly defines which properties that should be included in the response (by default all properties are included) +{% endswagger-parameter %} + {% swagger-response status="200: OK" description="Paginated list of content items" %} {% endswagger-response %} @@ -539,21 +456,42 @@ You can extend the built-in selector, filter, and sorting capabilities of the De {% tabs %} {% tab title="expand" %} {% hint style="info" %} -Refer to the [Output expansion](./#output-expansion) concept for more information about the benefits of this parameter. +Refer to the [Property expansion and limiting](./#property-expansion-and-limiting) concept for more information about this parameter. {% endhint %} -**`?expand=all`**\ +**`?expand=properties[$all]`**\ All expandable properties on the retrieved content item will be expanded. -**`?expand=property:alias1`**\ +**`?expand=properties[alias1]`**\ A specific expandable property with the property alias _`alias1`_ will be expanded. -**`?expand=property:alias1,alias2,alias3`**\ +**`?expand=properties[alias1,alias2,alias3]`**\ Multiple expandable properties with the specified property aliases will be expanded. + +**`?expand=properties[alias1[properties[nestedAlias1,nestedAlias2]]]`**\ +The property with the property alias _`alias1`_ will be expanded, and likewise the properties _`nestedAlias1`_ and _`nestedAlias2`_ of the expanded _`alias1`_ property. +{% endtab %} + +{% tab title="fields" %} +{% hint style="info" %} +Refer to the [Property expansion and limiting](./#property-expansion-and-limiting) concept for more information about this parameter. +{% endhint %} + +**`?fields=properties[$all]`**\ +Includes all properties on the retrieved content item in the output. + +**`?fields=properties[alias1]`**\ +Includes only the property with the property alias _`alias1`_ in the output. + +**`?fields=properties[alias1,alias2,alias3]`**\ +Includes only the properties with the specified property aliases in the output. + +**`?fields=properties[alias1[properties[nestedAlias1,nestedAlias2]]]`**\ +Includes only the property with the property alias _`alias1`_ in the output. If this property is expanded, only the properties _`nestedAlias1`_ and _`nestedAlias2`_ of the expanded _`alias1`_ property are included in the output. {% endtab %} {% tab title="fetch" %} -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: +To query content items based on their structure, you can apply a selector option to the `/umbraco/delivery/api/v2/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. @@ -573,12 +511,12 @@ For example, the following API call will attempt to retrieve all the content ite **Request** ```http -GET /umbraco/delivery/api/v1/content?fetch=children:dc1f43da-49c6-4d87-b104-a5864eca8152 +GET /umbraco/delivery/api/v2/content?fetch=children:dc1f43da-49c6-4d87-b104-a5864eca8152 ``` {% endtab %} {% tab title="filter" %} -The `filter` query parameter allows you to specify one or more filters that must match in order for a content item to be included in the response. The API provides two built-in filters that you can use right away with the `/umbraco/delivery/api/v1/content` endpoint: +The `filter` query parameter allows you to specify one or more filters that must match in order for a content item to be included in the response. The API provides two built-in filters that you can use right away with the `/umbraco/delivery/api/v2/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. @@ -593,7 +531,7 @@ Multiple filters can be applied to the same request in addition to other query p **Request** ```http -GET /umbraco/delivery/api/v1/content?filter=contentType:article&filter=name:guide&skip=0&take=10 +GET /umbraco/delivery/api/v2/content?filter=contentType:article&filter=name:guide&skip=0&take=10 ``` {% endtab %} @@ -615,12 +553,12 @@ An option to sort the results based on the sort order of the content item in eit **`?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: +Different sorting options can be combined for the `/umbraco/delivery/api/v2/content` endpoint, allowing for more advanced sorting functionality. Here is an example: **Request** ```http -GET /umbraco/delivery/api/v1/content?sort=name:asc&sort=createDate:asc +GET /umbraco/delivery/api/v2/content?sort=name:asc&sort=createDate:asc ``` {% endtab %} {% endtabs %} @@ -710,4 +648,4 @@ The Multinode Treepicker property editor, when configured for members, is also u 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. \ No newline at end of file +Alternatively the relevant content items can be republished. This will ensure that the changes are reflected, eliminating the need to rebuild the index. diff --git a/13/umbraco-cms/reference/content-delivery-api/custom-property-editors-support.md b/13/umbraco-cms/reference/content-delivery-api/custom-property-editors-support.md index dab5c50adf1..f777a94edb2 100644 --- a/13/umbraco-cms/reference/content-delivery-api/custom-property-editors-support.md +++ b/13/umbraco-cms/reference/content-delivery-api/custom-property-editors-support.md @@ -8,7 +8,7 @@ description: >- 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](./#output-expansion) for your custom property editors. +In this article, we'll look into how you can work with the `IDeliveryApiPropertyValueConverter` interface and implement custom [property expansion](./#property-expansion) for your custom property editors. ## Prerequisite @@ -124,7 +124,7 @@ The following example request shows how our custom implementation is reflected i **Request** ```http -GET /umbraco/delivery/api/v1/content/item/blog +GET /umbraco/delivery/api/v2/content/item/blog ``` **Response** @@ -153,11 +153,11 @@ GET /umbraco/delivery/api/v1/content/item/blog } ``` -## Output expansion support +## Property expansion support -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. +Property 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 property 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: +In our example, property expansion is implemented within `ConvertIntermediateToDeliveryApiObject()`. By considering the value of the `expanding` parameter, we can modify the `BuildDeliveryApiCustomPicker()` method as follows: ```csharp private DeliveryApiCustomPicker? BuildDeliveryApiCustomPicker(object inter, bool expanding) @@ -173,7 +173,7 @@ private DeliveryApiCustomPicker? BuildDeliveryApiCustomPicker(object inter, bool return null; } - // Output expansion support + // Property expansion support if (expanding == false) { return new DeliveryApiCustomPicker { Id = id }; @@ -199,7 +199,7 @@ To see the expanded output in the API response, we need to add the `expand` quer **Request** ```http -GET /umbraco/delivery/api/v1/content/item/blog?expand=property:pickedItem +GET /umbraco/delivery/api/v2/content/item/blog?expand=property:pickedItem ``` **Response** diff --git a/13/umbraco-cms/reference/content-delivery-api/extension-api-for-querying.md b/13/umbraco-cms/reference/content-delivery-api/extension-api-for-querying.md index a8ab959b489..9138a005ed6 100644 --- a/13/umbraco-cms/reference/content-delivery-api/extension-api-for-querying.md +++ b/13/umbraco-cms/reference/content-delivery-api/extension-api-for-querying.md @@ -6,7 +6,7 @@ description: >- # Extension API for querying -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](./#endpoints) section. +The Delivery API allows you to retrieve multiple items by utilizing the `/umbraco/delivery/api/v2/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](./#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. @@ -17,7 +17,7 @@ In this article, we'll explore creating custom selecting, filtering, and sorting 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: ```http -GET /umbraco/delivery/api/v1/content?fetch=xxx&filter=yyy&filter=zzz&sort=aaa&sort=bbb +GET /umbraco/delivery/api/v2/content?fetch=xxx&filter=yyy&filter=zzz&sort=aaa&sort=bbb ``` The placeholders in the example (`xxx`, `yyy`, etc.) represent the values that each query option evaluates in order to determine the suitable query handler. @@ -114,7 +114,7 @@ Since our custom query option modifies the index structure, we will need to rebu **Request** ```http -GET /umbraco/delivery/api/v1/content?fetch=featuredAuthors +GET /umbraco/delivery/api/v2/content?fetch=featuredAuthors ``` **Response** @@ -139,7 +139,7 @@ This filter allows specifying the desired author(s) by their key (`Guid`) in an **Request** ```http -GET /umbraco/delivery/api/v1/content?filter=author:7c630f15-8d93-4980-a0fc-027314dc827a,75380b4f-6d6e-47a1-9222-975cdfb2ac5f +GET /umbraco/delivery/api/v2/content?filter=author:7c630f15-8d93-4980-a0fc-027314dc827a,75380b4f-6d6e-47a1-9222-975cdfb2ac5f ``` The response will include the blog posts associated with the provided authors, enabling us to retrieve only the relevant results from the API. @@ -317,7 +317,7 @@ In the following example request, we also apply the author filter to retrieve on **Request** ```http -GET /umbraco/delivery/api/v1/content?filter=author:7c630f15-8d93-4980-a0fc-027314dc827a&sort=publishDate:asc +GET /umbraco/delivery/api/v2/content?filter=author:7c630f15-8d93-4980-a0fc-027314dc827a&sort=publishDate:asc ``` **Response** diff --git a/13/umbraco-cms/reference/content-delivery-api/media-delivery-api.md b/13/umbraco-cms/reference/content-delivery-api/media-delivery-api.md index 288d2c00c1f..22a6cf664b1 100644 --- a/13/umbraco-cms/reference/content-delivery-api/media-delivery-api.md +++ b/13/umbraco-cms/reference/content-delivery-api/media-delivery-api.md @@ -56,7 +56,7 @@ The Media Delivery API can either be queried for a specific media item or a page In the Media Delivery API, `id` parameters always refer to media item keys (`Guid`), not node ids (`integer`). {% endhint %} -{% swagger method="get" path="/media/item/{id}" baseUrl="/umbraco/delivery/api/v1" summary="Gets a media item by id" %} +{% swagger method="get" path="/media/item/{id}" baseUrl="/umbraco/delivery/api/v2" summary="Gets a media item by id" %} {% swagger-description %} Returns a single item. {% endswagger-description %} @@ -73,6 +73,10 @@ Access token Which properties to expand in the response {% endswagger-parameter %} +{% swagger-parameter in="query" name="fields" type="String" required="false" %} +Explicitly defines which properties that should be included in the response (by default all properties are included) +{% endswagger-parameter %} + {% swagger-response status="200: OK" description="Media item" %} {% endswagger-response %} @@ -86,13 +90,13 @@ Which properties to expand in the response {% endswagger-response %} {% endswagger %} -{% swagger method="get" path="/media/item/{path}" baseUrl="/umbraco/delivery/api/v1" summary="Gets a media item by path" %} +{% swagger method="get" path="/media/item/{path}" baseUrl="/umbraco/delivery/api/v2" summary="Gets a media item by path" %} {% swagger-description %} Returns a single item. {% endswagger-description %} {% swagger-parameter in="path" name="path" type="String" required="true" %} -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 +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 `/` @@ -107,6 +111,10 @@ Access token Which properties to expand in the response {% endswagger-parameter %} +{% swagger-parameter in="query" name="fields" type="String" required="false" %} +Explicitly defines which properties that should be included in the response (by default all properties are included) +{% endswagger-parameter %} + {% swagger-response status="200: OK" description="Media item" %} {% endswagger-response %} @@ -120,7 +128,7 @@ Which properties to expand in the response {% endswagger-response %} {% endswagger %} -{% swagger method="get" path="/media/item" baseUrl="/umbraco/delivery/api/v1" summary="Gets media item(s) by id" %} +{% swagger method="get" path="/media/item" baseUrl="/umbraco/delivery/api/v2" summary="Gets media item(s) by id" %} {% swagger-description %} Returns single or multiple items by id. {% endswagger-description %} @@ -137,6 +145,10 @@ Access token Which properties to expand in the response {% endswagger-parameter %} +{% swagger-parameter in="query" name="fields" type="String" required="false" %} +Explicitly defines which properties that should be included in the response (by default all properties are included) +{% endswagger-parameter %} + {% swagger-response status="200: OK" description="List of media items" %} {% endswagger-response %} @@ -146,7 +158,7 @@ Which properties to expand in the response {% endswagger-response %} {% endswagger %} -{% swagger method="get" path="/media" baseUrl="/umbraco/delivery/api/v1" summary="Gets media item(s) from a query" %} +{% swagger method="get" path="/media" baseUrl="/umbraco/delivery/api/v2" summary="Gets media item(s) from a query" %} {% swagger-description %} Returns single or multiple items. {% endswagger-description %} @@ -181,6 +193,10 @@ Access token Which properties to expand in the response {% endswagger-parameter %} +{% swagger-parameter in="query" name="fields" type="String" required="false" %} +Explicitly defines which properties that should be included in the response (by default all properties are included) +{% endswagger-parameter %} + {% swagger-response status="200: OK" description="Paginated list of media items" %} {% endswagger-response %} @@ -195,31 +211,31 @@ Which properties to expand in the response Fetch a media item by its ID: ```http -GET /umbraco/delivery/api/v1/media/item/3fa85f64-5717-4562-b3fc-2c963f66afa6 +GET /umbraco/delivery/api/v2/media/item/3fa85f64-5717-4562-b3fc-2c963f66afa6 ``` Fetch a media item inside a folder structure by its full path, and expand its `author` property: ```http -GET /umbraco/delivery/api/v1/media/item/root level folder/child folder/media item name/&expand=property:author +GET /umbraco/delivery/api/v2/media/item/root level folder/child folder/media item name/&expand=property:author ``` Fetch two media items by their ids: ```http -GET /umbraco/delivery/api/v1/media/item?id=11178b4f-f8e2-4686-9697-6d990851a081&id=7cd00706-de93-4db8-8fc2-4b20e8419c30 +GET /umbraco/delivery/api/v2/media/item?id=11178b4f-f8e2-4686-9697-6d990851a081&id=7cd00706-de93-4db8-8fc2-4b20e8419c30 ``` Fetch the first 10 media items of type `Image` at root level. Return the found items sorted by name ascending: ```http -GET /umbraco/delivery/api/v1/media?fetch=children:/&filter=mediaType:Image&sort=name:asc&skip=0&take=10 +GET /umbraco/delivery/api/v2/media?fetch=children:/&filter=mediaType:Image&sort=name:asc&skip=0&take=10 ``` Fetch the first 5 media items inside a folder structure. Return only items of type `Image` whose item names contain "size". ```http -GET /umbraco/delivery/api/v1/media?fetch=children:/root level folder/child folder/&filter=mediaType:Image&filter=name:size&skip=0&take=5 +GET /umbraco/delivery/api/v2/media?fetch=children:/root level folder/child folder/&filter=mediaType:Image&filter=name:size&skip=0&take=5 ``` ## Media item JSON structure diff --git a/13/umbraco-cms/reference/content-delivery-api/property-expansion-and-limiting.md b/13/umbraco-cms/reference/content-delivery-api/property-expansion-and-limiting.md new file mode 100644 index 00000000000..3e39fdef7c0 --- /dev/null +++ b/13/umbraco-cms/reference/content-delivery-api/property-expansion-and-limiting.md @@ -0,0 +1,1374 @@ +--- +description: Using property expansion and limiting to shape the Delivery API output. +--- + +# Property expansion and limiting + +{% hint style="info" %} +This article explains the mechanics of property expansion and limiting in depth. If you haven't already, please read the [Getting started](https://docs.umbraco.com/umbraco-cms/reference/content-delivery-api) article first - in particular the "Concepts" section. +{% endhint %} + +Property expansion and limiting applies only to select property editors. The following built-in property editors in Umbraco support expansion and limiting: + +- Picker editors + - Content Picker + - Media Picker + - Media Picker (legacy) + - Multinode Treepicker +- Block based editors + - Block List + - Block Grid + - Rich Text Editor (with blocks) + +{% hint style="info" %} +When working with property expansion and limiting in API queries, there are two rules of thumb to keep in mind: + +1. Expandable properties are _not_ expanded by default. They must be expanded explicitly. +2. All properties are included in the API output by default. We can apply limiting to limit the included properties. +{% endhint %} + +## Working with picker editors + +In the following we will be querying a content tree with blog posts and blog authors: + +- All blog posts are located under a root content item called "Posts". +- All authors are located under a root content item called "Authors". + +The blog post content type (`post`) contains two properties that support expansion and limiting: + +- `author`: A content picker for picking the author of the post. +- `coverImage`: A media picker for picking an image for the post. + +The author content type (`author`) contains a single property that support expansion and limiting: + +- `picture`: A media picker for picking a picture of the author. + +When fetching a blog post, the `author` and `coverImage` properties are returned in their un-expanded representation by default. This representation does not contain any property data; the `properties` collections of `author` and `coverImage` are empty: + +**Request** + +```http +GET /umbraco/delivery/api/v2/content/item/set-your-content-free/ +Start-Item: posts +``` + +**Response** + +{% code title="Default Delivery API output" %} +```json +{ + "contentType": "post", + "name": "Set your content free", + "createDate": "2023-08-14T08:35:58.8397754", + "updateDate": "2023-08-14T08:54:41.8018872", + "route": { + "path": "/set-your-content-free/", + "startItem": { + "id": "d88fefc3-da04-493d-9533-294a7264b27f", + "path": "posts" + } + }, + "id": "5de65f2e-055e-4e6a-adc3-edb340dcd2e8", + "properties": { + "author": { + "contentType": "author", + "name": "Go Fish", + "createDate": "2023-08-14T08:35:58.9245488", + "updateDate": "2023-11-06T14:21:22.2160133", + "route": { + "path": "/go-fish/", + "startItem": { + "id": "a0e500e2-295e-43e0-ab85-71a44e690c31", + "path": "authors" + } + }, + "id": "f5baeee9-fe8d-4e54-b5c8-fc0373df61cf", + "properties": {} + }, + "coverImage": [ + { + "focalPoint": null, + "crops": [], + "id": "dbb62958-de31-465f-bdbe-5e9079b54b25", + "name": "Arrows", + "mediaType": "Image", + "url": "/media/lyulnwzr/arrows.png", + "extension": "png", + "width": 1080, + "height": 530, + "bytes": 24069, + "properties": {} + } + ], + "excerpt": "Fusce ut mauris ornare, mollis felis ac, convallis neque. Aenean eu tortor ac dui dictum lacinia. Aliquam erat volutpat. Sed malesuada congue imperdiet. Sed dictum aliquam velit. Nunc non nibh dignissim, consequat quam ac, mattis turpis. ", + "content": { + "markup": "

Maecenas consectetur tellus ut aliquet gravida. Mauris at tortor et tellus ultrices tempor vitae nec sapien. Etiam in luctus justo. Praesent rutrum turpis nec maximus congue. Sed sed convallis dui, ut luctus magna. Cras eget diam et sem consequat dictum ut in diam.

\n

Donec feugiat, quam ut varius ultricies, erat purus luctus ex, at sagittis tellus ante vel orci. Nunc dapibus purus feugiat, rhoncus est non, feugiat metus. Vivamus vulputate mauris id urna ultrices sagittis non ut est. Mauris mauris diam, interdum nec lectus et, vehicula faucibus risus. Etiam varius sem erat, nec venenatis elit pellentesque sed. Interdum et malesuada fames ac ante ipsum primis in faucibus.

\n

Sed nibh arcu, feugiat eu arcu sed, posuere lacinia urna. Phasellus interdum euismod sagittis. Etiam vel erat sed erat posuere placerat. Sed pulvinar tincidunt suscipit.

\n

Curabitur molestie turpis elit, vitae bibendum mi convallis a. Etiam convallis, massa vitae sagittis consectetur, lacus odio condimentum felis, ac congue ligula odio eu tortor. Proin dignissim sit amet eros non lobortis. Sed blandit dolor id magna pulvinar auctor. Maecenas sed mi vel arcu pretium sodales in quis urna. Nunc lectus nunc, posuere efficitur dignissim congue, mollis at orci.

", + "blocks": [] + }, + "tags": [ + "Content", + "Awesome" + ] + }, + "cultures": {} +} +``` +{% endcode %} + +If we want to show the author picture when rendering the blog post, we need to _expand_ the `author` property. By expanding the property, the author properties (including `picture`) are included in the output. We can achieve this by appending the `expand` parameter to our request. + +The `expand` parameter syntax is as follows: + +`expand=properties[propertyAlias1,propertyAlias2,propertyAlias3]` + +Within the `properties` part of the `expand` parameter we can list the aliases of the properties we wish to expand. If we want to expand all expandable properties, we can use the operator `$all` instead: + +`expand=properties[$all]` + +**Request** + +```http +GET /umbraco/delivery/api/v2/content/item/set-your-content-free/ + ?expand=properties[author] +Start-Item: posts +``` + +**Response** + +{% code title="Delivery API output with property expansion" %} +```json +{ + "contentType": "post", + "name": "Set your content free", + "createDate": "2023-08-14T08:35:58.8397754", + "updateDate": "2023-08-14T08:54:41.8018872", + "route": { + "path": "/set-your-content-free/", + "startItem": { + "id": "d88fefc3-da04-493d-9533-294a7264b27f", + "path": "posts" + } + }, + "id": "5de65f2e-055e-4e6a-adc3-edb340dcd2e8", + "properties": { + "author": { + "contentType": "author", + "name": "Go Fish", + "createDate": "2023-08-14T08:35:58.9245488", + "updateDate": "2023-11-06T14:21:22.2160133", + "route": { + "path": "/go-fish/", + "startItem": { + "id": "a0e500e2-295e-43e0-ab85-71a44e690c31", + "path": "authors" + } + }, + "id": "f5baeee9-fe8d-4e54-b5c8-fc0373df61cf", + "properties": { + "picture": [ + { + "focalPoint": null, + "crops": [], + "id": "598c8ce5-1323-4926-98a4-0f3a395dae2d", + "name": "Fishtank", + "mediaType": "Image", + "url": "/media/2ogiywjd/fishtank.png", + "extension": "png", + "width": 1080, + "height": 1080, + "bytes": 26941, + "properties": {} + } + ], + "biography": "Cras fermentum enim vitae varius tristique. Suspendisse tempor quis lacus vitae facilisis. Ut eget mauris tempus dui pulvinar egestas vel eget nibh.\n\nDonec hendrerit sem eu diam sodales luctus non sed urna. Ut sapien ex, imperdiet non eleifend nec, venenatis et purus. Integer tincidunt cursus cursus.\n\nSuspendisse euismod sem nisi, aliquam dignissim sem dictum non. Ut et ex lacus. Fusce ac nisi mattis, ultrices nibh ac, facilisis leo. Aliquam faucibus, elit eu posuere scelerisque, mi enim accumsan lorem, quis rhoncus libero massa quis ligula.", + "dateOfBirth": "1996-04-04T00:00:00Z" + } + }, + "coverImage": [ + { + "focalPoint": null, + "crops": [], + "id": "dbb62958-de31-465f-bdbe-5e9079b54b25", + "name": "Arrows", + "mediaType": "Image", + "url": "/media/lyulnwzr/arrows.png", + "extension": "png", + "width": 1080, + "height": 530, + "bytes": 24069, + "properties": {} + } + ], + "excerpt": "Fusce ut mauris ornare, mollis felis ac, convallis neque. Aenean eu tortor ac dui dictum lacinia. Aliquam erat volutpat. Sed malesuada congue imperdiet. Sed dictum aliquam velit. Nunc non nibh dignissim, consequat quam ac, mattis turpis. ", + "content": { + "markup": "

Maecenas consectetur tellus ut aliquet gravida. Mauris at tortor et tellus ultrices tempor vitae nec sapien. Etiam in luctus justo. Praesent rutrum turpis nec maximus congue. Sed sed convallis dui, ut luctus magna. Cras eget diam et sem consequat dictum ut in diam.

\n

Donec feugiat, quam ut varius ultricies, erat purus luctus ex, at sagittis tellus ante vel orci. Nunc dapibus purus feugiat, rhoncus est non, feugiat metus. Vivamus vulputate mauris id urna ultrices sagittis non ut est. Mauris mauris diam, interdum nec lectus et, vehicula faucibus risus. Etiam varius sem erat, nec venenatis elit pellentesque sed. Interdum et malesuada fames ac ante ipsum primis in faucibus.

\n

Sed nibh arcu, feugiat eu arcu sed, posuere lacinia urna. Phasellus interdum euismod sagittis. Etiam vel erat sed erat posuere placerat. Sed pulvinar tincidunt suscipit.

\n

Curabitur molestie turpis elit, vitae bibendum mi convallis a. Etiam convallis, massa vitae sagittis consectetur, lacus odio condimentum felis, ac congue ligula odio eu tortor. Proin dignissim sit amet eros non lobortis. Sed blandit dolor id magna pulvinar auctor. Maecenas sed mi vel arcu pretium sodales in quis urna. Nunc lectus nunc, posuere efficitur dignissim congue, mollis at orci.

\n

Aenean elit arcu, cursus sit amet vulputate eu, dignissim sit amet lorem. Nunc tempus rhoncus lorem, sit amet finibus mi scelerisque sollicitudin. Pellentesque auctor, nunc facilisis molestie ullamcorper, justo magna pellentesque dui, vel posuere est massa eget nibh. Sed dignissim eget purus vitae malesuada. Maecenas eu ultricies nunc. Sed porta pretium ligula, non auctor arcu blandit elementum. Nullam nibh metus, consequat non imperdiet et, scelerisque id urna. Vivamus mollis, dolor ac fringilla bibendum, leo turpis finibus libero, sit amet porttitor nunc magna non diam.

\n

Curabitur cursus ullamcorper mauris. Fusce porta turpis at metus fermentum, commodo rhoncus leo dignissim. Etiam eu eleifend elit, sit amet pulvinar nibh. In pharetra massa massa, sit amet convallis leo consectetur vitae. In id pharetra sapien, sit amet tincidunt enim.

\n

Duis velit lectus, mollis eu eros sed, dignissim scelerisque neque. Mauris blandit sit amet diam dignissim cursus.

\n

Integer ornare ultrices finibus. Nullam iaculis eget sapien in porttitor. Etiam sit amet viverra mauris. Vestibulum risus ligula, placerat eget tortor vel, mattis porta odio. Vestibulum non euismod lacus. Integer quis velit suscipit, commodo mi sed, rutrum metus. Donec auctor ex ut elit vehicula, quis tincidunt odio laoreet. Suspendisse pharetra sit amet ante quis consequat. Duis finibus pellentesque urna ac molestie.

", + "blocks": [] + }, + "tags": [ + "Content", + "Awesome" + ] + }, + "cultures": {} +} +``` +{% endcode %} + +Now we have the `picture` data in the `properties` collection of `author`. However, the rest of the author properties (`biography` and `dateOfBirth`) are also present in our output, so we are slightly over-fetching. We will take care of that later. + +First we need to get the alt texts of our images (the blog post `coverImage` and the author `picture`). The alt text in this case is a text string property (`altText`) on the media type. Fetching the alt texts is possible because property expansion can be performed both across multiple properties and in a nested fashion. + +For nested property expansion, the `expand` parameter syntax is as follows: + +`expand=properties[propertyAlias[properties[nestedPropertyAlias1,nestedPropertyAlias2]]]` + +Nested property expansion can also be combined with the `$all` operator: + +`expand=properties[$all[properties[nestedPropertyAlias1,nestedPropertyAlias2]]]` + +{% hint style="info" %} +There is no API limit to how "deep" the nesting can go. Eventually though, the total length of request URL may become a hard limit to the size of the query. +{% endhint %} + +Let's amend the `expand` parameter to accommodate expansion of the images: + +**Request** + +```http +GET /umbraco/delivery/api/v2/content/item/set-your-content-free/ + ?expand=properties[coverImage,author[properties[picture]]] +Start-Item: posts +``` + +**Response** + +{% code title="Delivery API output with nested property expansion" %} +```json +{ + "contentType": "post", + "name": "Set your content free", + "createDate": "2023-08-14T08:35:58.8397754", + "updateDate": "2023-08-14T08:54:41.8018872", + "route": { + "path": "/set-your-content-free/", + "startItem": { + "id": "d88fefc3-da04-493d-9533-294a7264b27f", + "path": "posts" + } + }, + "id": "5de65f2e-055e-4e6a-adc3-edb340dcd2e8", + "properties": { + "author": { + "contentType": "author", + "name": "Go Fish", + "createDate": "2023-08-14T08:35:58.9245488", + "updateDate": "2023-11-06T14:21:22.2160133", + "route": { + "path": "/go-fish/", + "startItem": { + "id": "a0e500e2-295e-43e0-ab85-71a44e690c31", + "path": "authors" + } + }, + "id": "f5baeee9-fe8d-4e54-b5c8-fc0373df61cf", + "properties": { + "picture": [ + { + "focalPoint": null, + "crops": [], + "id": "598c8ce5-1323-4926-98a4-0f3a395dae2d", + "name": "Fishtank", + "mediaType": "Image", + "url": "/media/2ogiywjd/fishtank.png", + "extension": "png", + "width": 1080, + "height": 1080, + "bytes": 26941, + "properties": { + "altText": "An image of the author Fishtank" + } + } + ], + "biography": "Cras fermentum enim vitae varius tristique. Suspendisse tempor quis lacus vitae facilisis. Ut eget mauris tempus dui pulvinar egestas vel eget nibh.\n\nDonec hendrerit sem eu diam sodales luctus non sed urna. Ut sapien ex, imperdiet non eleifend nec, venenatis et purus. Integer tincidunt cursus cursus.\n\nSuspendisse euismod sem nisi, aliquam dignissim sem dictum non. Ut et ex lacus. Fusce ac nisi mattis, ultrices nibh ac, facilisis leo. Aliquam faucibus, elit eu posuere scelerisque, mi enim accumsan lorem, quis rhoncus libero massa quis ligula.", + "dateOfBirth": "1996-04-04T00:00:00Z" + } + }, + "coverImage": [ + { + "focalPoint": null, + "crops": [], + "id": "dbb62958-de31-465f-bdbe-5e9079b54b25", + "name": "Arrows", + "mediaType": "Image", + "url": "/media/lyulnwzr/arrows.png", + "extension": "png", + "width": 1080, + "height": 530, + "bytes": 24069, + "properties": { + "altText": "Some arrows pointing in different directions (but generally upwards)" + } + } + ], + "excerpt": "Fusce ut mauris ornare, mollis felis ac, convallis neque. Aenean eu tortor ac dui dictum lacinia. Aliquam erat volutpat. Sed malesuada congue imperdiet. Sed dictum aliquam velit. Nunc non nibh dignissim, consequat quam ac, mattis turpis. ", + "content": { + "markup": "

Maecenas consectetur tellus ut aliquet gravida. Mauris at tortor et tellus ultrices tempor vitae nec sapien. Etiam in luctus justo. Praesent rutrum turpis nec maximus congue. Sed sed convallis dui, ut luctus magna. Cras eget diam et sem consequat dictum ut in diam.

\n

Donec feugiat, quam ut varius ultricies, erat purus luctus ex, at sagittis tellus ante vel orci. Nunc dapibus purus feugiat, rhoncus est non, feugiat metus. Vivamus vulputate mauris id urna ultrices sagittis non ut est. Mauris mauris diam, interdum nec lectus et, vehicula faucibus risus. Etiam varius sem erat, nec venenatis elit pellentesque sed. Interdum et malesuada fames ac ante ipsum primis in faucibus.

\n

Sed nibh arcu, feugiat eu arcu sed, posuere lacinia urna. Phasellus interdum euismod sagittis. Etiam vel erat sed erat posuere placerat. Sed pulvinar tincidunt suscipit.

\n

Curabitur molestie turpis elit, vitae bibendum mi convallis a. Etiam convallis, massa vitae sagittis consectetur, lacus odio condimentum felis, ac congue ligula odio eu tortor. Proin dignissim sit amet eros non lobortis. Sed blandit dolor id magna pulvinar auctor. Maecenas sed mi vel arcu pretium sodales in quis urna. Nunc lectus nunc, posuere efficitur dignissim congue, mollis at orci.

\n

Aenean elit arcu, cursus sit amet vulputate eu, dignissim sit amet lorem. Nunc tempus rhoncus lorem, sit amet finibus mi scelerisque sollicitudin. Pellentesque auctor, nunc facilisis molestie ullamcorper, justo magna pellentesque dui, vel posuere est massa eget nibh. Sed dignissim eget purus vitae malesuada. Maecenas eu ultricies nunc. Sed porta pretium ligula, non auctor arcu blandit elementum. Nullam nibh metus, consequat non imperdiet et, scelerisque id urna. Vivamus mollis, dolor ac fringilla bibendum, leo turpis finibus libero, sit amet porttitor nunc magna non diam.

\n

Curabitur cursus ullamcorper mauris. Fusce porta turpis at metus fermentum, commodo rhoncus leo dignissim. Etiam eu eleifend elit, sit amet pulvinar nibh. In pharetra massa massa, sit amet convallis leo consectetur vitae. In id pharetra sapien, sit amet tincidunt enim.

\n

Duis velit lectus, mollis eu eros sed, dignissim scelerisque neque. Mauris blandit sit amet diam dignissim cursus.

\n

Integer ornare ultrices finibus. Nullam iaculis eget sapien in porttitor. Etiam sit amet viverra mauris. Vestibulum risus ligula, placerat eget tortor vel, mattis porta odio. Vestibulum non euismod lacus. Integer quis velit suscipit, commodo mi sed, rutrum metus. Donec auctor ex ut elit vehicula, quis tincidunt odio laoreet. Suspendisse pharetra sit amet ante quis consequat. Duis finibus pellentesque urna ac molestie.

", + "blocks": [] + }, + "tags": [ + "Content", + "Awesome" + ] + }, + "cultures": {} +} +``` +{% endcode %} + +As mentioned above we are slightly over-fetching. We don't need all the author data - we are only interested in the author `picture`. To fix this we can apply property limiting by adding the `fields` parameter to our request. + +The `fields` parameter allows us to limit the properties in the output to only those specified. The parameter uses the same syntax as the `expand` parameter. + +Our ideal blog post output contains: + +- All the properties of the blog post, including the `altText` of the post `coverImage`. +- Only the `picture` property of `author`, including the `altText` of the author `picture`. + +As with property expansion we can use the `$all` operator in the `fields` parameter. This will include everything at any given query level. We'll use this to include all the blog post properties in the output without having to specify each property explicitly: + +**Request** + +```http +GET /umbraco/delivery/api/v2/content/item/set-your-content-free/ + ?expand=properties[coverImage,author[properties[picture]]] + &fields=properties[$all[properties[altText,picture[properties[altText]]]]] +Start-Item: posts +``` + +**Response** + +{% code title="Delivery API output with property expansion and limiting" %} +```json +{ + "contentType": "post", + "name": "Set your content free", + "createDate": "2023-08-14T08:35:58.8397754", + "updateDate": "2023-08-14T08:54:41.8018872", + "route": { + "path": "/set-your-content-free/", + "startItem": { + "id": "d88fefc3-da04-493d-9533-294a7264b27f", + "path": "posts" + } + }, + "id": "5de65f2e-055e-4e6a-adc3-edb340dcd2e8", + "properties": { + "author": { + "contentType": "author", + "name": "Go Fish", + "createDate": "2023-08-14T08:35:58.9245488", + "updateDate": "2023-11-06T14:21:22.2160133", + "route": { + "path": "/go-fish/", + "startItem": { + "id": "a0e500e2-295e-43e0-ab85-71a44e690c31", + "path": "authors" + } + }, + "id": "f5baeee9-fe8d-4e54-b5c8-fc0373df61cf", + "properties": { + "picture": [ + { + "focalPoint": null, + "crops": [], + "id": "598c8ce5-1323-4926-98a4-0f3a395dae2d", + "name": "Fishtank", + "mediaType": "Image", + "url": "/media/2ogiywjd/fishtank.png", + "extension": "png", + "width": 1080, + "height": 1080, + "bytes": 26941, + "properties": { + "altText": "An image of the author Fishtank" + } + } + ] + } + }, + "coverImage": [ + { + "focalPoint": null, + "crops": [], + "id": "dbb62958-de31-465f-bdbe-5e9079b54b25", + "name": "Arrows", + "mediaType": "Image", + "url": "/media/lyulnwzr/arrows.png", + "extension": "png", + "width": 1080, + "height": 530, + "bytes": 24069, + "properties": { + "altText": "Some arrows pointing in different directions (but generally upwards)" + } + } + ], + "excerpt": "Fusce ut mauris ornare, mollis felis ac, convallis neque. Aenean eu tortor ac dui dictum lacinia. Aliquam erat volutpat. Sed malesuada congue imperdiet. Sed dictum aliquam velit. Nunc non nibh dignissim, consequat quam ac, mattis turpis. ", + "content": { + "markup": "

Maecenas consectetur tellus ut aliquet gravida. Mauris at tortor et tellus ultrices tempor vitae nec sapien. Etiam in luctus justo. Praesent rutrum turpis nec maximus congue. Sed sed convallis dui, ut luctus magna. Cras eget diam et sem consequat dictum ut in diam.

\n

Donec feugiat, quam ut varius ultricies, erat purus luctus ex, at sagittis tellus ante vel orci. Nunc dapibus purus feugiat, rhoncus est non, feugiat metus. Vivamus vulputate mauris id urna ultrices sagittis non ut est. Mauris mauris diam, interdum nec lectus et, vehicula faucibus risus. Etiam varius sem erat, nec venenatis elit pellentesque sed. Interdum et malesuada fames ac ante ipsum primis in faucibus.

\n

Sed nibh arcu, feugiat eu arcu sed, posuere lacinia urna. Phasellus interdum euismod sagittis. Etiam vel erat sed erat posuere placerat. Sed pulvinar tincidunt suscipit.

\n

Curabitur molestie turpis elit, vitae bibendum mi convallis a. Etiam convallis, massa vitae sagittis consectetur, lacus odio condimentum felis, ac congue ligula odio eu tortor. Proin dignissim sit amet eros non lobortis. Sed blandit dolor id magna pulvinar auctor. Maecenas sed mi vel arcu pretium sodales in quis urna. Nunc lectus nunc, posuere efficitur dignissim congue, mollis at orci.

\n

Aenean elit arcu, cursus sit amet vulputate eu, dignissim sit amet lorem. Nunc tempus rhoncus lorem, sit amet finibus mi scelerisque sollicitudin. Pellentesque auctor, nunc facilisis molestie ullamcorper, justo magna pellentesque dui, vel posuere est massa eget nibh. Sed dignissim eget purus vitae malesuada. Maecenas eu ultricies nunc. Sed porta pretium ligula, non auctor arcu blandit elementum. Nullam nibh metus, consequat non imperdiet et, scelerisque id urna. Vivamus mollis, dolor ac fringilla bibendum, leo turpis finibus libero, sit amet porttitor nunc magna non diam.

\n

Curabitur cursus ullamcorper mauris. Fusce porta turpis at metus fermentum, commodo rhoncus leo dignissim. Etiam eu eleifend elit, sit amet pulvinar nibh. In pharetra massa massa, sit amet convallis leo consectetur vitae. In id pharetra sapien, sit amet tincidunt enim.

\n

Duis velit lectus, mollis eu eros sed, dignissim scelerisque neque. Mauris blandit sit amet diam dignissim cursus.

\n

Integer ornare ultrices finibus. Nullam iaculis eget sapien in porttitor. Etiam sit amet viverra mauris. Vestibulum risus ligula, placerat eget tortor vel, mattis porta odio. Vestibulum non euismod lacus. Integer quis velit suscipit, commodo mi sed, rutrum metus. Donec auctor ex ut elit vehicula, quis tincidunt odio laoreet. Suspendisse pharetra sit amet ante quis consequat. Duis finibus pellentesque urna ac molestie.

", + "blocks": [] + }, + "tags": [ + "Content", + "Awesome" + ] + }, + "cultures": {} +} +``` +{% endcode %} + +Now the API output contains only the properties we need to render the blog post. + +Property limiting is particularly useful when querying multiple items. For example, if we were building condensed list of blog posts, we likely wouldn't need the author data nor the blog post content. By applying limiting to a filtered query, we can tailor the API output specifically to this scenario: + +**Request** + +```http +GET /umbraco/delivery/api/v2/content/ + ?filter=contentType:post + &expand=properties[coverImage] + &fields=properties[excerpt,tags,coverImage[properties[altText]]] +Start-Item: posts +``` + +**Response** + +{% code title="Delivery API query output with property expansion and limiting" %} +```json +{ + "total": 6, + "items": [ + { + "contentType": "post", + "name": "Set your content free", + "createDate": "2023-08-14T08:35:58.8397754", + "updateDate": "2023-08-14T08:54:41.8018872", + "route": { + "path": "/set-your-content-free/", + "startItem": { + "id": "d88fefc3-da04-493d-9533-294a7264b27f", + "path": "posts" + } + }, + "id": "5de65f2e-055e-4e6a-adc3-edb340dcd2e8", + "properties": { + "coverImage": [ + { + "focalPoint": null, + "crops": [], + "id": "dbb62958-de31-465f-bdbe-5e9079b54b25", + "name": "Arrows", + "mediaType": "Image", + "url": "/media/lyulnwzr/arrows.png", + "extension": "png", + "width": 1080, + "height": 530, + "bytes": 24069, + "properties": { + "altText": "Some arrows pointing in different directions (but generally upwards)" + } + } + ], + "excerpt": "Fusce ut mauris ornare, mollis felis ac, convallis neque. Aenean eu tortor ac dui dictum lacinia. Aliquam erat volutpat. Sed malesuada congue imperdiet. Sed dictum aliquam velit. Nunc non nibh dignissim, consequat quam ac, mattis turpis. ", + "tags": [ + "Content", + "Awesome" + ] + }, + "cultures": {} + }, + { + "contentType": "post", + "name": "Building a community", + "createDate": "2023-08-14T08:35:58.6755792", + "updateDate": "2023-08-14T08:54:45.5526111", + "route": { + "path": "/building-a-community/", + "startItem": { + "id": "d88fefc3-da04-493d-9533-294a7264b27f", + "path": "posts" + } + }, + "id": "6e1bc040-f382-402c-ac56-3328d5f424c7", + "properties": { + "coverImage": [ + { + "focalPoint": null, + "crops": [], + "id": "9757a20c-3e98-49ef-8103-c7fa746856e7", + "name": "Community", + "mediaType": "Image", + "url": "/media/bkrfpf2y/community.png", + "extension": "png", + "width": 1080, + "height": 540, + "bytes": 25832, + "properties": { + "altText": "Two hands constructing a heart from coloured pieces" + } + } + ], + "excerpt": "Maecenas ipsum dui, lobortis non dui eleifend, dapibus bibendum dui. Pellentesque dolor felis, mollis nec diam eget, fermentum rutrum ipsum. Vestibulum condimentum urna id turpis tempus, id finibus sem facilisis. Nullam commodo felis quis ante posuere, dictum suscipit nisl suscipit.", + "tags": [ + "Community", + "Inspiration", + "Awesome" + ] + }, + "cultures": {} + }, + ... + ] +} +``` +{% endcode %} + +## Working with block based editors + +{% hint style="info" %} +If you are not familiar with block based editors, please refer to [this article](https://docs.umbraco.com/umbraco-cms/fundamentals/backoffice/property-editors/built-in-umbraco-property-editors/block-editor) for the general concepts of these. +{% endhint %} + +In the API output, a block has little value without its contained properties. Therefore, the content and settings properties of blocks are always included in the output. However, these properties are not expanded. As such, we can apply expansion and limiting to the contained properties. + +In the following we'll request different types of articles, all of which are located under a root content item called "Articles": + +- An article with a Block List property (`blockList`). +- An article a Block Grid property (`blockGrid`). +- An article with a Rich Text Editor property (`richText`). + +All these properties are configured with a "Featured Post" block which consists of: + +- A content model (`featuredPost`) that contains: + - `title`: A text string property. + - `post`: A content picker property that allows for picking a blog post. +- A settings model (`featuredPostSettings`) that contains: + - `backgroundColor`: An approved color property. + - `showTags`: A toggle property. + +The goal is once again to build a condensed list of blog posts. But this time we'll build the list from the "Featured Post" blocks within each block editor. + +To build the list we need the block `title`, the `coverImage` and `excerpt` from the picked post, and the `backgroundColor` from the block settings. Thus, we need to: + +- Expand the `post` property to retrieve the `altText` of the post `coverImage`. +- Limit both the block level properties and the nested `post` properties, as to only output the properties relevant for building the condensed list. + +For comparison, the samples show both the default output and the output with expansion and limiting applied. Notice that: + +- The `expand` and `fields` parameter syntax is the same for all editors, even though their rendered output is structurally different. +- The `expand` and `fields` parameters target both the content and settings parts of each block. + +### Block List + +Default output without expansion and limiting: + +**Request** + +```http +GET /umbraco/delivery/api/v2/content/item/article-with-block-list/ +Start-Item: articles +``` + +**Response** + +{% code title="Default Delivery API output" %} +```json +{ + "contentType": "articleWithBlockList", + "name": "Article with Block List", + "createDate": "2023-11-07T16:14:14.0913877", + "updateDate": "2023-11-07T16:30:58.0572288", + "route": { + "path": "/article-with-block-list/", + "startItem": { + "id": "5c8823f6-6442-4d04-9c14-f3411bd41aa8", + "path": "articles" + } + }, + "id": "c1d139df-c08d-4225-909f-f176d727dce6", + "properties": { + "blockList": { + "items": [ + { + "content": { + "contentType": "featuredPost", + "id": "4d5931fb-ad3c-4759-9824-777a2f3c6a85", + "properties": { + "title": "Free your content with the Delivery API", + "post": { + "contentType": "post", + "name": "Set your content free", + "createDate": "2023-08-14T08:35:58.8397754", + "updateDate": "2023-08-14T08:54:41.8018872", + "route": { + "path": "/set-your-content-free/", + "startItem": { + "id": "d88fefc3-da04-493d-9533-294a7264b27f", + "path": "posts" + } + }, + "id": "5de65f2e-055e-4e6a-adc3-edb340dcd2e8", + "properties": {} + } + } + }, + "settings": { + "contentType": "featuredPostSettings", + "id": "aff73d6b-cfd1-4471-92d8-68fc07fdb6fd", + "properties": { + "backgroundColor": "ce7e00", + "showTags": true + } + } + }, + { + "content": { + "contentType": "featuredPost", + "id": "76dabfff-7e86-4404-9a89-1b8274ac4f8e", + "properties": { + "title": "Community is key", + "post": { + "contentType": "post", + "name": "Building a community", + "createDate": "2023-08-14T08:35:58.6755792", + "updateDate": "2023-08-14T08:54:45.5526111", + "route": { + "path": "/building-a-community/", + "startItem": { + "id": "d88fefc3-da04-493d-9533-294a7264b27f", + "path": "posts" + } + }, + "id": "6e1bc040-f382-402c-ac56-3328d5f424c7", + "properties": {} + } + } + }, + "settings": { + "contentType": "featuredPostSettings", + "id": "175325ab-b4a0-489d-a196-c1cf32b41ca1", + "properties": { + "backgroundColor": "6fa8dc", + "showTags": false + } + } + } + ] + } + }, + "cultures": {} +} +``` +{% endcode %} + +Output with property expansion and limiting: + +**Request** + +```http +GET /umbraco/delivery/api/v2/content/item/article-with-block-list/ + ?expand=properties[blockList[properties[post[properties[coverImage]]]]] + &fields=properties[blockList[properties[title,post[properties[excerpt,coverImage]],backgroundColor]]] +Start-Item: articles +``` + +**Response** + +{% code title="Delivery API output with expansion and limiting" %} +```json +{ + "contentType": "articleWithBlockList", + "name": "Article with Block List", + "createDate": "2023-11-07T16:14:14.0913877", + "updateDate": "2023-11-07T16:34:45.6079582", + "route": { + "path": "/article-with-block-list/", + "startItem": { + "id": "5c8823f6-6442-4d04-9c14-f3411bd41aa8", + "path": "articles" + } + }, + "id": "c1d139df-c08d-4225-909f-f176d727dce6", + "properties": { + "blockList": { + "items": [ + { + "content": { + "contentType": "featuredPost", + "id": "4d5931fb-ad3c-4759-9824-777a2f3c6a85", + "properties": { + "title": "Free your content with the Delivery API", + "post": { + "contentType": "post", + "name": "Set your content free", + "createDate": "2023-08-14T08:35:58.8397754", + "updateDate": "2023-08-14T08:54:41.8018872", + "route": { + "path": "/set-your-content-free/", + "startItem": { + "id": "d88fefc3-da04-493d-9533-294a7264b27f", + "path": "posts" + } + }, + "id": "5de65f2e-055e-4e6a-adc3-edb340dcd2e8", + "properties": { + "coverImage": [ + { + "focalPoint": null, + "crops": [], + "id": "dbb62958-de31-465f-bdbe-5e9079b54b25", + "name": "Arrows", + "mediaType": "Image", + "url": "/media/lyulnwzr/arrows.png", + "extension": "png", + "width": 1080, + "height": 530, + "bytes": 24069, + "properties": { + "altText": "Some arrows pointing in different directions (but generally upwards)" + } + } + ], + "excerpt": "Fusce ut mauris ornare, mollis felis ac, convallis neque. Aenean eu tortor ac dui dictum lacinia. Aliquam erat volutpat. Sed malesuada congue imperdiet. Sed dictum aliquam velit. Nunc non nibh dignissim, consequat quam ac, mattis turpis. " + } + } + } + }, + "settings": { + "contentType": "featuredPostSettings", + "id": "aff73d6b-cfd1-4471-92d8-68fc07fdb6fd", + "properties": { + "backgroundColor": "ce7e00" + } + } + }, + { + "content": { + "contentType": "featuredPost", + "id": "76dabfff-7e86-4404-9a89-1b8274ac4f8e", + "properties": { + "title": "Community is key", + "post": { + "contentType": "post", + "name": "Building a community", + "createDate": "2023-08-14T08:35:58.6755792", + "updateDate": "2023-08-14T08:54:45.5526111", + "route": { + "path": "/building-a-community/", + "startItem": { + "id": "d88fefc3-da04-493d-9533-294a7264b27f", + "path": "posts" + } + }, + "id": "6e1bc040-f382-402c-ac56-3328d5f424c7", + "properties": { + "coverImage": [ + { + "focalPoint": null, + "crops": [], + "id": "9757a20c-3e98-49ef-8103-c7fa746856e7", + "name": "Community", + "mediaType": "Image", + "url": "/media/bkrfpf2y/community.png", + "extension": "png", + "width": 1080, + "height": 540, + "bytes": 25832, + "properties": { + "altText": "Two hands constructing a heart from coloured pieces" + } + } + ], + "excerpt": "Maecenas ipsum dui, lobortis non dui eleifend, dapibus bibendum dui. Pellentesque dolor felis, mollis nec diam eget, fermentum rutrum ipsum. Vestibulum condimentum urna id turpis tempus, id finibus sem facilisis. Nullam commodo felis quis ante posuere, dictum suscipit nisl suscipit." + } + } + } + }, + "settings": { + "contentType": "featuredPostSettings", + "id": "175325ab-b4a0-489d-a196-c1cf32b41ca1", + "properties": { + "backgroundColor": "6fa8dc" + } + } + } + ] + } + }, + "cultures": {} +} +``` +{% endcode %} + +### Block Grid + +Default output without expansion and limiting: + +**Request** + +```http +GET /umbraco/delivery/api/v2/content/item/article-with-block-grid/ +Start-Item: articles +``` + +**Response** + +{% code title="Default Delivery API output" %} +```json +{ + "contentType": "articleWithBlockGrid", + "name": "Article with Block Grid", + "createDate": "2023-11-07T16:34:19.1629081", + "updateDate": "2023-11-07T16:34:36.3701542", + "route": { + "path": "/article-with-block-grid/", + "startItem": { + "id": "5c8823f6-6442-4d04-9c14-f3411bd41aa8", + "path": "articles" + } + }, + "id": "17ed80d1-79e0-43b9-9ad6-7dad6a78e220", + "properties": { + "blockGrid": { + "gridColumns": 12, + "items": [ + { + "rowSpan": 1, + "columnSpan": 12, + "areaGridColumns": 12, + "areas": [ + { + "alias": "left", + "rowSpan": 1, + "columnSpan": 6, + "items": [ + { + "rowSpan": 1, + "columnSpan": 6, + "areaGridColumns": 12, + "areas": [], + "content": { + "contentType": "featuredPost", + "id": "8a509b3d-20f1-4b92-b74c-c74a309baec8", + "properties": { + "title": "Free your content with the Delivery API", + "post": { + "contentType": "post", + "name": "Set your content free", + "createDate": "2023-08-14T08:35:58.8397754", + "updateDate": "2023-08-14T08:54:41.8018872", + "route": { + "path": "/set-your-content-free/", + "startItem": { + "id": "d88fefc3-da04-493d-9533-294a7264b27f", + "path": "posts" + } + }, + "id": "5de65f2e-055e-4e6a-adc3-edb340dcd2e8", + "properties": {} + } + } + }, + "settings": { + "contentType": "featuredPostSettings", + "id": "81e51973-5107-4e9d-a1aa-71752ea7a9f4", + "properties": { + "backgroundColor": "ce7e00", + "showTags": true + } + } + } + ] + }, + { + "alias": "right", + "rowSpan": 1, + "columnSpan": 6, + "items": [ + { + "rowSpan": 1, + "columnSpan": 6, + "areaGridColumns": 12, + "areas": [], + "content": { + "contentType": "featuredPost", + "id": "de53752f-f3f1-4d17-a0f3-14ea62456fba", + "properties": { + "title": "Community is key", + "post": { + "contentType": "post", + "name": "Building a community", + "createDate": "2023-08-14T08:35:58.6755792", + "updateDate": "2023-08-14T08:54:45.5526111", + "route": { + "path": "/building-a-community/", + "startItem": { + "id": "d88fefc3-da04-493d-9533-294a7264b27f", + "path": "posts" + } + }, + "id": "6e1bc040-f382-402c-ac56-3328d5f424c7", + "properties": {} + } + } + }, + "settings": { + "contentType": "featuredPostSettings", + "id": "6471bae6-1341-4bbd-9e19-e61e8df4446d", + "properties": { + "backgroundColor": "6fa8dc", + "showTags": false + } + } + } + ] + } + ], + "content": { + "contentType": "twoColumnLayout", + "id": "40d5cf9c-809c-41ed-8639-84d894c2e663", + "properties": {} + }, + "settings": null + } + ] + } + }, + "cultures": {} +} +``` +{% endcode %} + +Output with property expansion and limiting: + +**Request** + +```http +GET /umbraco/delivery/api/v2/content/item/article-with-block-grid/ + ?expand=properties[blockGrid[properties[post[properties[coverImage]]]]] + &fields=properties[blockGrid[properties[title,post[properties[excerpt,coverImage]],backgroundColor]]] +Start-Item: articles +``` + +**Response** + +{% code title="Delivery API output with expansion and limiting" %} +```json +{ + "contentType": "articleWithBlockGrid", + "name": "Article with Block Grid", + "createDate": "2023-11-07T16:34:19.1629081", + "updateDate": "2023-11-07T16:34:36.3701542", + "route": { + "path": "/article-with-block-grid/", + "startItem": { + "id": "5c8823f6-6442-4d04-9c14-f3411bd41aa8", + "path": "articles" + } + }, + "id": "17ed80d1-79e0-43b9-9ad6-7dad6a78e220", + "properties": { + "blockGrid": { + "gridColumns": 12, + "items": [ + { + "rowSpan": 1, + "columnSpan": 12, + "areaGridColumns": 12, + "areas": [ + { + "alias": "left", + "rowSpan": 1, + "columnSpan": 6, + "items": [ + { + "rowSpan": 1, + "columnSpan": 6, + "areaGridColumns": 12, + "areas": [], + "content": { + "contentType": "featuredPost", + "id": "8a509b3d-20f1-4b92-b74c-c74a309baec8", + "properties": { + "title": "Free your content with the Delivery API", + "post": { + "contentType": "post", + "name": "Set your content free", + "createDate": "2023-08-14T08:35:58.8397754", + "updateDate": "2023-08-14T08:54:41.8018872", + "route": { + "path": "/set-your-content-free/", + "startItem": { + "id": "d88fefc3-da04-493d-9533-294a7264b27f", + "path": "posts" + } + }, + "id": "5de65f2e-055e-4e6a-adc3-edb340dcd2e8", + "properties": { + "coverImage": [ + { + "focalPoint": null, + "crops": [], + "id": "dbb62958-de31-465f-bdbe-5e9079b54b25", + "name": "Arrows", + "mediaType": "Image", + "url": "/media/lyulnwzr/arrows.png", + "extension": "png", + "width": 1080, + "height": 530, + "bytes": 24069, + "properties": { + "altText": "Some arrows pointing in different directions (but generally upwards)" + } + } + ], + "excerpt": "Fusce ut mauris ornare, mollis felis ac, convallis neque. Aenean eu tortor ac dui dictum lacinia. Aliquam erat volutpat. Sed malesuada congue imperdiet. Sed dictum aliquam velit. Nunc non nibh dignissim, consequat quam ac, mattis turpis. " + } + } + } + }, + "settings": { + "contentType": "featuredPostSettings", + "id": "81e51973-5107-4e9d-a1aa-71752ea7a9f4", + "properties": { + "backgroundColor": "ce7e00" + } + } + } + ] + }, + { + "alias": "right", + "rowSpan": 1, + "columnSpan": 6, + "items": [ + { + "rowSpan": 1, + "columnSpan": 6, + "areaGridColumns": 12, + "areas": [], + "content": { + "contentType": "featuredPost", + "id": "de53752f-f3f1-4d17-a0f3-14ea62456fba", + "properties": { + "title": "Community is key", + "post": { + "contentType": "post", + "name": "Building a community", + "createDate": "2023-08-14T08:35:58.6755792", + "updateDate": "2023-08-14T08:54:45.5526111", + "route": { + "path": "/building-a-community/", + "startItem": { + "id": "d88fefc3-da04-493d-9533-294a7264b27f", + "path": "posts" + } + }, + "id": "6e1bc040-f382-402c-ac56-3328d5f424c7", + "properties": { + "coverImage": [ + { + "focalPoint": null, + "crops": [], + "id": "9757a20c-3e98-49ef-8103-c7fa746856e7", + "name": "Community", + "mediaType": "Image", + "url": "/media/bkrfpf2y/community.png", + "extension": "png", + "width": 1080, + "height": 540, + "bytes": 25832, + "properties": { + "altText": "Two hands constructing a heart from coloured pieces" + } + } + ], + "excerpt": "Maecenas ipsum dui, lobortis non dui eleifend, dapibus bibendum dui. Pellentesque dolor felis, mollis nec diam eget, fermentum rutrum ipsum. Vestibulum condimentum urna id turpis tempus, id finibus sem facilisis. Nullam commodo felis quis ante posuere, dictum suscipit nisl suscipit." + } + } + } + }, + "settings": { + "contentType": "featuredPostSettings", + "id": "6471bae6-1341-4bbd-9e19-e61e8df4446d", + "properties": { + "backgroundColor": "6fa8dc" + } + } + } + ] + } + ], + "content": { + "contentType": "twoColumnLayout", + "id": "40d5cf9c-809c-41ed-8639-84d894c2e663", + "properties": {} + }, + "settings": null + } + ] + } + }, + "cultures": {} +} +``` +{% endcode %} + +### Rich Text Editor (with blocks) + +**Request** + +```http +GET /umbraco/delivery/api/v2/content/item/article-with-rich-text/ +Start-Item: articles +``` + +**Response** + +{% code title="Default Delivery API output" %} +```json +{ + "contentType": "articleWithRichText", + "name": "Article with Rich Text", + "createDate": "2023-11-07T16:33:51.5326056", + "updateDate": "2023-11-07T16:34:11.0504555", + "route": { + "path": "/article-with-rich-text/", + "startItem": { + "id": "5c8823f6-6442-4d04-9c14-f3411bd41aa8", + "path": "articles" + } + }, + "id": "785a7731-4312-4ed6-b11c-2f82db85c930", + "properties": { + "richText": { + "markup": "

Proin mattis enim arcu, ac maximus magna auctor a. Proin sed porttitor nibh, eget venenatis felis. Pellentesque mattis feugiat ultrices. Duis libero velit, sagittis eu nunc euismod, lacinia aliquam elit.

\n\n

Nulla quis fringilla sem. Integer id lacus sit amet ante gravida ullamcorper ac in neque. Etiam at ipsum a augue laoreet commodo. Vestibulum bibendum viverra diam, vel dignissim nunc suscipit id. 

\n\n

 

", + "blocks": [ + { + "content": { + "contentType": "featuredPost", + "id": "a42d825e-383c-4699-ae7f-eb851c0a5b13", + "properties": { + "title": "Free your content with the Delivery API", + "post": { + "contentType": "post", + "name": "Set your content free", + "createDate": "2023-08-14T08:35:58.8397754", + "updateDate": "2023-08-14T08:54:41.8018872", + "route": { + "path": "/set-your-content-free/", + "startItem": { + "id": "d88fefc3-da04-493d-9533-294a7264b27f", + "path": "posts" + } + }, + "id": "5de65f2e-055e-4e6a-adc3-edb340dcd2e8", + "properties": {} + } + } + }, + "settings": { + "contentType": "featuredPostSettings", + "id": "109e1f19-93b9-4f5a-9ab2-315aa618c42a", + "properties": { + "backgroundColor": "ce7e00", + "showTags": true + } + } + }, + { + "content": { + "contentType": "featuredPost", + "id": "724ecae7-3118-46a8-8dc2-a9bf9e10efdb", + "properties": { + "title": "Community is key", + "post": { + "contentType": "post", + "name": "Building a community", + "createDate": "2023-08-14T08:35:58.6755792", + "updateDate": "2023-08-14T08:54:45.5526111", + "route": { + "path": "/building-a-community/", + "startItem": { + "id": "d88fefc3-da04-493d-9533-294a7264b27f", + "path": "posts" + } + }, + "id": "6e1bc040-f382-402c-ac56-3328d5f424c7", + "properties": {} + } + } + }, + "settings": { + "contentType": "featuredPostSettings", + "id": "82b60071-38f6-49e8-896c-da7094895556", + "properties": { + "backgroundColor": "6fa8dc", + "showTags": false + } + } + } + ] + } + }, + "cultures": {} +} +``` +{% endcode %} + +Output with property expansion and limiting: + +**Request** + +```http +GET /umbraco/delivery/api/v2/content/item/article-with-rich-text/ + ?expand=properties[richText[properties[post[properties[coverImage]]]]] + &fields=properties[richText[properties[title,post[properties[excerpt,coverImage]],backgroundColor]]] +Start-Item: articles +``` + +**Response** + +{% code title="Delivery API output with expansion and limiting" %} +```json +{ + "contentType": "articleWithRichText", + "name": "Article with Rich Text", + "createDate": "2023-11-07T16:33:51.5326056", + "updateDate": "2023-11-07T16:34:11.0504555", + "route": { + "path": "/article-with-rich-text/", + "startItem": { + "id": "5c8823f6-6442-4d04-9c14-f3411bd41aa8", + "path": "articles" + } + }, + "id": "785a7731-4312-4ed6-b11c-2f82db85c930", + "properties": { + "richText": { + "markup": "

Proin mattis enim arcu, ac maximus magna auctor a. Proin sed porttitor nibh, eget venenatis felis. Pellentesque mattis feugiat ultrices. Duis libero velit, sagittis eu nunc euismod, lacinia aliquam elit.

\n\n

Nulla quis fringilla sem. Integer id lacus sit amet ante gravida ullamcorper ac in neque. Etiam at ipsum a augue laoreet commodo. Vestibulum bibendum viverra diam, vel dignissim nunc suscipit id. 

\n\n

 

", + "blocks": [ + { + "content": { + "contentType": "featuredPost", + "id": "a42d825e-383c-4699-ae7f-eb851c0a5b13", + "properties": { + "title": "Free your content with the Delivery API", + "post": { + "contentType": "post", + "name": "Set your content free", + "createDate": "2023-08-14T08:35:58.8397754", + "updateDate": "2023-08-14T08:54:41.8018872", + "route": { + "path": "/set-your-content-free/", + "startItem": { + "id": "d88fefc3-da04-493d-9533-294a7264b27f", + "path": "posts" + } + }, + "id": "5de65f2e-055e-4e6a-adc3-edb340dcd2e8", + "properties": { + "coverImage": [ + { + "focalPoint": null, + "crops": [], + "id": "dbb62958-de31-465f-bdbe-5e9079b54b25", + "name": "Arrows", + "mediaType": "Image", + "url": "/media/lyulnwzr/arrows.png", + "extension": "png", + "width": 1080, + "height": 530, + "bytes": 24069, + "properties": { + "altText": "Some arrows pointing in different directions (but generally upwards)" + } + } + ], + "excerpt": "Fusce ut mauris ornare, mollis felis ac, convallis neque. Aenean eu tortor ac dui dictum lacinia. Aliquam erat volutpat. Sed malesuada congue imperdiet. Sed dictum aliquam velit. Nunc non nibh dignissim, consequat quam ac, mattis turpis. " + } + } + } + }, + "settings": { + "contentType": "featuredPostSettings", + "id": "109e1f19-93b9-4f5a-9ab2-315aa618c42a", + "properties": { + "backgroundColor": "ce7e00" + } + } + }, + { + "content": { + "contentType": "featuredPost", + "id": "724ecae7-3118-46a8-8dc2-a9bf9e10efdb", + "properties": { + "title": "Community is key", + "post": { + "contentType": "post", + "name": "Building a community", + "createDate": "2023-08-14T08:35:58.6755792", + "updateDate": "2023-08-14T08:54:45.5526111", + "route": { + "path": "/building-a-community/", + "startItem": { + "id": "d88fefc3-da04-493d-9533-294a7264b27f", + "path": "posts" + } + }, + "id": "6e1bc040-f382-402c-ac56-3328d5f424c7", + "properties": { + "coverImage": [ + { + "focalPoint": null, + "crops": [], + "id": "9757a20c-3e98-49ef-8103-c7fa746856e7", + "name": "Community", + "mediaType": "Image", + "url": "/media/bkrfpf2y/community.png", + "extension": "png", + "width": 1080, + "height": 540, + "bytes": 25832, + "properties": { + "altText": "Two hands constructing a heart from coloured pieces" + } + } + ], + "excerpt": "Maecenas ipsum dui, lobortis non dui eleifend, dapibus bibendum dui. Pellentesque dolor felis, mollis nec diam eget, fermentum rutrum ipsum. Vestibulum condimentum urna id turpis tempus, id finibus sem facilisis. Nullam commodo felis quis ante posuere, dictum suscipit nisl suscipit." + } + } + } + }, + "settings": { + "contentType": "featuredPostSettings", + "id": "82b60071-38f6-49e8-896c-da7094895556", + "properties": { + "backgroundColor": "6fa8dc" + } + } + } + ] + } + }, + "cultures": {} +} +``` +{% endcode %} + +## Closing remarks + +Property expansion and limiting is a powerful feature that can boost our application performance. With this we can prevent additional requests to obtain data for linked items, and we can tailor the output to specific use cases. + +However, it is also a complex feature. The query syntax quickly gets complicated, particularly when targeting block editors. You will likely need to experiment some to get the query just right. Hopefully the examples in this article will guide you in applying expansion and limiting to your own content. From c27e04736d923ff83aae1b41c819bea901917918 Mon Sep 17 00:00:00 2001 From: kjac Date: Fri, 10 Nov 2023 12:48:22 +0100 Subject: [PATCH 2/8] Fixed linter errors --- 13/umbraco-cms/reference/content-delivery-api/README.md | 2 +- .../content-delivery-api/property-expansion-and-limiting.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/13/umbraco-cms/reference/content-delivery-api/README.md b/13/umbraco-cms/reference/content-delivery-api/README.md index 08d9fb73deb..d8d4d93ba3b 100644 --- a/13/umbraco-cms/reference/content-delivery-api/README.md +++ b/13/umbraco-cms/reference/content-delivery-api/README.md @@ -194,7 +194,7 @@ Property expansion and limiting allows you to: - Include properties from related content or media in the API output for a given content item. - Limit the content properties in the API output. -By default, a content property that allows picking a different content item (i.e. a content picker) outputs a "shallow" representation of the picked item. This means that the output only includes basic information about the picked item, without the item properties. +By default, a content property that allows picking a different content item (for example a content picker) outputs a "shallow" representation of the picked item. This means that the output only includes basic information about the picked item, without the item properties. If we apply property expansion to the content property, the properties of the picked item are included in the output. This functionality applies to media items and block editors, as well. diff --git a/13/umbraco-cms/reference/content-delivery-api/property-expansion-and-limiting.md b/13/umbraco-cms/reference/content-delivery-api/property-expansion-and-limiting.md index 3e39fdef7c0..d6e78089069 100644 --- a/13/umbraco-cms/reference/content-delivery-api/property-expansion-and-limiting.md +++ b/13/umbraco-cms/reference/content-delivery-api/property-expansion-and-limiting.md @@ -1,5 +1,5 @@ --- -description: Using property expansion and limiting to shape the Delivery API output. +description: Using property expansion and limiting to shape the Delivery API output --- # Property expansion and limiting @@ -1371,4 +1371,4 @@ Start-Item: articles Property expansion and limiting is a powerful feature that can boost our application performance. With this we can prevent additional requests to obtain data for linked items, and we can tailor the output to specific use cases. -However, it is also a complex feature. The query syntax quickly gets complicated, particularly when targeting block editors. You will likely need to experiment some to get the query just right. Hopefully the examples in this article will guide you in applying expansion and limiting to your own content. +However, it is also a complex feature. The query syntax quickly gets complicated, particularly when targeting block editors. You will likely need to experiment some to get the query exactly right. Hopefully the examples in this article will guide you in applying expansion and limiting to your own content. From bae0c17bec60a80337aac333a89c0ddaecfcd9a7 Mon Sep 17 00:00:00 2001 From: kjac Date: Fri, 10 Nov 2023 14:51:18 +0100 Subject: [PATCH 3/8] Review changes --- .../reference/content-delivery-api/README.md | 8 ++++---- .../content-delivery-api/media-delivery-api.md | 10 +++++----- .../protected-content-in-the-delivery-api.md | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/13/umbraco-cms/reference/content-delivery-api/README.md b/13/umbraco-cms/reference/content-delivery-api/README.md index d8d4d93ba3b..330fc4fc531 100644 --- a/13/umbraco-cms/reference/content-delivery-api/README.md +++ b/13/umbraco-cms/reference/content-delivery-api/README.md @@ -277,7 +277,7 @@ Which properties to expand and therefore include in the output if they refer to {% endswagger-parameter %} {% swagger-parameter in="query" name="fields" type="String" required="false" %} -Explicitly defines which properties that should be included in the response (by default all properties are included) +Which properties to include in the response (_by default all properties are included_) {% endswagger-parameter %} {% swagger-response status="200: OK" description="Content item" %} @@ -323,7 +323,7 @@ Which properties to expand and therefore include in the output if they refer to {% endswagger-parameter %} {% swagger-parameter in="query" name="fields" type="String" required="false" %} -Explicitly defines which properties that should be included in the response (by default all properties are included) +Which properties to include in the response (_by default all properties are included_) {% endswagger-parameter %} {% swagger-response status="200: OK" description="Content item" %} @@ -369,7 +369,7 @@ Which properties to expand in the response {% endswagger-parameter %} {% swagger-parameter in="query" name="fields" type="String" required="false" %} -Explicitly defines which properties that should be included in the response (by default all properties are included) +Which properties to include in the response (_by default all properties are included_) {% endswagger-parameter %} {% swagger-response status="200: OK" description="List of content items" %} @@ -427,7 +427,7 @@ Which properties to expand and therefore include in the output if they refer to {% endswagger-parameter %} {% swagger-parameter in="query" name="fields" type="String" required="false" %} -Explicitly defines which properties that should be included in the response (by default all properties are included) +Which properties to include in the response (_by default all properties are included_) {% endswagger-parameter %} {% swagger-response status="200: OK" description="Paginated list of content items" %} diff --git a/13/umbraco-cms/reference/content-delivery-api/media-delivery-api.md b/13/umbraco-cms/reference/content-delivery-api/media-delivery-api.md index 22a6cf664b1..383466bfffd 100644 --- a/13/umbraco-cms/reference/content-delivery-api/media-delivery-api.md +++ b/13/umbraco-cms/reference/content-delivery-api/media-delivery-api.md @@ -74,7 +74,7 @@ Which properties to expand in the response {% endswagger-parameter %} {% swagger-parameter in="query" name="fields" type="String" required="false" %} -Explicitly defines which properties that should be included in the response (by default all properties are included) +Which properties to include in the response (_by default all properties are included_) {% endswagger-parameter %} {% swagger-response status="200: OK" description="Media item" %} @@ -112,7 +112,7 @@ Which properties to expand in the response {% endswagger-parameter %} {% swagger-parameter in="query" name="fields" type="String" required="false" %} -Explicitly defines which properties that should be included in the response (by default all properties are included) +Which properties to include in the response (_by default all properties are included_) {% endswagger-parameter %} {% swagger-response status="200: OK" description="Media item" %} @@ -128,7 +128,7 @@ Explicitly defines which properties that should be included in the response (by {% endswagger-response %} {% endswagger %} -{% swagger method="get" path="/media/item" baseUrl="/umbraco/delivery/api/v2" summary="Gets media item(s) by id" %} +{% swagger method="get" path="/media/items" baseUrl="/umbraco/delivery/api/v2" summary="Gets media item(s) by id" %} {% swagger-description %} Returns single or multiple items by id. {% endswagger-description %} @@ -146,7 +146,7 @@ Which properties to expand in the response {% endswagger-parameter %} {% swagger-parameter in="query" name="fields" type="String" required="false" %} -Explicitly defines which properties that should be included in the response (by default all properties are included) +Which properties to include in the response (_by default all properties are included_) {% endswagger-parameter %} {% swagger-response status="200: OK" description="List of media items" %} @@ -194,7 +194,7 @@ Which properties to expand in the response {% endswagger-parameter %} {% swagger-parameter in="query" name="fields" type="String" required="false" %} -Explicitly defines which properties that should be included in the response (by default all properties are included) +Which properties to include in the response (_by default all properties are included_) {% endswagger-parameter %} {% swagger-response status="200: OK" description="Paginated list of media items" %} diff --git a/13/umbraco-cms/reference/content-delivery-api/protected-content-in-the-delivery-api.md b/13/umbraco-cms/reference/content-delivery-api/protected-content-in-the-delivery-api.md index d21cd4936fc..6601fa2c7a3 100644 --- a/13/umbraco-cms/reference/content-delivery-api/protected-content-in-the-delivery-api.md +++ b/13/umbraco-cms/reference/content-delivery-api/protected-content-in-the-delivery-api.md @@ -320,7 +320,7 @@ The [Login partial view](https://github.com/umbraco/Umbraco-CMS/blob/contrib/src 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: ```http -GET /umbraco/delivery/api/v1/content/{query} +GET /umbraco/delivery/api/v2/content/{query} Authentication: Bearer {access token} ``` From 4f78d42a593ccf6d6b50be7cadbedade08f549c5 Mon Sep 17 00:00:00 2001 From: kjac Date: Mon, 13 Nov 2023 08:10:43 +0100 Subject: [PATCH 4/8] Review changes from Elitsa --- .../reference/content-delivery-api/README.md | 8 ++--- .../property-expansion-and-limiting.md | 36 ++++++++++--------- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/13/umbraco-cms/reference/content-delivery-api/README.md b/13/umbraco-cms/reference/content-delivery-api/README.md index 330fc4fc531..202138ea569 100644 --- a/13/umbraco-cms/reference/content-delivery-api/README.md +++ b/13/umbraco-cms/reference/content-delivery-api/README.md @@ -198,11 +198,11 @@ By default, a content property that allows picking a different content item (for If we apply property expansion to the content property, the properties of the picked item are included in the output. This functionality applies to media items and block editors, as well. -Property expansion can be applied to expanded properties too, thus obtaining nested property expansion. As a consequence the output grows in size, and this is where property limiting comes into the picture. +Property expansion can be applied to expanded properties too, thus obtaining nested property expansion. As a consequence, the output grows in size, and this is where property limiting comes into the picture. By default, all content properties (including expanded properties) are included in the output. Property limiting allows us to specify exactly which content properties to include in the output. This means we can tailor the output specifically to concrete use cases without over-fetching. -Property expansion and limiting can be used when querying for both single and multiple content or media items. +Property expansion and limiting can be used when querying for both single and multiple content or media items. You can expand properties by adding an `expand` parameter to the query and limit them by the `fields` query parameter. Please refer to [this article](./property-expansion-and-limiting) for an in-depth explanation of this feature. @@ -447,7 +447,7 @@ All endpoints are documented in a Swagger document at `{yourdomain}/umbraco/swag ### Query parameters -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. +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`, `fields`, `fetch`, `filter` and `sort` parameters. Below are the options supported out of the box. {% hint style="info" %} You can extend the built-in selector, filter, and sorting capabilities of the Delivery API by creating your own custom query handlers. @@ -478,7 +478,7 @@ Refer to the [Property expansion and limiting](./#property-expansion-and-limitin {% endhint %} **`?fields=properties[$all]`**\ -Includes all properties on the retrieved content item in the output. +Includes all properties of the retrieved content item in the output. **`?fields=properties[alias1]`**\ Includes only the property with the property alias _`alias1`_ in the output. diff --git a/13/umbraco-cms/reference/content-delivery-api/property-expansion-and-limiting.md b/13/umbraco-cms/reference/content-delivery-api/property-expansion-and-limiting.md index d6e78089069..3fdf9e0bf98 100644 --- a/13/umbraco-cms/reference/content-delivery-api/property-expansion-and-limiting.md +++ b/13/umbraco-cms/reference/content-delivery-api/property-expansion-and-limiting.md @@ -1,4 +1,4 @@ ---- +--- description: Using property expansion and limiting to shape the Delivery API output --- @@ -15,7 +15,7 @@ Property expansion and limiting applies only to select property editors. The fol - Media Picker - Media Picker (legacy) - Multinode Treepicker -- Block based editors +- Block-based editors - Block List - Block Grid - Rich Text Editor (with blocks) @@ -29,7 +29,7 @@ When working with property expansion and limiting in API queries, there are two ## Working with picker editors -In the following we will be querying a content tree with blog posts and blog authors: +In the following, we will be querying a content tree with blog posts and blog authors: - All blog posts are located under a root content item called "Posts". - All authors are located under a root content item called "Authors". @@ -39,7 +39,7 @@ The blog post content type (`post`) contains two properties that support expansi - `author`: A content picker for picking the author of the post. - `coverImage`: A media picker for picking an image for the post. -The author content type (`author`) contains a single property that support expansion and limiting: +The author content type (`author`) contains a single property that supports expansion and limiting: - `picture`: A media picker for picking a picture of the author. @@ -115,7 +115,7 @@ Start-Item: posts ``` {% endcode %} -If we want to show the author picture when rendering the blog post, we need to _expand_ the `author` property. By expanding the property, the author properties (including `picture`) are included in the output. We can achieve this by appending the `expand` parameter to our request. +If we want to show the author's picture when rendering the blog post, we need to _expand_ the `author` property. By expanding the property, the author properties (including `picture`) are included in the output. We can achieve this by appending the `expand` parameter to our request. The `expand` parameter syntax is as follows: @@ -214,9 +214,9 @@ Start-Item: posts ``` {% endcode %} -Now we have the `picture` data in the `properties` collection of `author`. However, the rest of the author properties (`biography` and `dateOfBirth`) are also present in our output, so we are slightly over-fetching. We will take care of that later. +Now we have the `picture` data in the `properties` collection of `author`. However, the rest of the author's properties (`biography` and `dateOfBirth`) are also present in our output, so we are slightly over-fetching. We will take care of that later. -First we need to get the alt texts of our images (the blog post `coverImage` and the author `picture`). The alt text in this case is a text string property (`altText`) on the media type. Fetching the alt texts is possible because property expansion can be performed both across multiple properties and in a nested fashion. +First, we need to get the alt texts of our images (the blog post `coverImage` and the author `picture`). The alt text in this case is a text string property (`altText`) on the media type. Fetching the alt texts is possible because property expansion can be performed both across multiple properties and in a nested fashion. For nested property expansion, the `expand` parameter syntax is as follows: @@ -227,7 +227,7 @@ Nested property expansion can also be combined with the `$all` operator: `expand=properties[$all[properties[nestedPropertyAlias1,nestedPropertyAlias2]]]` {% hint style="info" %} -There is no API limit to how "deep" the nesting can go. Eventually though, the total length of request URL may become a hard limit to the size of the query. +There is no API limit to how "deep" the nesting can go. Eventually though, the total length of the request URL may become a hard limit to the size of the query. {% endhint %} Let's amend the `expand` parameter to accommodate expansion of the images: @@ -325,7 +325,7 @@ Start-Item: posts ``` {% endcode %} -As mentioned above we are slightly over-fetching. We don't need all the author data - we are only interested in the author `picture`. To fix this we can apply property limiting by adding the `fields` parameter to our request. +As mentioned above we are slightly over-fetching. We don't need all the author data - we are only interested in the author's `picture`. To fix this we can apply property limiting by adding the `fields` parameter to our request. The `fields` parameter allows us to limit the properties in the output to only those specified. The parameter uses the same syntax as the `expand` parameter. @@ -334,7 +334,7 @@ Our ideal blog post output contains: - All the properties of the blog post, including the `altText` of the post `coverImage`. - Only the `picture` property of `author`, including the `altText` of the author `picture`. -As with property expansion we can use the `$all` operator in the `fields` parameter. This will include everything at any given query level. We'll use this to include all the blog post properties in the output without having to specify each property explicitly: +As with property expansion, we can use the `$all` operator in the `fields` parameter. This will include everything at any given query level. We'll use this to include all the blog post properties in the output without having to specify each property explicitly: **Request** @@ -430,7 +430,7 @@ Start-Item: posts Now the API output contains only the properties we need to render the blog post. -Property limiting is particularly useful when querying multiple items. For example, if we were building condensed list of blog posts, we likely wouldn't need the author data nor the blog post content. By applying limiting to a filtered query, we can tailor the API output specifically to this scenario: +Property limiting is particularly useful when querying multiple items. For example, if we were building a condensed list of blog posts, we likely wouldn't need the author data nor the blog post content. By applying limiting to a filtered query, we can tailor the API output specifically to this scenario: **Request** @@ -534,10 +534,10 @@ Start-Item: posts ``` {% endcode %} -## Working with block based editors +## Working with block-based editors {% hint style="info" %} -If you are not familiar with block based editors, please refer to [this article](https://docs.umbraco.com/umbraco-cms/fundamentals/backoffice/property-editors/built-in-umbraco-property-editors/block-editor) for the general concepts of these. +If you are not familiar with block-based editors, please refer to [this article](https://docs.umbraco.com/umbraco-cms/fundamentals/backoffice/property-editors/built-in-umbraco-property-editors/block-editor) for the general concepts of these. {% endhint %} In the API output, a block has little value without its contained properties. Therefore, the content and settings properties of blocks are always included in the output. However, these properties are not expanded. As such, we can apply expansion and limiting to the contained properties. @@ -545,7 +545,7 @@ In the API output, a block has little value without its contained properties. Th In the following we'll request different types of articles, all of which are located under a root content item called "Articles": - An article with a Block List property (`blockList`). -- An article a Block Grid property (`blockGrid`). +- An article with a Block Grid property (`blockGrid`). - An article with a Rich Text Editor property (`richText`). All these properties are configured with a "Featured Post" block which consists of: @@ -562,12 +562,14 @@ The goal is once again to build a condensed list of blog posts. But this time we To build the list we need the block `title`, the `coverImage` and `excerpt` from the picked post, and the `backgroundColor` from the block settings. Thus, we need to: - Expand the `post` property to retrieve the `altText` of the post `coverImage`. -- Limit both the block level properties and the nested `post` properties, as to only output the properties relevant for building the condensed list. +- Limit both the block-level properties and the nested `post` properties, as to only output the properties relevant for building the condensed list. +{% hint style="info" %} For comparison, the samples show both the default output and the output with expansion and limiting applied. Notice that: - The `expand` and `fields` parameter syntax is the same for all editors, even though their rendered output is structurally different. - The `expand` and `fields` parameters target both the content and settings parts of each block. +{% endhint %} ### Block List @@ -1369,6 +1371,6 @@ Start-Item: articles ## Closing remarks -Property expansion and limiting is a powerful feature that can boost our application performance. With this we can prevent additional requests to obtain data for linked items, and we can tailor the output to specific use cases. +Property expansion and limiting is a powerful feature that can boost our application performance. With this, we can prevent additional requests to obtain data for linked items, and we can tailor the output to specific use cases. -However, it is also a complex feature. The query syntax quickly gets complicated, particularly when targeting block editors. You will likely need to experiment some to get the query exactly right. Hopefully the examples in this article will guide you in applying expansion and limiting to your own content. +However, it is also a complex feature. The query syntax quickly gets complicated, particularly when targeting block editors. You will likely need to experiment to get the query exactly right. Hopefully, the examples in this article will guide you in applying expansion and limiting to your own content. From 5927c7e86839b91118e4aa3e9b756164a0b13f6a Mon Sep 17 00:00:00 2001 From: kjac Date: Mon, 13 Nov 2023 11:11:28 +0100 Subject: [PATCH 5/8] Update expand syntax for custom property editors support article --- .../content-delivery-api/custom-property-editors-support.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/13/umbraco-cms/reference/content-delivery-api/custom-property-editors-support.md b/13/umbraco-cms/reference/content-delivery-api/custom-property-editors-support.md index f777a94edb2..91e871946e5 100644 --- a/13/umbraco-cms/reference/content-delivery-api/custom-property-editors-support.md +++ b/13/umbraco-cms/reference/content-delivery-api/custom-property-editors-support.md @@ -194,12 +194,12 @@ private DeliveryApiCustomPicker? BuildDeliveryApiCustomPicker(object inter, bool 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. +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=properties[$all]` to expand all properties or `?expand=properties[pickedItem]` to expand the specific `'pickedItem'` property. **Request** ```http -GET /umbraco/delivery/api/v2/content/item/blog?expand=property:pickedItem +GET /umbraco/delivery/api/v2/content/item/blog?expand=properties[pickedItem] ``` **Response** From 08fa8019667b39430283b07c21082f998fff32f5 Mon Sep 17 00:00:00 2001 From: kjac Date: Tue, 14 Nov 2023 10:35:43 +0100 Subject: [PATCH 6/8] Include docs for expansion specific API cache level --- .../content-delivery-api/custom-property-editors-support.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/13/umbraco-cms/reference/content-delivery-api/custom-property-editors-support.md b/13/umbraco-cms/reference/content-delivery-api/custom-property-editors-support.md index 91e871946e5..92699e917c2 100644 --- a/13/umbraco-cms/reference/content-delivery-api/custom-property-editors-support.md +++ b/13/umbraco-cms/reference/content-delivery-api/custom-property-editors-support.md @@ -59,6 +59,9 @@ public class MyCustomPickerValueConverter : PropertyValueConverterBase, IDeliver public PropertyCacheLevel GetDeliveryApiPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Elements; + public PropertyCacheLevel GetDeliveryApiPropertyCacheLevelForExpansion(IPublishedPropertyType propertyType) + => PropertyCacheLevel.Snapshot; + public Type GetDeliveryApiPropertyValueType(IPublishedPropertyType propertyType) => typeof(DeliveryApiCustomPicker); @@ -114,6 +117,7 @@ public class DeliveryApiItemDetails 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. +* `GetDeliveryApiPropertyCacheLevelForExpansion()`: This method specifies the cache level used for our property representation in the Delivery API response when [property expansion](./property-expansion-and-limiting) is applied. * `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. From c76bb5c33ffe07782e0c255a198242f14b30975c Mon Sep 17 00:00:00 2001 From: kjac Date: Tue, 14 Nov 2023 10:42:30 +0100 Subject: [PATCH 7/8] Review changes --- .../content-delivery-api/property-expansion-and-limiting.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/13/umbraco-cms/reference/content-delivery-api/property-expansion-and-limiting.md b/13/umbraco-cms/reference/content-delivery-api/property-expansion-and-limiting.md index 3fdf9e0bf98..21bb3108cd3 100644 --- a/13/umbraco-cms/reference/content-delivery-api/property-expansion-and-limiting.md +++ b/13/umbraco-cms/reference/content-delivery-api/property-expansion-and-limiting.md @@ -29,7 +29,7 @@ When working with property expansion and limiting in API queries, there are two ## Working with picker editors -In the following, we will be querying a content tree with blog posts and blog authors: +In the following examples, we will be querying a content tree with blog posts and blog authors: - All blog posts are located under a root content item called "Posts". - All authors are located under a root content item called "Authors". @@ -542,7 +542,7 @@ If you are not familiar with block-based editors, please refer to [this article] In the API output, a block has little value without its contained properties. Therefore, the content and settings properties of blocks are always included in the output. However, these properties are not expanded. As such, we can apply expansion and limiting to the contained properties. -In the following we'll request different types of articles, all of which are located under a root content item called "Articles": +In the following examples we'll request different types of articles, all of which are located under a root content item called "Articles": - An article with a Block List property (`blockList`). - An article with a Block Grid property (`blockGrid`). From ce1bc233cb8a7299a853497d001639c5541a0437 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Tue, 14 Nov 2023 10:44:48 +0100 Subject: [PATCH 8/8] Update 13/umbraco-cms/SUMMARY.md Co-authored-by: jonat123 <54025331+jonat123@users.noreply.github.com> --- 13/umbraco-cms/SUMMARY.md | 1 - 1 file changed, 1 deletion(-) diff --git a/13/umbraco-cms/SUMMARY.md b/13/umbraco-cms/SUMMARY.md index 8624d57e656..fa159c835bc 100644 --- a/13/umbraco-cms/SUMMARY.md +++ b/13/umbraco-cms/SUMMARY.md @@ -25,7 +25,6 @@ * [Extension API for querying](reference/content-delivery-api/extension-api-for-querying.md) * [Media Delivery API](reference/content-delivery-api/media-delivery-api.md) * [Protected content in the Delivery API](reference/content-delivery-api/protected-content-in-the-delivery-api.md) - * [Additional preview environments support](reference/content-delivery-api/additional-preview-environments-support.md) * [Property expansion and limiting](reference/content-delivery-api/property-expansion-and-limiting.md) ## Tutorials