Shortcuts URL Scheme Guide

Many products have great features that aren't utilized as much as they should be. When it comes to iOS, Shortcuts are definitely one of them. To me, Shortcuts provide a meeting place for all the apps the system provides, enabling us to make different apps cooperate. We can run them and connect the outputs of one app to the inputs of others. The possibilities are infinite. This post will focus on one aspect of Shortcuts, and that's the URL scheme. While developers mostly use frameworks like AppIntent and SiriKit to expose app functionalities to Shortcuts, one might ask: how do we run shortcuts from code? The answer is good old URL schemes. So, let's dive into it.

Opening a Shortcut

To open a shortcut, we utilize the following URL: shortcuts://open-shortcut?name=[name], where instead of the [name] placeholder, we put the name of the shortcut we want to open. So, the code may look like:

let url = URL(string: "shortcuts://open-shortcut?name=Shazam shortcut")!
UIApplication.shared.open(url)

"Shazam shortcut" is a preinstalled shortcut.

Creating a New Shortcut

To create a new shortcut, we use the following URL: shortcuts://create-shortcut.

let url = URL(string: "shortcuts://create-shortcut")!
UIApplication.shared.open(url)

Opening the Shortcuts App

If we just want to open the Shortcuts app, we can use the scheme shortcuts://.

let url = URL(string: "shortcuts://")!
UIApplication.shared.open(url)

Running a Shortcut

For running a shortcut from code, we can use the following URL: shortcuts://run-shortcut?name=[name]&input=[input]&text=[text]. Same as the previous URL, the name parameter represents the name of the shortcut we want to run. The input parameter is optional, providing us with a way to send input to the shortcut. The value of the input can be text, in which case we provide an additional parameter text which will hold the text input for the shortcut, or it can have a value clipboard. In the former case, the input to the shortcut will be collected from the clipboard. I created a shortcut named Note With Input you can find it here. To run it from code, we would use:

// Input from text
let url = URL(string: "shortcuts://run-shortcut?name=Note With Input&input=text&text=This is a test from text")!
UIApplication.shared.open(url)
// Input from clipboard
let url2 = URL(string: "shortcuts://run-shortcut?name=Note With Input&input=clipboard")!
UIApplication.shared.open(url2)

Returning to the App after the Shortcut is Finished

To return to the app (call site) from which the shortcut was triggered, we utilize x-callback-url. The x-callback-url standard comes with the following parameters which can be provided in the URL:

x-success (optional): A URL which opens when a shortcut is finished running. With this, a parameter named result is appended to the URL, containing the textual output of the shortcut. • x-cancel (optional): A URL that opens when the shortcut is cancelled by the user. • x-error (optional): A URL that opens when the shortcut fails because of an error. A parameter named errorMessage is appended to the URL, containing the description of the error.

So, if we wanted to return to the app after running the previous Note With Input action, the URL would look like: shortcuts://x-callback-url/run-shortcut?name=Add Note&input=text&text=Test&x-success=shortcutsdemo://.

In the x-success parameter, we put the URL scheme of our app. So instead of shortcutsdemo://, you would put your app's scheme.

Returning Output from the Shortcut to the App

In the previous section, we mentioned that a result parameter is appended to the x-success callback URL when the shortcut finishes and has a textual output. In order for the result parameter to be present, we need the shortcut to output a result. I created this shortcut, which outputs all created shortcuts.

let url = URL(string: "shortcuts://x-callback-url/run-shortcut?name=Get My Shortcuts&x-success=shortcutsdemo://")!
UIApplication.shared.open(url)

Now, in order to get the result, we add the following code to our ContentView:

.onOpenURL { url in
    if url.scheme == "shortcutsdemo" {
        guard let dirty = url.absoluteString.split(separator: "result=").last,
              let clean = String(dirty).removingPercentEncoding else {
            return
        }
        let shortcuts = clean.split(separator: "\n").map { String($0) }
        print(shortcuts)
    }
}

The code above reacts to URLs that correspond to our app's scheme, then we extract the data from the URL.

I created a sample app, so you can check it out here.

Tagged with: