Power Automate Proof of Concept: Create a new Service Request
I didn't see many screenshots or detailed examples of Power Automate use for Cityworks API so here's my little offering:
I'm on 23.10. I'm an API and programming newby, so please offer any advice, tips, or tricks if you have them. I am lucky to be allowed the latitude to do a lot of testing and playing around since I happen to also be the Cityworks Administrator. Hopefully I can develop some new tools that help my organization. I've gotten some good integrations going already with Survey123 and the Cityworks API using Python. Instead of 'polling' for new Survey123 submissions with Windows Task running a python script on some recurring interval of minutes, I'd rather use a webhook to parse and process Survey123 submissions into service requests using Power Automate, which will happen virtually immediately, for every submission.
I'm just posting this for posterity since I had to get help with the proper Authorization header syntax for passing a token for API calls. Maybe this will save someone else some headache. This is a Power Automate cloud flow, manually triggered here for testing, but the input could be all kinds of stuff such as a webhook with values from a Survey123 form submission, which is my own priority use case. Note that Power Automate HTTP actions (the green one) require a premium level Power Automate license.
Here's the overall summary of my quick proof of concept. The red wrapper ('get cw token') is just an optional Scope which can be used to organize a Flow.
Here's the format for getting the token initially. The HTTP action is specifying the POST method. The URI here is the General/Authentication/Authenticate method and passing in a LoginName and Password for a user that has the Cityworks API license(s) assigned.
I stored the LoginName and Password in a Compose instead of initializing a Variable. This seems simpler. Also, FYI you can't initialize variables inside Scopes; variables have to be declared outside of a Scope wrapper. Anyway... the Queries key here is data and the value is the JSON containing the LoginName and Password from the Compose I named 'cw api credentials'
Here is what the Power Automate 'raw input' for the Authenticate method looks like when it is run:
and the 'raw output' response from the Cityworks server:
Next up is the Parse JSON action, using the response Body of the Authenticate method. Once I ran the Authenticate successfully the first time, I could use the raw output to 'Generate from sample' and populate the schema for this to Parse.
{
"type": "object",
"properties": {
"Value": {
"type": "object",
"properties": {
"Token": {
"type": "string"
}
}
},
"Status": {
"type": "integer"
},
"Message": {},
"ErrorMessages": {
"type": "array"
},
"WarningMessages": {
"type": "array"
},
"SuccessMessages": {
"type": "array"
}
}
}
This enables me to use the parsed Token string value in following Flow actions. I can imagine there is a better/simpler way to parse this string out but this seemed straightforward for testing.
Next is the tingly magical feeling I get from making something happen. I'm creating a new service request using a junk test template. You can find the Service Request Template Id of your templates in Admin Work Activity Templates menu. To create a service request using the API, the only required field to create is ProblemSid. The full list of values you can populate are in the API documentation at https://<yourdomain>/<site>/apidocs
Here I created another Compose action to write out the JSON for the service request values I want to pass to the Ams/ServiceRequest/Create method. My template's Id is 107. I threw in a string for "Details" as a proof of concept to see something else in the raw output.
What I got stuck on initially was how to pass the token for this method (and probably most other methods I will use). For Cityworks 23.10 at least you will use the Header key of Authorization and the value is the word Cityworks followed by a space, and then the raw Token string, which I'm pulling from the Parse JSON action I did above:
The raw inputs when run:
And raw outputs of the response from the Cityworks server. Everything here are the defaults of a new service request for this template except "Details" field, which I passed a value for.
Quick side note on the optional token Validate method -- I did that for troubleshooting, just to make sure the token was accepted: The correct syntax here is to pass the {"Token":<tokenstring>} JSON object as the Queries data value, and not the raw token string by itself as the value. That confused me for a bit because I made an assumption, before paying closer attention to the API documentation.
The response from this (if valid) is
{
"Value": true,
"Status": 0,
"Message": null,
"ErrorMessages": [],
"WarningMessages": [],
"SuccessMessages": []
}
