Automationsintermediate

Recipe — Fire a webhook when a case closes

When a case closes with a specific tag (e.g. VIP-Refund), POST a webhook to a downstream system with the case ID, contact, and any relevant custom fields. The universal escape hatch for systems Atender doesn't natively integrate with.

May 10, 2026

Recipe — Fire a webhook when a case closes

When a case closes with a specific tag (e.g. VIP-Refund), POST a webhook to a downstream system — your finance system, order pipeline, ERP — with the case ID, contact, and relevant custom fields. The universal escape hatch for systems Atender doesn’t natively integrate with.

What this rule does

  • Trigger: A case is closed.
  • Condition: Case has the VIP-Refund tag.
  • Action: POST a templated JSON payload to your downstream system.

Before you start

  • A receiving endpoint that can authenticate the request (typically via a static bearer token in a header) and process the payload idempotently
  • The case-tag values you want to filter on, defined in Tag Management
  • A bearer token or signing secret stored where the webhook action can reference it (typically as a header value baked into the rule)

Build it

  • 1 — Trigger — Case closed
  • 2 — Condition — case.tags contains VIP-Refund
  • 3 — Branch — Always
  • 4 — Action — Webhook
  • 5 — Method — POST
  • 6 — URL — https://api.your-finance-system.com/refunds
  • 7 — Headers — Authorization: Bearer YOUR_TOKEN, Content-Type: application/json
  • 8 — Body — (see below)

Body template

{
  "atender_case_id": "{{case.id}}",
  "atender_human_id": "{{case.human_id}}",
  "tenant": "{{tenant.slug}}",
  "contact": {
    "id": "{{contact.id}}",
    "email": "{{contact.email}}",
    "customer_level": "{{contact.customer_level}}"
  },
  "refund_amount": "{{case.custom_fields.refund_amount}}",
  "closed_at": "{{case.closed_at}}",
  "closed_by": "{{case.assigned_agent.email}}"
}

Merge tags fill at send time from the case context. Whatever your downstream system expects, mirror its shape here.

Idempotency

Webhook actions can fire more than once for the same logical event under unusual conditions (network retries, manual re-runs, re-triggers from edits). Make the receiver idempotent — key on atender_case_id so a duplicate POST is a no-op.

Throttling

Add a rule throttle if your downstream system has rate limits. Common pattern: Global, 60 per minute to protect a small downstream service from a burst of bulk-closed cases.

Verify it worked

Manually close a test case with the VIP-Refund tag. Check Manual Executions for the rule; expand the run and read the webhook action’s response. You’re looking for:

  • HTTP 2xx status code from the receiver
  • The expected response body (your receiver’s “ok” payload, an idempotency key it returned, etc.)

If the receiver returns non-2xx, the action shows as failed and the response body is captured in the log — read it to debug.

Variants

  • Multiple downstream systems. Use multiple webhook actions in the same branch — they’ll fire in sequence. If you need them parallel, that’s not currently supported; split into multiple rules with the same trigger.
  • Different payloads by tag. Use branches: If case.tags contains VIP-Refund → POST to finance; Else if case.tags contains Bug → POST to engineering issue tracker.
  • Include the conversation transcript. Add "transcript_url": "{{conversation.url}}/transcript" so the downstream system has a deep link back to the source.
  • Sign the payload. Add an HMAC of the body in a X-Atender-Signature header so the receiver can verify the payload wasn’t tampered with. The receiver uses the shared secret to recompute and compare.

Troubleshooting

  • Symptom: Receiver doesn’t see the POST. Fix: Open Manual Executions and read the action’s response. If the action shows success but the receiver disagrees, the URL is wrong or being intercepted by a proxy. If the action shows a network error, the URL is unreachable from Atender’s egress IPs — confirm DNS and any IP allowlists.

  • Symptom: Receiver returns 401. Fix: Bearer token is stale or the wrong header name. Some systems expect X-Auth-Token rather than Authorization.

  • Symptom: Receiver returns 422 with a “missing field” error. Fix: A merge tag resolved to empty. The most common cause is a custom field not yet populated — gate the rule on case.custom_fields.refund_amount is not empty.

  • Symptom: Webhook fires multiple times for one case close. Fix: Throttle per-case, 1 per 60 minutes. Make sure the receiver is idempotent regardless.

See also

Tags

Recipe

See Atender in action

Book a personalized demo and see how AI-powered customer service with expert humans can transform your support operation.