Hi team,
Use Case:User wants to access specific Appian task form from the external system. The task is not readily available. But, based on the request, the process would get triggered and a task is generated.
So, the ask here is to create a web API which initiates the process which generates the task, get the task ID, and constructs the task form link, and lastly redirects the user to the link that is just generated.
Is this possible using Appian's Web API?
Thanks,Akshar
Discussion posts and replies are publicly visible
I realize it's less likely, but if the user is on mobile, they can get a push notification that they can then tap on to take them to the task.
And, now that I think about it, the experience wouldn't necessarily be all that different on desktop if they have desktop email notifications (which many people do). So, once the task is created, the user would get an email notification in the corner of their screen with a link to the task.
I know that's not exactly what you had in mind, but from a functional standpoint, it might not be that far off. If you're having trouble figuring out how to interact with the process via a web api, you can also publish a process as a web service in order to invoke it from an external system. https://docs.appian.com/suite/help/19.2/Publishing_Process_Models_as_Web_Services.html
Another potential approach to consider, depending on how much flexibility you have with the external system, would be to make two requests, along with some sort of identifier. So, you might do something like:1) Start process (either via a POST request or web service call), passing your identifier as a parameter (for example, "id=3")2) In the process, associate the identifier you passed in with the task you end up creating.2a) (depending on how things go for you in testing) *brief pause/sleep to let the task get generated*3) Make a GET request to get the task link, using the identifier. (If you want, you can even have the request do a redirect to that link, as Josh suggested, with maybe a fallback url, like the tasks tab, in case you do have instances where the task hasn't yet been generated when the GET request is made.)It would be important to keep the different steps very lightweight (for example, if you want to store the identifier-to-task associations in a database, maybe have a table with only those two columns, and clean up the table entries when tasks are completed. Or, as another example, make the task a very early node in the process--if the task has 15 nodes in front of it that have to get completed first, you're more likely to end up with timing issues). But I could honestly see this still yielding a pretty smooth experience for the end user, even if you have to split up the steps behind the scenes.
Thanks Eliot. So, one of the stackholders came to me and said, "I want to be able to call the WebAPI from my browser URL link and give identifier. That should open the form based on the identifier." So, in short, I should have some webAPI which I can paste in the browser like - https://<SITE>.appiancloud.com/suite/webapi/openform?key=1 and it would open the form.
Hope I am making sense!
Ok. I think the multi-step approach could still work for that, with some slight modifications to wrap the different calls. So, on success, you'd have your POST request return a 201 or 301 redirect to your GET request, which would return a 201 or 301 with a redirect to the task. With that setup, pasting the POST url including parameters into the browser would yield the desired outcome.
Hi Eliot,
I did the same set up, Wherein I have created a post web API and initiated a process model to generate the task link. Now on the success, I'm returning status code 301 with subsequent call to get method WebAPI but when I paste the POST url including parameters into the browser it directly gives me "404 not found error"
bleh. that's my mistake--I wasn't thinking clearly and forgot that a POST request needs a form.I think you can still hack your way around it, BUT I would *strongly* encourage you to put in the work to keep things clean and handle edge cases. I need to emphasize that just because we can trick the system into treating a post like a get, it doesn't mean we necessarily should. Having said that, I was able to test out the following approach and get it to work:* Create a web api POST request to start your process. We'll call this "A".
* Create an integration object that invokes our rule A. Let's call this "B". For the "usage" option, select "queries". In this case, we are lying to the system, and it is extremely important that we put in appropriate guardrails to compensate for this. An example of such a guardrail would be a node early in the process that checks whether a process has already been started with the identifier we're passing in, and terminates itself if it realizes that it is a duplicate process. You could also theoretically put this check in rule A. In either case, you'd still want to be very wary of race conditions. In my own testing, I didn't have any issues with B getting executed multiple times, but if we've selected the "query" option, this is not guaranteed, and we shouldn't count on it. * Create a web api get request that will retrieve the task, given the identifier we used to start the process, and redirect us to the desired final url (e.g. the form for the task). We'll call this "C".
* Create a web api get request. We'll call this "D". "D" will look something like this:
load(local!result:rule!B( onsuccess:a!httpResponse( statusCode: 200, headers:{}, body: "" ), onError: a!httpResponse( statusCode: 500, headers:{}, body:"" )), a!httpResponse(statusCode: 301, headers: a!httpHeader(name:"Location",value:"https://example.com/suite/webapi/C"), body:"") )
The reason for putting rule!B in a load is that the return type for rule!B (our integration object) is not the expected return type for a webapi. But that also means we're ignoring the actual result from B--including any errors. I would, again, encourage you to take the time to parse out the result from B and add appropriate logic to handle different possible outcomes. So, to summarize: the approach I've described should do what you want, but you'll need to add error handling, pay special care to race conditions (for example, what happens if the GET request is made before the task has been generated? what happens if two requests are made to start the same process? etc), and make sure to keep the logic lightweight and snappy. Parsing the response body, for example, is the sort of thing where it's possible to get carried away and put in overly complex, non-performant logic.
Thanks Eliot! Let me try this out. I will update here!
So, I had a success implementing this. Thanks Eliot for the guidance.
What I did was, I used one of the functions available under Web and XML Extensions shared component - httppost. Using that, I initiated the process which has the task. Once that is done, in the WebAPI, I got the active task of that process and redirected user to that task form.