I am working on an automation script to push out emails based on tickets we receive from our CRM.
Is there a way for the collaborator_ids to take multiple emails? I've tried using email_ccs and email_ccs_ids with no luck. Below is what I am currently using to include one CC'd email address.
zenpy_client.tickets.update(Ticket(id=i.id, requester=User(email=roster_email, name=name), collaborator_ids=cc_email))
I've also tried: collaborator_ids=(cc_email, cc_email2)
This will work (even if there are internal notes in the ticket):
# Add CC
url = "https://{sub}.zendesk.com/api/v2/tickets/{id}"
payload = json.dumps({
"ticket": {
"email_ccs": [
{
"user_email": "new#email.com",
"action": "put"
}
]
}
})
headers = {
'Authorization': 'Basic {token}',
'Content-Type': 'application/json'
}
response = requests.request("PUT", url, headers=headers, data=payload)
print(response.text)
You could get the ticket ID from ZenPy like facetoe showed here:
ticket_audit = zenpy_client.tickets.create(Ticket(description='test', subject='test'))
print(ticket_audit.ticket.id) # Ticket ID of last created ticket
Related
I have an Azure DevOps project with multiple iteration paths:
If I use this Azure Python API (https://github.com/microsoft/azure-devops-python-api) to create a new work item and set /fields/System.IterationPath to have a value that already exists like RTC-ADS\PI28\Sprint 28-3 it will create the work item with no issue.
But if I try to create a work item with an iteration that does not yet exist such as RTC-ADS\PI27 it will fail with an error
ERROR:root:Error creating ADS work item: TF401347: Invalid tree name given for work item -1, field 'System.IterationPath'.
I could create PI27 manually in my Azure Project settings, but is there a way I can use this Azure Python API to create a new iteration value for PI27 by making a POST request or something?
I have found documentation supporting how to do so I believe:
https://learn.microsoft.com/en-us/rest/api/azure/devops/work/iterations/post-team-iteration?view=azure-devops-rest-6.0
But is it possible to add a new iteration value using this API?
https://github.com/microsoft/azure-devops-python-api
Thanks
EDIT
I've been trying to get a POST request working to add a new iteration path:
pat = CONFIG.personal_access_token
authorization = str(base64.b64encode(bytes(':'+pat, 'ascii')), 'ascii')
headers = {
'Accept': 'application/json',
'Authorization': 'Basic '+authorization
}
response = requests.post(
url="https://dev.azure.com/ADSP-Org-A03/RTC-ADS/_apis/work/teamsettings/iterations?api-version=6.0&iteration=apple&startDate=2021-01-01&endDate=2021-01-11",
headers=headers
)
print(response.text)
But this results in an error:
{"$id":"1","innerException":null,"message":"Value cannot be null.\r\nParameter name: iteration","typeName":"System.ArgumentNullException, mscorlib","typeKey":"ArgumentNullException","errorCode":0,"eventId":0}
which i am trying to solve, is my request formatted incorrectly? I cant find a working example online for adding an iteration path to an ADS project
The first approach you've taken should be correct, but I think you're passing the request data incorrectly. It should be something like
pat = CONFIG.personal_access_token
authorization = str(base64.b64encode(bytes(':'+pat, 'ascii')), 'ascii')
iteration_id = "" # add id here
headers = {
'Accept': 'application/json',
'Authorization': 'Basic '+authorization
}
attributes = {"startDate":"2021-01-01", "endDate": "2021-01-11"}
data = {"id": iteration_id, "attributes": attributes}
let url = "https://dev.azure.com/ADSP-Org-A03/RTC-ADS/_apis/work/teamsettings/iterations?api-version=6.0"
response = requests.post(url=url, headers=headers, json=data)
print(response.text)
Alternatively, for the classification nodes approach, the data you're using is incorrect. It should be
data = {
"name":"Wk 18.02 - 18.03",
"attributes": {
"startDate":"8 january 2018 GMT",
"finishDate":"21 january 2018 GMT"
}
}
I have registered the app, added read-write permissions on it, gotten admin consent, and gotten the token. When I make a GET request I get an error.
This my Python code:
import requests, sys, os, json
# Get token
params = {
'client_id': clientID,
'scope': 'https://graph.microsoft.com/.default',
'client_secret': clientSecret,
'grant_type': 'client_credentials'
}
response = requests.post('https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token', data=params)
jresp = response.json()
access_token = jresp['access_token']
# Get item
header = {'Authorization': 'Bearer ' + access_token}
response = requests.get('https://graph.microsoft.com/v1.0/me/drive/root:/Documents/WildRydes.txt', headers = header)
print response
print response.text
print response.content
sys.exit()
This is what is returned:
<Response [500]>
{
"error": {
"code": "BadRequest",
"message": "Unable to retrieve user's mysite URL.",
"innerError": {
"request-id": ,
"date": "2020-04-29T12:42:06"
}
}
}
I have been following the Microsoft Graph API documentation for the past two days straight. They are very good at theory but rubbish at showing concrete examples. Or maybe they're good at hiding where those are.
I am developing App leveraging Microsoft Graph using Python 3.6.
I am getting very strange behavior when requesting Graph API which uses request data as nested JSON.
This is a successful request:
url = f "https://graph.microsoft.com/v1.0/users/{user_id}"
headers = {
'Authorization': f 'Bearer {office365_access_token}',
'Content-Type': 'application/json'
}
data = {
"city": "Tokyo"
}
req = urllib.request.Request(url, json.dumps(data).encode("utf-8"), headers = headers, method = 'PATCH')
urllib.request.urlopen(req)
The next snipped fails with an HTTP Error 400 error. The documentation states that the skills property is a String Collection, so I used an Array of String values:
url = f "https://graph.microsoft.com/v1.0/users/{user_principal_name}"
headers = {
'Authorization': f 'Bearer {office365_access_token}',
'Content-Type': 'application/json'
}
data = {
"skills": ["swift", "python"]
}
req = urllib.request.Request(url, json.dumps(data).encode("utf-8"), headers = headers, method = 'PATCH')
urllib.request.urlopen(req)
The only difference is whether the value is a string or not. I can dump the data dictionary to a JSON string, so I don't think the code is wrong but I do not know why this error occurres.
It appears to be a bug related with Microsoft Graph itself, specifically with User update operation. For example the following query:
PATCH https://graph.microsoft.com/v1.0/me
Content-type: application/json
{
"skills": [
"Fortran",
"Cobol"
],
"city": "Helsinki"
}
indeed fails and returns the following error:
{
"error": {
"code": "BadRequest",
"message": "The request is currently not supported on the targeted entity set"
}
}
At the same time updating another User properties, for example User.otherMails property which has the same Collection(Edm.String) type as User.skills:
PATCH https://graph.microsoft.com/v1.0/me
Content-type: application/json
{
"otherMails": [
"office365admin#gmail.com",
"office365admin#yahoo.com"
],
"city": "Helsinki"
}
completes successfully.
Workaround
It appears it fails when skills property of User resource is getting updated along with another properties. But if only a skills property is getting updated
PATCH https://graph.microsoft.com/v1.0/me
Content-type: application/json
{
"skills": [
"Fortran",
"Cobol",
"C"
]
}
no error occurs and the operation successfully completes.
currently I am using eBay Trading API with Python. Thanks to: https://github.com/timotheus/ebaysdk-python
I used https://github.com/luke-dixon/django-ebay-accounts to get tokens for user.
Now, I would like to use Restful API (https://developer.ebay.com/docs#Acc). I don't think I can use tokens I have already. So, I managed thanks to Getting an Ebay OAuth Token get one. But I think I missing something, because during the process I cannot include info for user (name/password), so, for example https://api.ebay.com/sell/fulfillment/v1/order?limit=10 returns:
{
"errors": [{
"errorId": 1100,
"domain": "ACCESS",
"category": "REQUEST",
"message": "Access denied",
"longMessage": "Insufficient permissions to fulfill the request."
}]
}
Any idea how can I get a token for the user?
Just snippet of code to make things more clear:
AppSettings = {
'app_id': EBAY_PRODUCTION_APPID,
'app_secret': EBAY_PRODUCTION_CERTID,
'dev_id': EBAY_PRODUCTION_DEVID,
'ruName': EBAY_PRODUCTION_RU_NAME
}
authHeaderData = AppSettings['app_id'] + ':' + AppSettings['app_secret']
encodedAuthHeader = base64.b64encode(authHeaderData.encode())
headers = {
"Content-Type": "application/x-www-form-urlencoded",
"Authorization": "Basic ".encode() + encodedAuthHeader
}
body = {
"grant_type": "client_credentials",
"redirect_uri": settings.EBAY_PRODUCTION_RU_NAME,
"scope": "https://api.ebay.com/oauth/api_scope"
}
data = urllib.parse.urlencode(body)
tokenURL = "https://api.ebay.com/identity/v1/oauth2/token"
response = requests.post(tokenURL, headers=headers, data=body)
authDict = response.json()
So the request to run I need is:
r = requests.get("https://api.ebay.com/sell/fulfillment/v1/order?limit=10",
headers={"Authorization": "{}".format(authDict['access_token']),
"Content-Type": "application/json",
"X-EBAY-C-MARKETPLACE-ID": "EBAY_UK",
"Accept": "application/json"
})
According to this, I believe you are supposed to use the following authorization header:
headers['Authorization'] = "Bearer " + USER_ACCESS_TOKEN
Where the USER_ACCESS_TOKEN is the massive token generated on this page.
It looks something like this:
'v^1.1#i^1#p^3#f^0#I^3#r^0#t^ ...
...
...
...
... bfxr8BJtphi2M/oo2xpYo2hiMWxmZt4fVzS7qe2tMXUSAAA='
The Authorization you are using is for requests that aren't linked to a specific user account (search results, meta data for items, etc.). To make requests that are for specific users (eg. orders or inventory updates), you have to get their permission via their USER_ACCESS_TOKEN.
If you need help getting the USER_ACCESS_TOKEN let me know and I'll update.
Note that I have been trying to do the same thing that you are doing for about 6 hours now, and still haven't figured it out, so I am not confident in this answer.
Hope this helps. If you do figure it out, you should post an answer so others can too (ie myself xD).
eBay definitely wins the gold metal for worst api docs in the history of api docs...
The API Explore # developer.ebay.com has description of HTTP Headers for each RestFul API. E.G. Fulfillment API - getOrdres:
HTTP Headers
Authorization:Bearer <OAUTH_token>
Accept:application/json
Content-Type:application/json
Sample code:
import requests,json
headers = {
"Authorization": "Bearer Type_Your_Token_here_or_Paste_IF_too_long",
'Accept':'application/json',
'Content-Type':'application/json'
}
EndPoint = "https://api.ebay.com/sell/fulfillment/v1/order?filter=orderfulfillmentstatus:%7BNOT_STARTED|IN_PROGRESS%7D"
response = requests.get(EndPoint,headers = headers)
https://newbedev.com/ebay-oauth-token-and-refresh-tokens has introduced eBay OAuth token much better than eBay.
By the way, "grant_type": "client_credentials" is only valid for clients who can on have one scope. https://api.ebay.com/oauth/api_scope.
A shortcut to get your code run: the refresh token is actually the token you have for standard API, which is valid for 18 months. With a refresh token, you can get token without getting the annoying "authorization code" via user consent.
In short, please use refresh token to get user access token for the restful API.
Hope the above helps.
I am trying (legitimately and with the go ahead from the site)to log into the betting exchange matchbook.com through their api.
The documentation states:
To Login: https://www.matchbook.com/bpapi/rest/security/session
and
Example Request
POST /security/session
{
"username": "j_henry",
"password": "******"
}
Example Response
{
"session-token": "1418_1234567890",
"user-id": 1418,
"account": { // Same as GET /account API response.
...
}
}
I am using Requests and have the following code:
payload = {"username": "********", "password": "************"}
r = requests.post('https://www.matchbook.com/edge/rest/security/session', data=payload)
print (r.status_code)
I get error code 415? I must be getting the wrong type of response??
I have looked at a lot of very similar posts on here, and I am about to ask matchbook's team, but before I do has anybody got any ideas?
You might have to specify Content-Type, try to add a header to tell the server it's JSON formatted:
payload = {"username": "********", "password": "************"}
headers = {"Content-Type": "application/json;"}
r = requests.post('https://www.matchbook.com/edge/rest/security/session', data=payload, headers=headers)
print (r.status_code)
It does not appear from your code that you are JSON-encoding your payload. The endpoint is likely expecting JSON.
Try this:
payload = '{"username": "********", "password": "************"}'