Infos:
- Used Zammad version: 6.5.0
- Used Zammad installation type: docker / kubernetes
- Operating system: MacOS
- Browser + version: Firefox 137.0.1
Expected behavior:
PUT request to http://zammad/api/v1/tickets/${ticket_id}/shared_draft creates a draft with the supplied attachements.
Actual behavior:
Draft is created, but without attachement.
Steps to reproduce the behavior:
PUT request to http://zammad/api/v1/tickets/{ticket_id}/shared_draft with example payload:
{
“new_article”: {
“subject”: “Some Title”,
“body”: “This is some text.”,
“to”: “mailtest@example.org”,
“content_type”: “text/html”,
“sender”: “Agent”,
“type”: “email”,
“attachments”: [
{
“data”: “SNIP”,
“filename”: “blub.pdf”,
“mime-type”: “application/pdf”
}
]
}
}
Draft is created and logs confirm processing. Also GET to http://zammad/api/v1/tickets/{ticket_id}/shared_draft confirms the existance of the attachements. It is not displayed in the GUI however
Update:
I am aware of /api/v1/upload_caches/form_id as an endpoint, however that is (like the entire form_id param) undocumented.
lutuh
3
Hey,
I think I got it figured out how to create shared drafts with attachments by studying how the UI handles file uploads.
First, forget about the “attachments” data within the PUT body to “shared_draft”. This works for ticket articles, but not for drafts.
You were right with the “form_id” parameter. This is how it works:
- Generate a custom, unique “form_id” parameter.
- Create one or multiple uploads via POSTing to the “upload_caches/<form_id>” endpoint, using this form_id you just created.
- Create the shared draft as usual, but add the same “form_id” paramater to your paypload. This attaches your file uploads to your shared draft.
Important: Create the file uploads first! They have to already exist when the draft is created.
Sample Python code:
import requests
import uuid
base_url = 'http://zammad.example.com'
api_token = 'YOUR_TOKEN'
ticket_id = 123
form_id = str(uuid.uuid4())
session = requests.Session()
session.headers.update({
'Authorization': f'Token token={api_token}',
'Content-Type': 'application/json',
'Accept': 'application/json',
})
def upload_file(path):
with open(path, 'rb') as f:
files = {'File': (path.split('/')[-1], f)}
data = {'form_id': form_id}
r = session.post(f'{base_url}/api/v1/upload_caches/{form_id}', files=files, data=data)
r.raise_for_status()
return r.json()['data']
def create_shared_draft():
payload = {
'form_id': form_id,
'new_article': {
'subject': 'Some Title',
'body': 'This is some text.',
'to': 'mailtest@example.org',
'content_type': 'text/html',
'sender': 'Agent',
'type': 'email',
},
'ticket_attributes': {}
}
r = session.put(
f'{base_url}/api/v1/tickets/{ticket_id}/shared_draft',
json=payload,
)
r.raise_for_status()
return r.json()
upload_file('/path/to/blub.pdf')
draft = create_shared_draft()