Create a SharePoint list, add/remove content types and updating the default SharePoint list view through REST API in Power Automate
It all seems so simple, but there are many steps to follow to programmatically achieve what takes a few seconds to manually carry out. So why bother when it’s so simple to manually do these tasks? Well, I wanted to dynamically create lists under the right conditions. For my circumstance, it was for each new year as the lists that I was creating would end up so large after one year, I wanted a new list to start fresh every year.
I had already created the site columns and content type I wanted to use for these lists, I just wanted to create the list, and give it a dynamic name. Additionally, I wanted to add my custom content type and remove the default Item content type. Finally, I wanted to add my site columns to the default view and call it a day.
The set up
To start, I use the Manually trigger a flow trigger, as this is a child flow that I call from another flow. However, you can use any trigger you want. I pass in the ListName and ListYear as inputs.
As I’m a bit pedantic, I don’t like spaces in my URLs, so my next step is to remove any spaces from the ListName.
I then initialize my ListTitle variable by concatenating the list title composed in the above step (the list name without spaces) and the ListYear together.
My next steps are to initialize GUIDs for the batch job I’ll be running later in the flow. I focus more on running batch jobs in another post.
Create the list
Now that we’ve initialized and set up all the variables, it’s time to start creating. First, we’ll create the SharePoint list by calling the SharePoint REST API. We want to allow content types as we will be adding a custom content type later. The base template is 100 which means custom list. You can find other types here. I’ve given my list a description and the title is the ListTitle variable I set earlier.
_api/web/lists
{
"AllowContentTypes": true,
"BaseTemplate": 100,
"ContentTypesEnabled": true,
"Description": "BMS @{triggerBody()['text']} log for entries in the year @{triggerBody()['text_1']}.",
"Title": "@{variables('ListTitle')}"
}
Now, I did say I was pedantic. So now that we have given the list a name without spaces, the URL has been set as such. However, that’s not very user friendly. Therefore, it’s time to change the list name back to a user friendly name. This way the name of the list will change, but the URL of the list will remain the same (i.e. without spaces).
I get the list by name (the name I set above, ListTitle). I then set the property of Title to the new value.
_api/web/lists/getbytitle('@{variables('ListTitle')}')
{
"Accept": "application/json;odata=verbose",
"Content-Type": "application/json;odata=verbose",
"IF-MATCH": "*",
"X-HTTP-Method": "MERGE"
}
{
"__metadata": {
"type": "SP.List"
},
"Title": "@{triggerBody()['text']} @{triggerBody()['text_1']}"
}
Now that we’ve set a new title, it’s time to set the ListTitle variable to the new value.
Adding and removing content types
The next step is to add the content type to the list. To add the content type, you need the content type ID. To get this, go to your content type in the Site Settings, and you will see the ID in the URL (e.g. ctype=0x0100001502C9FB3E4741B3565DD5EF9F6558).
_api/web/lists/getbytitle('@{variables('ListTitle')}')/ContentTypes/AddAvailableContentType('0x0100001502C9FB3E4741B3565DD5EF9F6558')
{
"Accept": "application/json;odata=verbose",
"Content-Type": "application/json;odata=verbose"
}
As I only want my content type available on the list, I want to remove the default Item content type. However, I need the ID of the Item content type (which is different for every list). So first, I retrieve the Item content type by Name.
_api/web/lists/getbytitle('@{variables('ListTitle')}')/ContentTypes?$filter=Name eq 'Item'
Now that I have retrieved the Item content type by name, I can access the content type ID. The ID can be accessed in the StringID property.
outputs('Send_an_HTTP_request_to_SharePoint_-_Retrieve_Item_CT')?['body']?['d']?['results']?[0]?['StringId']
Now that we have the content type ID, we can call a request to SharePoint to delete the Item content type from the list.
_api/web/lists/getbytitle('@{variables('ListTitle')}')/ContentTypes('@{outputs('Compose_-_Get_Item_ContentTypeID')}')/deleteObject()
Changing the default list view
Similar to the content type above, we need the ID of the All Items view in order to manipulate it. Therefore, we will bring back the properties of the view by retrieving the view by its Title.
_api/web/lists/getbytitle('@{variables('ListTitle')}')/Views?$filter=Title eq 'All Items'
Now that we have retrieved the All Items view by title, we can access the ID.
outputs('Send_an_HTTP_request_to_SharePoint_-_Retrieve_All_Items_view')?['body']?['d']?['results']?[0]?['Id']
I want to put together all the columns that I want to add to the All Items view. I add a Compose action and create an array. I add all the internal names off the columns that I want to add (they will be added in the order you put them in the array).
Next, I go through each column in the array and create my changeset item for the batch code. As the code to add each column to the view is one call to SharePoint, I decided to write a batch call to reduce the number of calls I had to make. For more explanation on what I did here, you can read my post Writing batch SharePoint API calls in Power Automate.
We have reached the final step! Updating the All Items view. Once this batch code runs, our programmatic way of creating a SharePoint list, adding/removing content types and changing the default SharePoint list view through REST API in Power Automate is complete. Simple eh?
_api/$batch
{
"Content-Type": "multipart/mixed; boundary=@{variables('BatchGUID')}",
"Expect": "100-continue"
}
--@{variables('BatchGUID')}
Content-Type: multipart/mixed; boundary="@{variables('ChangeSetGUID')}"
Host: https://<tenant>/sites/<site>
Content-Transfer-Encoding: binary
@{outputs('Compose_-_Change_changeset_from_array_to_string')}
--@{variables('ChangeSetGUID')}--
--@{variables('BatchGUID')}--
Hi Cass,
Thanks for posting this- very useful for what I’m trying to do. I’ve managed to replicate all of the steps you’ve listed, but getting a error on the final one – sooo close!
The error msg is “The request line ‘POST’ is invalid. The request line at the start of each operation must be of the format ‘HttpMethod RequestUrl HttpVersion’.”
Would you have any clues as to why this might be the case?
So close! I know that the last call can be extremely picky. Make sure there are no extra white spaces (not sure if it applies to your error, but can’t hurt). This is not Power Automate, but it might give you an idea of what’s happening: https://community.dynamics.com/crm/f/microsoft-dynamics-crm-forum/264113/problem-with-web-api-bulk-operation?pifragment-97030=1
Hi everyone,
unfortunately I got the same error message as Andrew and am not able to resolve.
Does anyone have some ideas on this?
Hi Cass,
Your article has been super helpful and I’ve successfully implemented this in my flow.
However, I’m running into an issue where on a newly created site, I cannot create a list with a custom content type, only the built in ones. Do you know what endpoint would sync the global content type gallery to a newly created site.
I’ve posted more detail to the Power Platform Community if you’d like some points 🙂
https://powerusers.microsoft.com/t5/Building-Flows/Sync-SharePoint-master-content-type-gallery-with-http-request-on/m-p/1885736#M207569
Is there a way to enable content types without creating a new list? I want to enable content types of lists that already exist.