Update roles on existing work using the API

  • 18 February 2023
  • 18 replies
  • 203 views

Userlevel 7
Badge +19
  • Sr. Karbon Community Guide
  • 1196 replies

** UPDATE **

There’s a bug in the API that does not let us GET or PUT “UserRoleAssignments” so this project is on hold until the bug is fixed. Here’s the email from the ever helpful @StuartK.

General Info

This post is under construction… I will continue to update and add more content here based on conversation below.

Issue

Credit: @Tom Kneeland 

When using Intuit Practice Management (IPM), there are certain limitations that we will address here.

Possible countermeasures

  • Programmatically add or update roles using the API and Python (doable)
    • I have programmatically added roles with Python API calls
    • I’ll share code when I fully understand the issue
  • Automatically add roles using webhooks and a webhook handler like Azure Logic apps or Zapier (doable at a small cost)
  • Explore, submit feature ideas to fix issues with IPM (Subject to others)

More Information

Tom’s original post:

...I am an IPM user, which is still Karbon.  It turns out that IPM populates all of your tax jobs with no staff assignments to the role assignee.  Also, Intuit does not allow Excel bulk download and upload of these fields like Karbon does. 

I have used Pipedream and connected via API Karbon and Python.  I don't suppose you have ever written a Python script that would let me accomplish assigning all roes for tax jobs containing 2022 in the work title to:something like the following:

Admin on all work Admin roles = Joe

Partner on all work partner roles = John

Reviewer on all work Reviewer roles = Mary

Preparer on all work Preparer roles = Tom

 

Code Samples

Untested Pipedream automation that adds roles as soon as new work is created.

Notes:

  • User adds karbon keys as environment variables in Pipedream with the names:
    • “karbon_bearer_token_test”
    • “karbon_access_key_test”
    • feel free to update the names to “live” in environment and in code step if desired
  • There’s currently an issue with GET and PUT related to roles. Once I have a resolution from Karbon support, I will finish testing and update this post.
  • I have little experience in this area, so I welcome any feedback in the comments. Even if it’s to fix spelling errors. 😉

 add http trigger step like this: 

add python code step with this code: 

# regular imports for api calls
from requests import request as req
import json

# to get access to environment variables
import os

# to get access to previous steps
from pipedream.script_helpers import steps as webhook_results

# ** action required **
# set your roles (find keys in karbon in the url on the page of the role or profile)
roles = {
"UserRoleAssignments": [
{
"RoleKey": "3cmJV41hsXJ6", # admin
"UserProfileKey": "45Ps11p3D3ys" # Amelia
},
{
"RoleKey": "qbx11GGGqqX", # client manager
"UserProfileKey": "2DDTDy71QdjR" # Andi
}
]
}

# ** action required **
# set the appropriate work types
#
# leave 'target_work_types' empty to apply to all work types
# Add the target work types as text exactly how they are in karbon
#
# Example:
# target_work_types = {
# "Form 1040 - Individual Income Tax Return",
# "Form 1065 - Partnership Income Tax Return"
# }
# Notice the "," at the end of each line between records
# for readability, put each work type on its own line

target_work_types = {

}

# sets keys from environment variables
bearer_token = os.environ['karbon_bearer_token_test']
access_key = os.environ['karbon_access_key_test']


# retrieves the data from the webhook
webhook_body = webhook_results["trigger"]["event"]

# imports event from previous step
this_resource_type = webhook_body["ResourceType"]
this_action_type = webhook_body["ActionType"]
this_resources_permakey = webhook_body["ResourcePermaKey"]

# constant: api base url
base_url = "https://api.karbonhq.com/v3/"

# basic functions for use later
### standard api call function
def api_request(method,url,bearer_token, access_key, body=None):
"""
Make's API request and returns the response for 200 and 201 status codes.
Returns noting for 204. For all other status codes, returns nothing and prints
the status code and error message
"""
default_headers = {
'Content-Type': 'application/json', # Do not change. This tells Karbon how we are sending our request and how we would like the information returned
'Authorization': 'Bearer ' + bearer_token, # Do not change. This is how Karbon tells how is trying to use the api
'AccessKey': access_key # Do not change. This is how Karbon knows that you have permission to use the api
}
response = req(method, url, headers=default_headers, data=json.dumps(body)) # This accepts the response from Karbon which will be a success or error message
if response.status_code == 200 or response.status_code == 201: # if the request is sucessful, pass the json object
json_object = json.loads(response.text) # This picks up the text from Karbon and makes it a JSON object
return json_object # returns the json object
elif response.status_code == 204: # if the request body is empty
return
else: # if the request fails, print the error responses
print("Status code:")
print(response.status_code)
print("MESSAGE:")
print(json.dumps(response.json(),indent=2))
return

# checks webhook response to see if it's a new work item
if this_resource_type == "WorkItem" and this_action_type == "Inserted":

# builds the request url
url = base_url + "WorkItems/" + this_resources_permakey

# requests full work item
full_work_item = api_request('GET',url,bearer_token,access_key)

# checks to see if work types list is empty
# or if the work type matches one from your list
# and proceeds if so
if not(target_work_types) or full_work_item["WorkType"] in target_work_types:

# changes or adds roles to roles defined above
full_work_item.update(roles)

# PUT back to Karbon
api_request('PUT',url,bearer_token,access_key,full_work_item)

else pass # nothing happens if the work item doen't match one from the list

else pass # nothing happens if the webhook body doesn't contain a new work item

 

 


18 replies

Userlevel 7
Badge +19

I don’t use IPM, so I’ll try to synthesize what you mean before taking a stab at a countermeasure:

Your tax software syncs with IMP (whitelabeled Karbon sold by Intuit) and adds work items automatically to the practice management side of the software. I assume it adds work based on a templates mapped in some way to your tax software. When it does this, though, it doesn’t assign roles and it will take you quite some time to work through the list and assign all the roles, allowing you to take full advantage of the software.

Some questions:

  • Am I way off? lol
  • What is the tax software (this is a gap in my understanding of IPM)
  • Is it possible that you can assign roles at the template level and they will apply when adding work in the future? (doesn’t fix the current issue, but might make it a one-time thing)
  • Are you able to export lists from IPM of the work that doesn’t have roles? (specifically with the work keys visible)
Userlevel 4
Badge +5

Max,

 

  • Am I way off? No
  • What is the tax software (this is a gap in my understanding of IPM) It is Lacerte
  • Is it possible that you can assign roles at the template level and they will apply when adding work in the future? (doesn’t fix the current issue, but might make it a one-time thing) No, IMP/Lacerte does not allow for this. 
  • Are you able to export lists from IPM of the work that doesn’t have roles? (specifically with the work keys visible) Yes, I can download work with the work key in column A.

Thanks so much for the help.  Doing this at this late stage of tax season is “killing” me:)

Userlevel 7
Badge +19

 

Max,

  • Am I way off? No
  • What is the tax software (this is a gap in my understanding of IPM) It is Lacerte

Okay, this makes more sense to me now. And the work is getting created in IPM based on a trigger in Lacerte?

  • Is it possible that you can assign roles at the template level and they will apply when adding work in the future? (doesn’t fix the current issue, but might make it a one-time thing) No, IMP/Lacerte does not allow for this. 

That’s unfortunate. It might be worthwhile to put in a feature idea for this functionality.

  • Are you able to export lists from IPM of the work that doesn’t have roles? (specifically with the work keys visible) Yes, I can download work with the work key in column A.

Perfect. This may help with the cleanup.

Are you interested in getting this done automatically every time certain work items get created? If so, we could build the functions and deploy it to work on all “New” work that fires from a webhook, then apply the same functions to do the cleanup of already-entered work.

Doing the cleanup first is probably more urgent, but there may be work that slips through between completing the cleanup and initializing the automation, necessitating a second mini clean-up.

Userlevel 4
Badge +5

Are you interested in getting this done automatically every time certain work items get created? If so, we could build the functions and deploy it to work on all “New” work that fires from a webhook, then apply the same functions to do the cleanup of already-entered work. Yes.

However, I also need a script that will go in and assign the roles for 2022.  I exported all 2022 tax projects and added the roles columns to the far right, populated with names.  Now I just need to figure out how to push this back into Karbon/IPM.  The IMP AP{I is the same as the Karbon API. 

 

Userlevel 7
Badge +19

Sounds good. I also assume the roles exist on the work items already, but they are not populated. I have not tried to add a person to a role that didn’t exist on a work item, and I’m not sure what would happen. We can test it.

From a high level, what I suggest doing is building a function that does something like this:

for each key in list_of_keys:
     GET work item
     Add roles to the resulting JSON
     PUT updated result back to Karbon

For the automated part, it will work the same from a webhook handler:

When webhook for work item received:
     if webhook action equals created and work type equals [work type you want]
         GET work item
         add roles to the resulting JSON
         PUT updated result back to Karbon

I think I have all the code for this already, but I’m heading to a birthday party. I’ll add it here later.

Some questions:

  • Does Pipedrive handle webhooks?
  • If not, do you have a preference? (I have some experience with Azure and Zapier)

Incidentally, this process is exactly what I’m trying to do with the work schedules. When a work item is created from a specific work template (1040 individual income tax return), I want to automatically apply the appropriate work schedule with this “Webhook > GET > Change > PUT” workflow.

Userlevel 4
Badge +5

The roles do exist, but are not populated.  I used pipedrive today just to see if I could make it connect.  My preference would be to code this in Zapier. However, we can stick with pipedrive as it does do webhooks.

 

Thanks a million,

Tom

 

Userlevel 7
Badge +19

Zapier can handle the webhooks, too.

I think Zapier might be more complicated than pipe drive based on my quick overview, but we can compare.

Userlevel 4
Badge +5

Pipedream it is then. Pipedream does python, Java, or web hooks.  Would love to get this done. 🙏

Userlevel 4
Badge +5

@max Any epiphany overnight 😊

Userlevel 7
Badge +19

I signed up for pipedream and have the automation almost complete. Pipedream has some peculiarities I haven’t quite worked out yet. As soon as I do, I’ll post the code here and update the first post.  

Userlevel 4
Badge +5

Thanks a million!

Tom

Userlevel 7
Badge +19

Okay, I got it working, however there seems to be an issue with the API and roles are currently not populating in the GET request and are not responding to the PUT request. I sent a support ticket to the development team and will get back to you as soon as I can.

One other option I thought about this morning would be to reset the work to the template. If you have an Annual Service Plan addon, your Karbon CSM can do a batch update to all your open work (or the work you select) and reset it to the template to bring in the role assignments. I tested resetting the work to the template and it does bring in the role assignments.

That doesn’t solve the ongoing issue, but it may clear your backlog for now.

Something we have been testing in our office is having the first step of any recurring work to be to reset the work to the template so that updated steps and instructions flow through to the new work. I don’t know if that makes sense for your office now.

Userlevel 4
Badge +5

@max unfortunately I can’t reset to the template says it will break the link to the link to Lacerte.  Counting on the development team.  😊

Userlevel 7
Badge +19

That’s strange, but I don’t know that product.

I updated the original post with code sample code for you to look at and get started with the setup. It’s untested since the roles aren’t exposed in the api right now. I’ll test and update the original post when I hear back from support.

Userlevel 4
Badge +5

@max Would you be willing to invite me into your pipedream account to resolve this together?

email is tkneeland@kneelandcpa.​com

Userlevel 7
Badge +19

@Tom Kneeland, bad news… the ability to GET and PUT roles isn’t available in the API, so this plan is bust for now. It’s a bug in the API that won’t get fixed in the near future. Here’s the email I got from Stuart King:

That leaves us with few options. One thing you could do is contact your CSM here:

They may be able to help you, or point you to other resources within Karbon support who might help.

If you don’t have that menu, hit up Karbon chat support and they can get you connected with a CSM.

Userlevel 4
Badge +5

@max I got dead ended here.  On another front do you know if I can use the API to add “people” contacts to an existing Client group?

 

Thanks a million!
Tom

Userlevel 7
Badge +19

Hi Tom,

I’m not sure. I think it might be possible, but I’ll have to test it.

Been doing a lot of unplanned traveling so my communication has been intermittent.

Reply