kyleweise
(Kyle Weise)
April 26, 2024, 2:21pm
1
Hello all!
There are bits and pieces of documentation that relate to this topic, but none that explicitly show how to use this mutation from Python (that I’ve been able to find).
Basically, I’d like the query set up so that I have dynamic variables for both file
(the image being uploaded) and item_id
(the Item to which the image is uploaded to).
Does anyone have an example script showing how this is done? Here is what I’ve tried so far:
import requests
import json
import os
import pandas as pd
from pprint import pp
apiKey = os.getenv("MONDAY_API_TOKEN")
apiUrl = "https://api.monday.com/v2"
headers = {"Authorization" : apiKey}
url = "https://api.monday.com/v2/file"
payload = {'query': 'mutation add_file($file: File!, $item: ID!) {add_file_to_column (item_id: $item, column_id:"files__1" file: $file) { id } }'}
variables = {
'file': open('/path/to/my/file.svg', 'rb'),
'item_id': '6530743418'
}
payload['variables'] = variables
response = requests.post(url, headers=headers, data=payload)
pp(response.headers)
Appreciate any help.
Best,
-Kyle
dipro
(Dipro Bhowmik)
April 26, 2024, 5:39pm
2
There are two issues with your request (that I can see):
You need to make a multipart request, which typically will require a different syntax than a regular POST request.
You need to send three parts – a query, a map (which maps the ‘parts’ of your request to variables), and then the variables themselves (including the file).
You can refer to this working Postman example to see how the final HTTP requests should look.
From some Googling, looks like passing the files
argument to requests.post
will make it a multipart: How to send a "multipart/form-data" with requests in python? - Stack Overflow
So the syntax is something like this (pardon if my Python is rusty):
apiUrl = "https://api.monday.com/v2"
apiQuery = 'mutation add_file($file: File!, $item: ID!) {add_file_to_column (item_id: $item, column_id:"files__1" file: $file) { id } }'
apiMap = json.dumps({"image" : "variables.file", "item" : "variables.item_id"})# please check if this syntax is correct
payload = {
'query': apiQuery,
'map': apiMap,
'file': open('/path/to/my/file.svg', 'rb'),
'item': '6530743418'
}
response = requests.post(url, headers=headers, files=payload) # this is where you're using the 'files' argument to make a multipart request
kyleweise
(Kyle Weise)
April 26, 2024, 7:25pm
3
@dipro Appreciate your response! I made some changes, but am still running into issues (receiving 500 Internal Server Error
’s):
I am using the /file
API, not the base one.
I changed the item
key of payload
to match the value of the corresponding key-value pair in apiMap
.
I set the correct file path to the file I want to upload (not including here for security)
url = "https://api.monday.com/v2/file"
apiQuery = 'mutation add_file($file: File!, $item: ID!) {add_file_to_column (item_id: $item, column_id:"files__1" file: $file) { id } }'
apiMap = json.dumps({"image" : "variables.file", "item" : "variables.item_id"})
payload = {
'query': apiQuery,
'map': apiMap,
'file': open('/path/to/my/file.svg', 'rb'),
'item_id': '6530743418'
}
response = requests.post(url, headers=headers, files=payload)
print(response.status_code)
print(response.reason)
dipro
(Dipro Bhowmik)
April 29, 2024, 3:34pm
4
The add_file mutation is a bit fussy and will return a 500 status more often than the other ones…
Anyway, looking at the above, your map is wrong – the parts of the HTTP form should correspond to the left-hand-side of the map JSON.
So if your map is:
{ "image" : "variables.file" }
The API will expect to get an HTTP part called “image”. In your code above, it gets “file”.
Try one of these instead:
url = "https://api.monday.com/v2/file"
apiQuery = 'mutation add_file($file: File!, $item: ID!) {add_file_to_column (item_id: $item, column_id:"files__1" file: $file) { id } }'
apiMap = json.dumps({"image" : "variables.file", "item" : "variables.item_id"})
payload = {
'query': apiQuery,
'map': apiMap,
'image': open('/path/to/my/file.svg', 'rb'),
'item': '6530743418'
}
response = requests.post(url, headers=headers, files=payload)
print(response.status_code)
print(response.reason)
Or perhaps better…
url = "https://api.monday.com/v2/file"
apiQuery = 'mutation add_file($file: File!, $item: ID!) {add_file_to_column (item_id: $item, column_id:"files__1" file: $file) { id } }'
apiMap = json.dumps({"file" : "variables.file", "item_id" : "variables.item_id"})
payload = {
'query': apiQuery,
'map': apiMap,
'file': open('/path/to/my/file.svg', 'rb'),
'item_id': '6530743418'
}
response = requests.post(url, headers=headers, files=payload)
print(response.status_code)
print(response.reason)
If this doesn’t work, it’s worth opening a ticket at this form so we can get your account info and look up error logs on our side!
kyleweise
(Kyle Weise)
April 29, 2024, 5:18pm
5
Appreciate the follow up @dipro . Your code did not work, but I’d like to provide some code that did and maybe you can help me expand from there. The following (based on the Python-Requests code snippet provided by the Postman example here ), did in fact work:
import requests
import json
import os
import pandas as pd
apiKey = os.getenv("MONDAY_API_TOKEN")
headers = {"Authorization" : apiKey, 'API-version':'2023-10'}
url = "https://api.monday.com/v2/file"
payload = {
'query': 'mutation add_file($file: File!) {add_file_to_column (item_id: 6530743418, column_id:"files__1" file: $file) {id}}',
'map': '{"image":"variables.file"}'
}
files=[
('image',('file',open('/path/to/my/file.svg','rb'),'application/octet-stream'))
]
response = requests.post(url, headers=headers, data=payload, files=files)
print(response.text)
print(response.reason)
Now, I just need some guidance on how to also pass item_id
as a dynamic variable argument to the query. I know that the query itself would probably look something like:
mutation add_file($file: File!, $item_id: ID!) {add_file_to_column (item_id: $item_id, column_id:"files__1" file: $file) {id}}
but it is unclear to me where to put the Python variable containing the item_id
so that it gets interpreted properly.
Appreciate your help.
1 Like
dipro
(Dipro Bhowmik)
April 29, 2024, 7:08pm
6
Ah great, glad you got something working.
If you want to add the item ID as a variable, add it to three places:
The query
The map – in the format { "key_in_http_form" : "variables.variable_name_in_query}
As a key in the form (aka the payload
variable above)
payload = {
'query': 'mutation add_file($file: File!, $item_id:ID!) {add_file_to_column (item_id: $item_id, column_id:"files__1" file: $file) {id}}',
'map': '{"image":"variables.file", "item" : "variables.item_id"}',
'item' : 6530743418
}
files=[
('image',('file',open('/path/to/my/file.svg','rb'),'application/octet-stream'))
]
response = requests.post(url, headers=headers, data=payload, files=files)
1 Like
kyleweise
(Kyle Weise)
April 29, 2024, 8:37pm
7
Thanks so much @dipro ! Appreciate your help, this worked wonderfully. I have a few follow-up questions.
One thing that’s unexpected:
When I navigate to the Board/Item of interest, the ‘files’ column does not actually show the image preview, but instead a file attachment icon, with options to download/etc.
Please tell me there is a way to display the image itself. Seems to be a previously identified issue .
Also, does the API support giving a name to the file? It seems it does not use the original filename, and something a bit more descriptive than file
would be preferred.
Thanks again
Hello there @kyleweise what type of file is that?
There is no way to select a name for the file when uploading it via API.
Looking forward to hearing from you!
Cheers,
Matias
kyleweise
(Kyle Weise)
May 1, 2024, 12:18pm
9
Hello @Matias.Monday !
It is a .svg
image file. The other issue I linked to seems to have the same behavior with pdf
’s (although it didn’t look like they were using the API), so I’m not sure it’s a file type-specific problem.
Hello again @kyleweise ,
I could not reproduce the issue.
Would you be able to please fill this form (https://support.monday.com/hc/en-us/requests/new?ticket_form_id=13855862562962 ) adding as much information as possible to it (such as account ID, board IDs, item IDs, timestamps, etc.) so that our team can take a look into it?
Looking forward to hearing from you via the form!
Cheers,
Matias
kyleweise
(Kyle Weise)
May 13, 2024, 2:18pm
11
For completeness, this is the what the Technical Support Engineer sent me which helped me solve my issue:
import requests
import json
import os
import pandas as pd
apiKey = "token"
headers = {"Authorization" : apiKey, 'API-version':'2023-10'}
url = "https://api.monday.com/v2/file"
payload = {
'query': 'mutation add_file($file: File!) {add_file_to_column (item_id: 123456789, column_id:"files__1" file: $file) {id}}',
'map': '{"image":"variables.file"}'
}
files=[
('image',('test.png',open('test.png','rb'),'image/png'))
]
response = requests.post(url, headers=headers, data=payload, files=files)
print(response.text)
print(response.reason)
I needed to:
set the header correctly: image/png
, not application/octet-stream
specify the file type both in the name of the file: test.png
, and the actual file itself: open('test.png', 'rb')
Thank you @kyleweise for sharing this!
Flowsen
(Florian)
December 8, 2024, 10:39am
13
@Matias.Monday could it be that something changed in the API?
My older integrations that used moncli stopped working. So I started from scratch in python and reading the suggestions in this thread.
None of them worked for me, this is what I tried:
import requests
apiKey = MONDAY_APIKEY
headers = {"Authorization" : apiKey, 'API-version':'2023-10'}
url = "https://api.monday.com/v2/file"
payload = {
'query': 'mutation add_file($file: File!) {add_file_to_column (item_id: 8005103588, column_id:"datei" file: $file) {id}}',
'map': '{"pdf":"variables.file"}'
}
files=[
('pdf',('file',open('12400861.pdf','rb'),'application/octet-stream'))
]
response = requests.post(url, headers=headers, data=payload, files=files)
print("Direct Response Status Code:", response.status_code)
print("Direct Response Text:", response.text)
and thats what I get:
Request Data (json): {‘query’: ‘mutation add_file($file: File!) {add_file_to_column (item_id: 8005103588, column_id:“datei” file: $file) {id}}’, ‘map’: ‘{“pdf”:“variables.file”}’}
Direct Response Status Code: 400
Direct Response Text: {“status_code”:400,“error_message”:“Unsupported query”,“errors”:[{“message”:“Unsupported query”,“extensions”:{“status_code”:400}}]}
I tried several other things but I am not getting rid of that 400 error_code:
Since my old integrations broke about 5 days ago I assume something changed in he API?
Any advise would be highly appreciated!
Hello there @Flowsen and welcome to the community!
I hope you like it here
I just made and tested this script that I hope hlelps:
import requests
# Set filename
upfile = 'myImage.jpg'
# Set query (mutation) for GraphQL request
query = '''
mutation ($file: File!) {
add_file_to_column(file: $file, item_id: "1112223334", column_id: "files__1") {
id
}
}
'''
# Set URL and boundary
url = "https://api.monday.com/v2/file"
boundary = "xxxxxxxxxx"
data = ""
# Read the file content
try:
with open(upfile, 'rb') as f:
content = f.read()
except Exception as err:
print(f"Error reading file: {err}")
exit(1)
# Construct the multipart/form-data body
data += f"--{boundary}\r\n"
data += "Content-Disposition: form-data; name=\"query\"; \r\n"
data += "Content-Type: application/json\r\n\r\n"
data += query + "\r\n"
data += f"--{boundary}\r\n"
data += f"Content-Disposition: form-data; name=\"variables[file]\"; filename=\"{upfile}\"\r\n"
data += "Content-Type: application/octet-stream\r\n\r\n"
# Prepare the full multipart body with the file
payload = data.encode('utf-8') + content + f"\r\n--{boundary}--\r\n".encode('utf-8')
# Set headers
headers = {
"Content-Type": f"multipart/form-data; boundary={boundary}",
"Authorization": "Bearer APITOKENHERE",
}
# Make the POST request
try:
response = requests.post(url, headers=headers, data=payload)
# Check if the request was successful
if response.status_code == 200:
print(response.json()) # Log the response JSON
else:
print(f"Error: {response.status_code}, {response.text}")
exit(1)
except requests.exceptions.RequestException as err:
print(f"Request failed: {err}")
exit(1)
Let me know how that goes!
Cheers,
Matias
Flo
(Florian)
December 17, 2024, 6:07pm
15
Kudos, @Matias.Monday
This saved my day—I was able to fix my script!
It seems something in the API has changed without documentation, so I hope this helps others facing the same issue.
Best Regards
Florian
1 Like