Deskwerk· Workshop

KnowledgeHelp Center

My requests: the Help Center page that shows the real status

Log into almost any Zendesk Help Center, click «My requests», and you get a list: subject, date, one word of status. Technically correct, humanly useless. Because the one question customers have, «Where does my request stand right now?», is the one this dead list doesn’t answer.

Yet all the data for it is right there. You just have to fetch it. And because logged-in customers (JWT login assumed) hit their own instance same-origin, this works straight from the Help Center page, without an API token. The same call from a foreign domain you’d have to send through a token-bearing proxy; from the Help Center page itself the session cookie is enough.

The flow: four calls

Every call runs client-side from the logged-in HC page. Authentication goes through the session cookie: no token, no OAuth. Reading (GET) needs nothing more; writing (PUT/POST) needs a CSRF token.

// 1. Load your own requests – status included
const { requests } = await (
  await fetch('/api/v2/requests.json?sort_by=updated_at&sort_order=desc')
).json();
// requests[].status: new | open | pending | hold | solved | closed

// 2. For anything that writes: get a CSRF token
const { user } = await (await fetch('/api/v2/users/me.json')).json();
const csrf = user.authenticity_token;

// 3. Upload a file → single-use upload token
const { upload } = await (
  await fetch(`/api/v2/uploads.json?filename=${encodeURIComponent(file.name)}`, {
    method: 'POST',
    headers: { 'Content-Type': file.type, 'X-CSRF-Token': csrf },
    body: file,
  })
).json();

// 4. Attach the reply + file to the request
await fetch(`/api/v2/requests/${id}.json`, {
  method: 'PUT',
  headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': csrf },
  body: JSON.stringify({ request: { comment: { body: text, uploads: [upload.token] } } }),
});

Two things the docs state plainly and that are easy to miss: the upload token is single-use, spent once you attach it. And end-user comments are always public; only agents can set the «private» flag.

For the status display it’s worth a look at the filter endpoints: the standard list GET /api/v2/requests.json has no ?status= parameter. For separate views there’s GET /api/v2/requests/open.json (new/open/pending/hold) and GET /api/v2/requests/solved.json (solved/closed). To filter freely by status you can only use the search endpoint: GET /api/v2/requests/search.json?query=&status=hold,open takes a status list. If the Agent Workspace runs with Custom Statuses, each request additionally carries a custom_status_id; each maps to one of the six standard statuses. Which mapping applies is set by your instance.

Where this lives in the theme

The standard pages are Guide theme templates: request_list_page.hbs renders the list, request_page.hbs the individual request. The list template already ships a status filter form; before you build something of your own, check what’s already there. But the templates render server-side with Curlybars. For live loading you need your own JavaScript. You add it through the theme file script.js (Guide/Knowledge admin → Customize design → Edit code); it runs globally on every HC page, so check for the right page first, then execute. Load the data when the page opens or on focus change, not on a continuous interval.

Two notes: editing theme code needs at least Suite Growth; the smallest tier, Suite Team, has no code editor. And the moment you touch a standard theme’s code, it becomes a custom theme: you own it, but you also own its maintenance. Zendesk feature updates no longer roll in automatically.

📸 Screenshot still to be added Your own «My requests» page with the status visible per request. public/werkstatt/bauplaene/meine-anfragen/status-liste.png
The dead list becomes a status tracker: every request shows where it stands.

The secure return channel

The most interesting part isn’t the reading, it’s the uploading. A common case: someone can no longer log into the main platform but has to transmit a document securely. The reflex is email, and email is the worst channel imaginable for it: often unencrypted in transit, then sitting in several mailboxes, no access control, no clean trail.

Uploading through a Help Center ticket is the opposite: transmitted over HTTPS, identified through the login, bound to a single comment by a one-time token, and traceable in the history. Instead of a loose attachment in a mail thread, an authenticated action in the right place. The advantage isn’t the size: API upload and mail attachment both sit at around 50 MB per file.

Whether your Help Center allows end-user uploads at all is controlled by an instance setting (Admin Center → Objects and rules → Tickets → Settings, Attachments section); without it, step 3 above fails.

At the same place a second look pays off, especially under the revised Data Protection Act: with Secure Downloads Zendesk requires a login before an attachment can be viewed, and the URLs of public attachments can be given an expiry. A document sent through this channel then doesn’t lie around as a permanently open link; it sits behind the login and expires after its deadline.

And the design question, when someone can’t log in normally anymore: how do they reach this one ticket? Through a tightly scoped access path that allows attachments and nothing else.

A list shows that a request exists. A page that shows its status and opens a secure way back shows that someone is behind it. That’s the difference between a portal and a place where you feel taken seriously.

← Back to: Help Center