CallbackURL() hangs if app does not return



When I use CallbackURL() in a script, if the app does not return the x-success value, the script will hang - I presume until a timeout value happens.

For example, if I call an app that has a “Return to Drafts” button, but instead Cmd-Tab back to Drafts, the action step is stuck awaiting the return. Another example: when I link to Working Copy and my action throws an error, like “Invalid URL key”, my action is unusable after that. I have to quit Drafts and relaunch to use the action again.

The URL step does not have this issue.


That is correct. CallbackURL scripted action is designed to allow use of the results of an x-callback-url to be used and to conditionally continue execution of the action based on that result - so it pauses execution.

If you do not need a result, use app.openURL, which will not pause execution.


So with that I have to manually add x-source, x-success, and encodeURIComponent() for everything as I build a string piece by piece?

And with callbackUrl() you have to check if there’s any return value anyway. Wouldn’t it make more sense to await callbackResponse() rather than open()?

Maybe I need to build some kind of wrapper object around openUrl() to do the convenience stuff.


CallbackURL should probably have an option to disable waiting on the response, like the Callback URL action step does - that was an oversight.



In the meantime, I made a workaround function here. (I returned the string instead of a boolean mostly for debugging. Not that I would ever use the string)

var URLScheme = (function() {
	return {
		create: function() { return this; },
		baseUrl: "",
		params: {},
		addParameter: function(name, value) {
			this.params[name] = value;
		useSafari: false,
		open: function() {
			var rv = "?";
			rv += "x-source=" + "Drafts&";
			rv += "x-success=" + encodeURIComponent("drafts5://") + "&";
			for (var p in this.params) {
				if (this.params.hasOwnProperty(p)) {
					rv += p + "=" + encodeURIComponent(this.params[p]) + "&";
			if (this.baseUrl !== "") {
				app.openURL(this.baseUrl + rv.slice(0, -1), this.useSafari);
			return this.baseUrl + rv.slice(0, -1);


Turns out the oversight was just in documenting the property. The CallbackURL object already has and supports a waitForResponse property. I’ll get the docs updated. Example:

let cb = CallbackURL.create();
cb.baseURL = "...";
cb.waitForResponse = false;;


Cool. I tried it but still had some issues. I tried using it with Working Copy. In this action I run one callback, awaiting a response. This works fine at first.

For the second call (writing the file, using waitForResponse = false) I tried passing in an invalid URL key to interrupt the x-success flow. WC flags an error (as it should) and the script seems to complete. However, I can’t run the script again, the first call (fetching the list of repositories) locks up. I am not defining waitForResponse on that instance, I presume it must be true.

I am using 2 different instances of CallbackURL, one for each call.

Thanks for your attention to this.