This week there was a question on the Sitecore slack, about how to recover a previously deleted experience/experiment. It was pretty clear that the experience/experiment was still there, because when you tried to create a new experience/experiment with the exact same friendly id, it wouldn’t allow you to create the experience/experiment with that same friendlyId. I had seen this before when working on my POC for Sitecore Symposium, that typically Sitecore Personalize will actually archive an item, instead of deleting it. From my understanding, this is done to preserve analytical data that may have been collected about that experience/experiment. However the UI doesn’t give the user any way to recover an archived experience/experiment. It’s also, nice that it archives the item, instead of deleting it, because it makes it easy to recover the item at any point. But in the UI it can be frustrating, if you wanted to use the specific name for an experiment/experience.
APIs to the Rescue
Luckily during the work on the POC, that I’ll be introducing at Sitecore Symposium and on this blog in a few weeks as well, I discovered a bunch of kind of like management APIs for the tenants assets, which will come to the rescue in this case. Now as of today these are not currently documented anywhere, except for possibly these connection APIs, but unfortunately they don’t fully explain authentication, because authentication is different when working with this new set of APIs. It uses oAuth to authenticate against
/v2/oauth/token. There is really two primary ways (grant types) for authentication to this API, but the result is the same, to get back a JWT access token that you would then use with additional endpoints. To start authentication, I’ve provided a Gist of a Postman collection with the three authentication endpoints that I’ll detail below.
Password Grant Type
The password grant type method, allows you to use your own CDP/Personalize username and password to authenticate to the tenant. You will get back an access token and a refresh token. The refresh token can be used with the Refresh Token endpoint that I also provided in the postman collection.
There is one challenge with this type of grant type, and that is MFA (multi-factor authentication). If your tenant is a production tenant, it will likely require MFA, and in that case, you’ll have to pass the
code parameter, with the value from your MFA device, in addition to the username/password combination. That may not seem like a challenge, but it would be, if you are hoping to use this login to automate functionality, which was the case in my Sitecore Symposium presentation and POC.
Client Credentials Type
The second type of authentication is using client credentials which is very similar to the REST APIs used for ingestion, except you would pass these to the same
/v2/oauth/token endpoint to get back a JWT access token. Now that is all you will get back, there is no refresh token when using this method. But the great thing about this grant type is that even if your tenant requires MFA, it does not require it with this grant type. So if you want to achieve automation in some form, this is the grant type in a lot of cases that you’ll be looking for.
There are some issues, which are getting fixed, with this grant type. The biggest is that this grant type doesn’t always work for all of the endpoints I’m about to talk about, including today’s Experiences and Experiment (Flow) endpoints. But there are plans to add support for this grant type in the future for those APIs that throw errors when using this grant type.
Using the APIs to View Our Deleted Experience/Experiment
Now that we’ve explained how you can authenticate, now we need to start querying data to see what information we have access to. We’ll focus more on the topics of today’s blog, since there are many other APIs that can be used to achieve very many things. I’ve created the following Postman collection for these Flow APIs, that we’ll use in the next few paragraphs. Before we get to far, at a minimum you will need to know either the
friendlyId for the item you deleted, or its unique GUID. I find it’s quite useful in most situations, to use the
friendlyId since that uniquely identifies our items.
The first thing you’ll want to do is run a
GET to Retrieve Flow Definition, which is at
/v3/flowDefinitions/:flowDefinitionId, as previously mentioned, the flowDefinitionId can be its GUID or a
friendlyId. When you get the result set back, you should notice that you are being returned your deleted item, and that it’s set to archive:
All we need to do, is use the
PUT request (Update Flow Definition) that I provided in the Postman collection, by providing the
flowDefinitionId which is like before, either the GUID or the
friendlyId for the flow (Experience/Experiment) in Sitecore Personalize. And then in the body, we’ll copy the contents of our
GET request earlier, and inject those into the
BODY as JSON. Then update archive equals true, to now false. Then run the request, and upon success, refresh your browser, you should now see the item in the UI. Because the item was archived the name of the flow is now showing the previous name plus archived with a time stamp. So if you are planning to use this existing flow, then you’ll need to ensure that you remove that name and update the flow to match your use cases.
It’s important to note that this is a way around accidently deleting a flow (experience/experiment), but there may be other risk factors that aren’t entirely clear at this point. You should do thorough testing to ensure that your experiment or experiences are working as expected after an item was archived.
Also these APIs described above are not in Sitecore documentation. There is work to get them added, and once documentation is available I’ll include links to the documentation. Also I've created an unofficial Sitecore CDP/Personalize API Swagger reference that you can view on GitHub, that I'll likely use in future blog content.