07-11-2023 11:30 AM
Good Day,
Im playing around a little with the sample python code created by dekwan ( https://github.com/CiscoDevNet/finesse-sample-code/tree/master/NonGadgetPythonSample )
using REST APIs and python to see/change agent states, with the end game of checking for agents in 50002 state and change them back to their previous state.
Long before there at step 1, Im just trying to get the sample code running. We're running Finesse 11.6
Im starting with dekwan's code with no changes except updating the
URL / domain / finesse user login id and pw / scheme (http or https) and port
For the latter 2 Im using https and port 8445 (Ive tried other ports and http with other ports) - for user id and pw Im using a finesse agent login that I am able to successfully log in with interactively. - for the URL Im using the host and domain portion of the same url Id use to log into finesse interactively.
however on 'Executing GET 'https://finesseSvr.ourCompany.com:8445/finesse/api/User/myUser' I get a string of various errors similar to this:
GET User - ID: myUser
REST API URL is: 'https://finesseSvr.ourCompany.com:8445/finesse/api/User/myUser'
Executing GET 'https://finesseSvr.ourCompany.coms.com:8445/finesse/api/User/myUser'
C:\Program Files (x86)\Python38-32\lib\site-packages\urllib3\connectionpool.py:979: InsecureRequestWarning: Unverified HTTPS request is being made to host 'myUser.com'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
warnings.warn(
GET() - Status: 401
GET() - Text: <ApiErrors>
<ApiError>
<ErrorType>Invalid Authorization User Specified</ErrorType>
<ErrorData>myuser</ErrorData>
<ErrorMessage>The user specified in the authentication credentials and the uri don't match</ErrorMessage>
</ApiError>
</ApiErrors>
I DO, subsequently, get a successful connection to XMPP
"Connecting to the Finesse Notification Service.
Waiting 2 seconds to establish a connection.
The XMPP connection is successful."
but on the subsequent puts, etc I continue to get the 401s (along with the '<ErrorType>User does not belong to Supervisor's Teams</ErrorType>' Errors. (BTW 'myUser' is a supervisor of all teams as well as an agent)
Ive read a couple of other threads in places where it seemed the problem was usually the agent id/pw but Ive double and triple checked that unless Im misunderstanding and should be using some other credentials.
Does anyone have any suggestions on how I can move forward?
thanks
Solved! Go to Solution.
07-12-2023 01:14 PM
Wait! I Got it thanks to a tip in another post by dekwan
"Scenario 1 should work as far as agents being able to access their own information. For UCCE, you must use the agentId rather than the agent login name. So in your case, it should be /finesse/User/47483650"
Thanks for your help!
07-13-2023 09:03 AM
Hi @Keith Abbott ,
The unique reason code IDs are system generated and not exposed to the users directly. What you have passed might be the numeric reason code that you created.
For retrieving the reason code IDs belonging to the reason codes associated with a particular agent's team, you can issue a GET request on the resource /finesse/api/User/<user-id>/ReasonCodes?category=<NOT_READY|LOGOUT|ALL>.
Please refer to https://developer.cisco.com/docs/finesse/#!user%e2%80%94get-reason-code-list/userget-reason-code-list
Here is a sample response:
#> curl -k https://finesse-primary-node:8445/finesse/api/User/1001050/ReasonCodes?category=NOT_READY -u '1001050:pwdfor50'
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ReasonCodes category="NOT_READY">
<ReasonCode>
<uri>/finesse/api/ReasonCode/7618</uri>
<id>7618</id>
<category>NOT_READY</category>
<code>25137</code>
<label>Tea break</label>
<forAll>true</forAll>
<systemCode>false</systemCode>
</ReasonCode>
<ReasonCode>
<uri>/finesse/api/ReasonCode/7619</uri>
<id>7619</id>
<category>NOT_READY</category>
<code>26960</code>
<label>Lunch Break</label>
<forAll>true</forAll>
<systemCode>false</systemCode>
</ReasonCode>
<ReasonCode>
<uri>/finesse/api/ReasonCode/7622</uri>
<id>7622</id>
<category>NOT_READY</category>
<code>48673</code>
<label>Other</label>
<forAll>true</forAll>
<systemCode>false</systemCode>
</ReasonCode>
</ReasonCodes>
Regards,
Renjith Alexander
07-11-2023 12:17 PM - edited 07-12-2023 12:49 PM
Hi @Keith Abbott ,
For calling the API endpoint /finesse/api/User/myUser, the credentials(loginid & pwd) used should be of the user 'myUser' itself, or the administrator. For security reasons, one user's data cannot be accessed by another user's credentials. The error clearly says that the user ID in the URL and in the authentication header are different.
This holds good for PUT requests too(here additionally the supervisor can change state). Looks like the login ID and password that you set are not of 'myUser'
Update: Edited. Supervisor of the user cannot access the User object of another user. Only the user or the administrator can access the User details.
Regards,
Renjith Alexander
07-11-2023 12:21 PM
Thanks for the reply realexan,
Let me see if I can review the code and see where its falling down
07-12-2023 11:02 AM
Hi realexan,
I hate to be a slow-coach but Im still not finding the problem.
I added a buncha print statements in each sub, to see where things were going and what was being passed, and it all looked good minus the part where it fails.
The first thing (non-setup) it hits is sub __init__, which code is:
def __init__(self, username, password, scheme, fqdn, port, domain):
# Get the information from the config file
print("INsub __init__")
print ("UN '%s'\n" % username)
print ("PW '%s'\n" % password)
print ("scheme '%s'\n" % scheme)
print ("fqdn'%s'\n" % fqdn)
print ("port '%s'\n" % port)
print ("domain '%s'\n" % domain)
self.scheme = scheme
self.fqdn = fqdn
self.port = port
self.domain = domain
self.username = username
self.password = password
# Call the GET user API (and store the XML response)
self.getUser(id=self.username)
# Establish a connection to the Finesse Notification Service
self.xmppConnection = Jabber(self.username, password, self.domain)
self.xmppConnection['feature_mechanisms'].unencrypted_plain = True
print("Connecting to the Finesse Notification Service.")
if self.xmppConnection.connect(address=(self.fqdn, 5222), use_tls=False, use_ssl=False):
print("Waiting 2 seconds to establish a connection.")
self.xmppConnection.process(block=False)
# Need to wait a couple of seconds before calling a REST API
self.waitForNotification()
print("The XMPP connection is successful.")
else:
print("Failed to connect to XMPP.")
sys.exit(0)
print("OUT __init__")
This code results in output/error(each sub call is bounded by an INsub/OUTsub print statement pair:
INsub __init__
UN 'myUser'
PW '12345abc'
scheme 'https'
fqdn'finesseSVR.ourCompany.com'
port '8445'
domain 'ourCompany.com'
INsub getUser
GET User - ID: myUser
INsub getURLPrefix
REST API URL is: 'https://finesseSVR.ourCompany.com:8445/finesse/api/User/myUser'
OUTsub getURLPrefix
Executing subGET 'https://finesseSVR.ourCompany.com:8445/finesse/api/User/myUser'
UN'myUser'
PW'12345abc'
C:\Program Files (x86)\Python38-32\lib\site-packages\urllib3\connectionpool.py:979: InsecureRequestWarning: Unverified HTTPS request is being made to host 'finesseSVR.ourCompany.com'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
warnings.warn(
Insub printRESTAPIResponse
GET() - Status: 401
GET() - Text: <ApiErrors>
<ApiError>
<ErrorType>Invalid Authorization User Specified</ErrorType>
<ErrorData>myUser</ErrorData>
<ErrorMessage>The user specified in the authentication credentials and the uri don't match</ErrorMessage>
</ApiError>
</ApiErrors>
OUTsub printRESTAPIResponse
OUTsub getUser
IN CLASS Jabber
self'<__main__.Jabber object at 0x02EEACA0>'
UN 'myUser'
PW '12345abc'
domain '%s'<blank>'%s'
OUT CLASS Jabber
Connecting to the Finesse Notification Service.
Waiting 2 seconds to establish a connection.
The XMPP connection is successful.
OUT __init__
As you can see (or at least as it appears to me) Im passing the same creds each time. Those creds are for my agent which is a member of a team on which Im a supervisor, so covered both ways. It appears to die at sub 'printRESTAPIResponse' which code is this:
def printRESTAPIResponse(prefix='printRESTAPIResponse()', response=''):
"""
Print the REST API response with the HTTP Request status code
and the Response body text
"""
print("Insub printRESTAPIResponse")
print (prefix + " - Status: ", response.status_code) # This is the http request status
print (prefix + " - Text: ", response.text)
print ("\n")
print("OUTsub printRESTAPIResponse")
Any thoughts/pointings on where to go from here?
Thx
07-12-2023 01:14 PM
Wait! I Got it thanks to a tip in another post by dekwan
"Scenario 1 should work as far as agents being able to access their own information. For UCCE, you must use the agentId rather than the agent login name. So in your case, it should be /finesse/User/47483650"
Thanks for your help!
07-12-2023 02:32 PM
Great.... I thought 'myUser' was a placeholder for the actual user ID, as you didn't want to expose agent IDs here.
07-13-2023 05:57 AM
That was indeed true, but it did mask a user login rather than a userID.
Now just trying to figure out why
PUT() data:
<User>
<state>NOT_READY</state>
</User>
Gives error
PUT() - Status: 400
PUT() - Text: <ApiErrors>
<ApiError>
<ErrorType>Parameter Missing</ErrorType>
<ErrorData>finesse.api.reasoncode.require_reasoncode</ErrorData>
<ErrorMessage>The state change requires a valid reason code.</ErrorMessage>
</ApiError>
</ApiErrors>
I assume (as it says) that a reason code is required when changing states. But Ive tried using both the ReasonCodeID, and ReasonCode (5004 and 1008) as strings and both produce this (with appropriate number)
PUT() data:
<User>
<state>NOT_READY</state>
<reasonCodeId>5004</reasonCodeId>
</User>
PUT() - Status: 400
PUT() - Text: <ApiErrors>
<ApiError>
<ErrorType>Invalid Input</ErrorType>
<ErrorData>finesse.api.reasoncode.not_valid</ErrorData>
<ErrorMessage>The Reason Code specified in the request does not exist</ErrorMessage>
</ApiError>
</ApiErrors>
Interestingly, 1008 gives a slightly different error:
404 and ReasonCode does not exist, codeId=1008</ErrorMessage>
Is ReasonCodeID the correct code to use (vs ReasonCode)?
Any thoughts on why the correct one is saying it doesnt exist? I have verified the 1008/5004 code is a reason code available for my team.
thanks
07-13-2023 09:03 AM
Hi @Keith Abbott ,
The unique reason code IDs are system generated and not exposed to the users directly. What you have passed might be the numeric reason code that you created.
For retrieving the reason code IDs belonging to the reason codes associated with a particular agent's team, you can issue a GET request on the resource /finesse/api/User/<user-id>/ReasonCodes?category=<NOT_READY|LOGOUT|ALL>.
Please refer to https://developer.cisco.com/docs/finesse/#!user%e2%80%94get-reason-code-list/userget-reason-code-list
Here is a sample response:
#> curl -k https://finesse-primary-node:8445/finesse/api/User/1001050/ReasonCodes?category=NOT_READY -u '1001050:pwdfor50'
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ReasonCodes category="NOT_READY">
<ReasonCode>
<uri>/finesse/api/ReasonCode/7618</uri>
<id>7618</id>
<category>NOT_READY</category>
<code>25137</code>
<label>Tea break</label>
<forAll>true</forAll>
<systemCode>false</systemCode>
</ReasonCode>
<ReasonCode>
<uri>/finesse/api/ReasonCode/7619</uri>
<id>7619</id>
<category>NOT_READY</category>
<code>26960</code>
<label>Lunch Break</label>
<forAll>true</forAll>
<systemCode>false</systemCode>
</ReasonCode>
<ReasonCode>
<uri>/finesse/api/ReasonCode/7622</uri>
<id>7622</id>
<category>NOT_READY</category>
<code>48673</code>
<label>Other</label>
<forAll>true</forAll>
<systemCode>false</systemCode>
</ReasonCode>
</ReasonCodes>
Regards,
Renjith Alexander
07-13-2023 09:34 AM
Perfect!
Thanks Realexan.
My ver came up a little different than your sample response but I used the URI code and it worked like a charm:
ReasonCodes category="NOT_READY">
<ReasonCode>
<uri>/finesse/api/ReasonCode/33</uri>
<category>NOT_READY</category>
<code>1008</code>
<label>IS Problem</label>
<forAll>false</forAll>
<systemCode>false</systemCode>
</ReasonCode>
<ReasonCode>
Hopefully with the tools you provided I can move forward!
07-13-2023 09:43 AM - edited 07-13-2023 09:43 AM
Glad to hear that it helped.
You must be using an older release of Finesse. The more recent versions have the ID as part of the URL as well as within a separate tag.
Regards,
Renjith Alexander
Discover and save your favorite ideas. Come back to expert answers, step-by-step guides, recent topics, and more.
New here? Get started with these tips. How to use Community New member guide