Launch – Make an Extension – Publish


Another article in the “Launch – Make an Extension” series. See the other ones here: Overview, Setup, Coding, Debugging, on a Mac, and Reloaded

I had an hour or so of deep frustration the other day, when I tried to transition an Extension I had built from “Development” state (in which it can only be used in Properties that have the “[x] Configure for extension development (cannot be modified later)” option set) to “Private”, in which it can be used in the Experience Cloud Org that was used to upload it.

The latter is something I count on doing quite a lot with customers.

There were (or are) three pieces of documentation for this: the Private Extensions are Coming forum post by Ben Robison, the Releasing Your Extension chapter of the Getting Started doc, and the Release Private API doc.

I tried a bunch of things, none worked, and I decided that I will never fall in love with Postman. Sorry.

What worked for me was a combination of using the reactor-uploader, and some good, old-fashioned curl, run on a Raspberry Pi, which was sitting on the desk next to me.

Emergency Pi to the rescue!
Here is how it worked for me in 3 easy steps…

  1. Use the Adobe I/O Console & curl to generate an access token, and copy your API Key,
  2. use @adobe/reactor-packager a& @adobe/reactor-uploader to package and upload the Extension package, and finally
  3. use curl to “release” the Extension package to “private” use.

If you are on a Mac, I presume you won’t need a Raspberry Pi. If you’re on Windows, und you can tell me where I can find a version of curl that works with the calls listed below, please speak up!

Some further testing, and I can now report that curl 7.55.1, seemingly bundled with Windows 10, and curl 7.62, downloaded from, work just fine on Windows, at least for step 1.

1 — Generate Access Token

This step involves your Adobe I/O Integration. You probably made this at some point whilst walking through either of the three documents listed above.

For this step, you need to a) be able to log into the Adobe I/O Console, and b) the contents of your private key file.

When you have successfully logged in, select your Integration from the list, or click the “View” button. You’ll be transported to the Integration Overview page.

Integration Overview in Adobe I/O Console
While you are on this screen, copy the API Key.

Now head over to the tab named “JWT”.

JWT screen
You will have to copy the contents of your private key file into the lower box, then click the “Generate JWT” button.

You’ll see the page expand towards the bottom.

JWT View with generated JWT
You’re interested in the curl command at the bottom right, as that command will generate an access token for you. You can re-use that command until the JWT expires, which by default is after a day, I believe.

So, use the little “Copy” icon to copy the command, then paste it somewhere into a terminal, and run it. The output should look like this:

After successful curl command
Copy the access token.

Depending on your terminal, it might be easier to just copy the lot into an editor, then remove everything but the access token. I am using the excellent ConEmu, which lets me copy parts of the text in the terminal pretty easily.

Ok. We have an access token. Onwards!

2 — Upload the Extension package

You will need the access token later in this step, but first, package your Extension using the packager.

The easiest way to do so is to move into your Extension directory, then issue the following command:

npx @adobe/reactor-packager

The command won’t really give any output, but once it has finished, you should have a ZIP file in your Extensions folder:

After successful packager command
Notice the two zip files? Wonder where the parts (“constant-dataelement” & “1.0.2”) come from?

Well, the extension.json contains a ‘name’ and a ‘version’ attribute, and those two are what make the package file name what it is.

extension.js file
You’re done with packaging, now you can upload the Extension.

In real life, you would likely upload to the integration environment, debug your Extension, and then eventually upload to production. I’ll show the steps for production, which only differ at one single point (you’ll see), because I want to show you how to turn your Extension to private in step 3.

You can now test your Extensions right on the production environment, so that’s what we’ll do.

Run the uploader, like this:

npx @adobe/reactor-uploader

The uploader will ask you a bunch of questions:

Which environment do you want to use? Select “Production”

Uploader – environment
How do you want to authenticate? Select Provide access tokenand paste the access token you generated in step 1

Uploader – access token
Which ZIP file do you want to upload? Select the latest, in this case “1.0.2”

Uploader – processing
When the uploader is done, you should copy the extension package ID, as you will need that to set your Extension to private in the next step.

Uploader – done with Extension Package ID
Note: at this point, you can see/use your Extension in any Property that has the “[x] Configure for extension development (cannot be modified later)” option set! But you won’t see it in “normal” Properties.

So when you’re happy with it, and you want to use it in your Experience Cloud only, then this is the time to set it to “private”.

3 — Release your Extension, privately

This step is just one curl command, but I suggest you use an editor to make it.

The base code looks like this:

curl<your Extension Package ID> -H "Accept: application/vnd.api+json;revision=1" -H "Content-Type: application/vnd.api+json" -H "Authorization: Bearer <your access token>" -H "X-Api-Key: <your API key>" -X PATCH -d '{ "data": { "attributes": {}, "meta": { "action": "release_private" }, "id": "<your Extension Package ID>", "type": "extension_packages" } }'

If you put that into an editor, replace the four(!) “<your something>” placeholders correctly, then run the command, you should be seeing something like this:

curl command – release Extension Package privately
I have so far had trouble executing this on Windows, no matter what version of curl I used, so I did this ony my trusty Raspberry Pi.

Your Extension is now live on Launch, and you should be able to see it in all your Properties.

Extension in the Catalog in Launch, by Adobe
You can now install it like any other Extension.

Extension installed
And that’s it. We’re done!


I know what you’re thinking, and you’re right. These steps are nowhere near easy enough.

There is too much c&p going on, and a lot of it should be automated.

I’m hoping that someone will create a tool, and if or when that happens, I shall let you all know.

If you think your Extension would benefit more people, you can decide to make it public, or rather you can ask my colleagues to release it publicly.

Use the Public Release Request Form to ask to get it released.

Yes, do it!

Regarding the Pi on the desk: I configured it so it logs into hotel wifi and in turn provides wifi for all my devices, allowing me to use a Chromecast when I’m travelling. I also use it on site.

In the picture above, it was sitting on the desk of a Swiss bank, one of my most cherished customers. It’s funny how very few people asked me what on Earth a Pi was doing on the desk.

In this case, I was really glad I had it with me!

Raspberry Pis are cool. You can never have enough Raspberry Pis.

6 thoughts on “Launch – Make an Extension – Publish

    1. Hi Dimitris,

      I tried with cygwin, but to no avail. On my machine, it looks as if cygwin is using the same version of curl as windows, 7.55.1, with the same result.

      The one from doesn’t want to send the request, either.

      But I frankly admit that I haven’t yet tested thoroughly, and so there will likely be an update to this article at some point 😉



Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.