Accessing end user uploaded attachments
If you've built a custom ticket form using the Ticketing API, accessing end user uploaded attachments requires a valid Zendesk session by default. This also applies to all attachments when Secure Downloads is enabled. Users on external websites don't have a Zendesk session, so attachment URLs cannot be accessed directly in the browser.
To serve these attachments on your website, create a proxy endpoint that requests the content_url with your API token on behalf of the user. Zendesk responds with a 302 and a Location header containing a temporary download URL. The proxy redirects the user's browser to this URL to download the file.
Attachment URLs returned by the Ticketing API in the content_url field should be routed through your proxy endpoint. For example:
https://yoursubdomain.zendesk.com/attachments/token/abc/?name=file.png
becomes:
https://yourserver.com/attachments/token/abc/?name=file.png
Node.js
app.get('/attachments/token/:token/', async (req, res) => {const { token } = req.paramsconst filename = req.query.nameconst contentUrl = `https://${ZENDESK_SUBDOMAIN}.zendesk.com/attachments/token/${token}/?name=${filename}`try {const response = await axios.get(contentUrl, {auth: {username: `${ZENDESK_USER_EMAIL}/token`,password: ZENDESK_API_TOKEN},maxRedirects: 0,validateStatus: status => status === 302})res.redirect(response.headers['location'])} catch (error) {// Handle error based on your application's requirementsres.status(500).send('Unable to retrieve attachment')}})
Python
@app.route('/attachments/token/<token>/')def proxy_attachment(token):filename = request.args.get('name')content_url = f"https://{ZENDESK_SUBDOMAIN}.zendesk.com/attachments/token/{token}/?name={filename}"response = requests.get(content_url,auth=(f"{ZENDESK_USER_EMAIL}/token", ZENDESK_API_TOKEN),allow_redirects=False)if response.status_code != 302:# Handle error based on your application's requirementsreturn 'Unable to retrieve attachment', 500return redirect(response.headers['Location'])
Note: The error handling shown above is minimal. Adjust the error responses based on your application's requirements.