Post layouts

Starting structures offered when you create a post: an article, release notes, a customer story, and a how-to guide.

A shared inbox works when anyone can tell, at a glance, which requests are theirs. This is the setup we walk new teams through in their first week, and the habits that keep it tidy after that.

Give every request one owner

When a request belongs to everyone, it belongs to no one. The first rule we set is that every open request has exactly one owner, even when three people end up working on it.

Owners change hands all the time, and that is fine. What matters is that the name on the request belongs to the person who sends the next reply.

  • Flag requests that sit without an owner for more than an hour
  • Hand a request over with an internal note, not a chat message
  • Close a request only when the customer has what they asked for

Use tags for topics and views for people

Tags describe what a request is about: billing, bookings, a bug. Views describe who should see it. Mixing the two up is the most common reason a queue turns messy by the third month.

A Hassium inbox view for one team, with an open request and an internal note from a teammate
A view for the bookings team. Tags show what each request is about at a glance.

Start with five or six tags and one view per team. Add more only when someone asks for a list that does not exist yet.

Write saved replies that sound like you

Customers can tell when they are reading a template. Write each saved reply the way you would answer one person, then leave room for a line only a teammate could add.

We rewrite a saved reply whenever a customer answers it with a follow-up question. That question is the part the reply missed.

Tobias Kline, support lead at Hassium

Try this: Review your saved replies once a quarter. Old prices, retired features, and broken links hide in them longer than anywhere else.

Try this setup on your own queue

Every feature is free for 14 days. Bring a week of real requests and see how the inbox feels with owners and views in place.

Workflows 2.0

Available on every plan

Workflows can now take different paths, pause for a customer, and show you their work on old requests before anyone depends on them. Here is everything in the release.

The workflow builder with a refund workflow that splits into two branches after a check on the order total

What is new

  • Branches. Split a workflow on a tag, a form answer, or the customer's plan, and give each path its own actions.
  • Delays. Pause a step for a set time, or until the customer writes back, then carry on from the same place.
  • Test runs. Choose a date range and see what a draft would have done to every request in it, while the draft is still private.

Improvements

  • The step log now says why each condition passed or failed.
  • Large workflows open about twice as fast in the builder.
  • Duplicating a workflow now copies its test history too.

Workflow runs in the REST API now include the branch each run took and the steps it ran, in order. Existing fields are unchanged.

GET /v1/runs/run_8f2c

{
  "id": "run_8f2c",
  "status": "completed",
  "branch": "over_limit",
  "steps": [
    "check_total",
    "ask_approval",
    "notify_owner"
  ]
}

Fixes

  • Approval requests sent by email now expire after seven days, as the setting says.
  • A form submitted twice within a second no longer starts the same workflow twice.
  • Renaming a tag now updates every workflow condition that uses it.

Upgrade notes

For workspace admins

Existing workflows keep running exactly as they did. Branches and delays appear the next time you open a workflow in the builder, and nothing changes until you publish a new version.

For API users

branch is a new field on every run. It is empty for runs that started before September 8, 2026, so allow an empty value if your code checks responses strictly.

Brightwater Dental books patients across nine clinics from one front desk team. Here is how they stopped losing appointment changes between the phone, the inbox, and the website.

CompanyBrightwater Dental
Team size12 people across nine clinics
PlanTeam, billed yearly
Using Hassium sinceMarch 2025

The challenge

Patients asked to move appointments by phone, by email, and through a form on the website, and each clinic kept its own list of changes.

Changes slipped between those lists. A patient would email on Friday, call on Monday, and arrive on Wednesday for a slot that had already moved. Priya Nair, the operations manager, counted 14 missed changes in one quarter.

What they changed

The team moved all three channels into one Hassium inbox in a week. An intake form replaced the free text box on the website, so every request now arrives with the clinic, the patient, and two preferred times.

  • A workflow routes each request to the clinic it names
  • Anything without a reply after two hours goes to the shift lead
  • Saved replies confirm the new time and link to the clinic's map

The results

Six months later, the same front desk team handles about a third more requests, and missed changes are close to zero.

38 min

Median first reply, down from 5 hours

1

Missed change last quarter, down from 14

94%

Patients who rated their reply good or great

Nobody keeps a list on a sticky note anymore. If a patient asked for something, it is in Hassium, and it has a name next to it.

Priya Nair, operations manager, Brightwater Dental

Brightwater is now setting up the same routing for insurance questions, starting with the two busiest clinics.

This guide connects Hassium to your own server with a webhook, so every new request is posted to an address you control. From there you can log it, alert on it, or copy it into another system. Plan on about fifteen minutes.

What you need

  • An admin role in your Hassium workspace
  • An HTTPS endpoint that accepts POST requests
  • A safe place for a secret, such as an environment variable

Set up the webhook

  1. Open the webhook settings Go to Settings, then Integrations, and choose Add webhook.
  2. Paste your endpoint Enter the HTTPS address that should receive requests. Plain HTTP addresses are rejected.
  3. Pick the events Start with Request created. You can add replies and status changes later.
  4. Copy the signing secret Hassium shows it once. Store it with your other credentials, never in your code.
  5. Send a test event Choose Send test and check that your endpoint answers with a 200 status.

Check the signature

Every delivery carries a signature header. Compute your own from the raw body and your secret, and trust the request only when the two match. A minimal check looks like this:

const expected = hmacSha256(secret, rawBody);
const received = request.headers['hassium-signature'];

if (!timingSafeEqual(expected, received)) {
  return respond(401);
}

return respond(200);

Troubleshooting

The test event times out

Hassium waits 10 seconds for an answer. Reply with a 200 status straight away and do the slow work afterward, in a queue or a background job.

The signatures never match

Compute the signature from the raw body, before anything parses it. Parsing and re-encoding the JSON changes the bytes, and the signature changes with them.

Every request arrives twice

Hassium retries a delivery when it gets no 200 status in time. Store the delivery ID from the header and skip any ID you have already handled.

Next steps

Once test events arrive, you can narrow down what gets sent or add more events: