Specious Coda-Bishop · Operations, People & Technical Support
Four reference-quality playbook documents demonstrating technical depth, process documentation, and cross-audience communication across ops and HR systems. Each document is written for a different primary audience — from technical support agents to non-technical finance and HR stakeholders — to show range as well as depth.
API troubleshooting and SQL diagnostics written for people who need to use them under real ticket pressure — precise, structured, and opinionated about resolution order.
EOR payroll explainer written for non-technical stakeholders with no assumed background. Same domain knowledge, completely different register and structure.
The escalation playbook doesn't describe a process — it is the process. Decision logic, SLAs, and routing criteria are structured to replace tribal knowledge, not supplement it.
Every document is scoped. The SQL guide covers missing and null records, not wrong values. The EOR explainer covers the payroll cycle, not employment law. Scope discipline is a writing skill.
| # | Document | Audience |
|---|---|---|
| 01 | API Troubleshooting Playbook — Zendesk → Slack Integration Failure | Technical ops / support agents |
| 02 | SQL Missing Data Audit Guide — Diagnosing Absent or Incomplete Records | Ops analysts / payroll leads |
| 03 | System Explainer: EOR Payroll Processing | Non-technical stakeholders |
| 04 | Support Escalation Playbook — Tiered Decision Logic for Ops/HR Tickets | Support agents / ops coordinators |
This playbook guides technical ops staff through diagnosing and resolving failures in the Zendesk–Slack integration. It covers webhook misconfigurations, authentication failures, payload schema mismatches, and silent delivery failures. It assumes working knowledge of both platforms and access to Zendesk Admin, Slack App management, and server/webhook logs.
Zendesk sends event-triggered notifications to Slack via outbound webhooks or the official Zendesk for Slack app. The two main delivery paths are:
| Path | Method | Common Use |
|---|---|---|
| Native App | OAuth + Slack Events API | Ticket sidebar, /zendesk slash commands |
| Custom Webhook | HTTP POST to Slack Incoming Webhook URL | Custom alerts, ticket routing notifications |
| Zendesk Triggers + HTTP Target | REST POST to Slack Webhook | Conditional alerts based on ticket rules |
Failures can occur at any point in this chain. The first step in any investigation is identifying which path is broken.
Classify Before You Investigate
Before touching any configuration, identify which failure class you're dealing with. This avoids chasing the wrong layer.
| Symptom | Likely Failure Layer |
|---|---|
| Notifications stopped entirely | Webhook URL expired or channel deleted |
| Some notifications arrive, some don't | Trigger condition logic or filter mismatch |
| Notifications arrive but are malformed | Payload schema / template error |
403 or 401 errors in logs | Authentication / token expiry |
200 OK in logs but nothing in Slack | Webhook URL is stale (Slack returns 200 on some invalid URLs) |
| Slash commands broken but alerts fine | OAuth scope issue or app reinstall required |
Zendesk Side
Navigate to Admin Center → Apps and Integrations → Targets (for legacy HTTP targets) or Webhooks (for newer webhook config).
200 = delivered (but check Slack anyway) · 404 = webhook URL not found · 410 = webhook URL revoked by Slack · 403/401 = auth failure · 5xx = Slack-side error, usually transient.
Slack Side
In Slack, navigate to your workspace App Management → Custom Integrations → Incoming Webhooks.
Isolate the Integration from Zendesk
Before debugging Zendesk trigger logic, confirm the webhook URL itself is functional by sending a test payload directly.
# Send a test POST to your Slack webhook URL curl -X POST -H 'Content-type: application/json' \ --data '{"text": "Webhook test from ops debug - ignore"}' \ https://hooks.slack.com/services/YOUR/WEBHOOK/URL # Expected: HTTP 200, message appears in target Slack channel # If you get 'no_service' or 'invalid_payload': webhook is broken at Slack end # If you get a 200 but no message: check channel permissions or archival
If this test fails, the webhook URL needs to be regenerated. Do not continue debugging Zendesk configuration until the URL is confirmed live.
Common Payload Errors
text or a blocks arraychannel field causes rejectionValid Minimal Payload
{
"text": "[{{ticket.status}}] Ticket #{{ticket.id}}: {{ticket.title}}",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Ticket #{{ticket.id}}*\n{{ticket.title}}"
}
}
]
}Always include a top-level text field alongside blocks. Slack uses it as a fallback for notifications and accessibility. Blocks-only payloads are valid but will show no preview text in mobile push notifications.
Token Expiry and Scope Failures
If the Zendesk for Slack app (rather than a raw webhook) is being used, failures are more likely to be OAuth-related.
chat:write, channels:read, users:read.If a Slack admin revoked the app's token without informing the Zendesk admin, all notifications will silently stop. There will be no error in Zendesk because Zendesk receives a 200 from Slack's API even after token revocation in some scenarios. Always cross-check both sides.
| Check | Confirmed |
|---|---|
| Webhook URL tested directly and returns 200 with message | ☐ |
| Zendesk delivery log shows no 4xx errors for past 24h | ☐ |
Payload schema validated (text field present, no stale attachment format) | ☐ |
| Target Slack channel confirmed active and not archived | ☐ |
| OAuth token/scopes confirmed if using Zendesk App | ☐ |
| Trigger conditions reviewed and tested with a live ticket | ☐ |
| Incident logged with root cause and resolution for future reference | ☐ |
This guide walks through a structured approach to diagnosing missing or incomplete records in operational databases — payroll runs, headcount exports, onboarding completions, or any dataset where expected rows are absent. It assumes basic SQL proficiency and read access to the relevant tables.
Know What You're Looking For Before You Query
Missing data has three distinct forms. Treating them the same leads to querying the wrong thing.
| Type | Description | Example |
|---|---|---|
| Row missing entirely | Record does not exist in the table | Employee not in payroll run |
| Row exists, field is NULL | Record present but field has no value | Start date column is NULL |
| Row exists, field is wrong | Record present but value is incorrect or stale | Wrong cost centre code |
This guide focuses on the first two. Establish which type you have before writing any query.
Build a Source of Truth First
The most common mistake in missing data investigations is jumping straight to the broken table without first establishing what should be there. Define your expected population from a reliable source, then compare.
-- Step 1: Define expected population -- All active employees as of the payroll run date SELECT e.employee_id, e.full_name, e.employment_status, e.start_date FROM employees e WHERE e.employment_status = 'active' AND e.start_date <= '2026-03-01' -- payroll run date AND (e.end_date IS NULL OR e.end_date > '2026-03-01'); -- Step 2: See who actually appeared in the run SELECT DISTINCT employee_id FROM payroll_runs WHERE run_date = '2026-03-01'; -- Step 3: Find the gap SELECT e.employee_id, e.full_name, e.start_date FROM employees e WHERE e.employment_status = 'active' AND e.start_date <= '2026-03-01' AND (e.end_date IS NULL OR e.end_date > '2026-03-01') AND e.employee_id NOT IN ( SELECT employee_id FROM payroll_runs WHERE run_date = '2026-03-01' );
Use NOT IN with caution if the subquery might return NULLs — NOT IN with a NULL in the list returns no rows. Use NOT EXISTS or a LEFT JOIN instead if NULL values are possible in the employee_id column of payroll_runs.
Handling NULLs Correctly
-- LEFT JOIN approach: safer when NULLs may be present SELECT e.employee_id, e.full_name, e.start_date, pr.run_date -- will be NULL if employee is missing from run FROM employees e LEFT JOIN payroll_runs pr ON e.employee_id = pr.employee_id AND pr.run_date = '2026-03-01' WHERE e.employment_status = 'active' AND e.start_date <= '2026-03-01' AND (e.end_date IS NULL OR e.end_date > '2026-03-01') AND pr.employee_id IS NULL; -- the gap condition
When the Row Exists But the Data Doesn't
If rows are present but downstream reports are broken, NULL fields are usually the cause. Check systematically.
-- Audit NULLs across key fields for active employees SELECT employee_id, full_name, CASE WHEN cost_centre IS NULL THEN 'MISSING' ELSE 'OK' END AS cost_centre_status, CASE WHEN contract_type IS NULL THEN 'MISSING' ELSE 'OK' END AS contract_type_status, CASE WHEN pay_currency IS NULL THEN 'MISSING' ELSE 'OK' END AS currency_status, CASE WHEN bank_account_id IS NULL THEN 'MISSING' ELSE 'OK' END AS bank_status FROM employees WHERE employment_status = 'active' AND ( cost_centre IS NULL OR contract_type IS NULL OR pay_currency IS NULL OR bank_account_id IS NULL ); -- Count scale of the problem SELECT COUNT(*) AS total_active, SUM(CASE WHEN cost_centre IS NULL THEN 1 ELSE 0 END) AS missing_cost_centre, SUM(CASE WHEN bank_account_id IS NULL THEN 1 ELSE 0 END) AS missing_bank FROM employees WHERE employment_status = 'active';
Find Where It Should Have Come From
Once you know which records are missing, trace backwards through the data pipeline to find where the gap was introduced.
| Pipeline Stage | What to Check |
|---|---|
| Source system (HRIS / EOR platform) | Was the employee created? Is their profile complete? |
| ETL / sync job | Did the sync run? Did it error silently? Check job logs. |
| Staging or intermediary table | Does the record exist here but not in the final table? |
| Transform logic | Is there a filter condition excluding the record unintentionally? |
| Permissions | Does the query user have access to all partitions / schemas? |
-- Check if record exists in staging but not production SELECT 'staging' AS source, employee_id FROM staging.employees WHERE employee_id = '12345' UNION ALL SELECT 'production' AS source, employee_id FROM employees WHERE employee_id = '12345'; -- If it's in staging but not production, the ETL step is where it dropped
Never delete or overwrite records during a missing data investigation without a backup and a confirmed understanding of why the record is wrong. What looks like a duplicate is sometimes valid — e.g. rehires, contractor-to-employee conversions, multi-entity employees.
This document is written for non-technical stakeholders — team leads, finance partners, or new hires who need to understand what an EOR platform does, why payroll timelines work the way they do, and what happens when something goes wrong. No technical background is assumed.
The Short Version
When your company hires someone in a country where you don't have a legal entity, you can't pay them directly — you're not registered as an employer there. An Employer of Record (EOR) solves this by becoming the legal employer on paper, handling payroll, taxes, and compliance in that country on your behalf.
Your employee still works for you in practice. The EOR handles the legal and administrative layer you can't.
How a Payment Gets From You to Your Employee
The process is more involved than a direct bank transfer. Here is what happens each month, in order:
| Stage | What Happens | Who Acts |
|---|---|---|
| 1. Data collection | EOR platform collects salary, expenses, and changes for the period | HR / Ops |
| 2. Payroll calculation | Platform calculates gross pay, tax, social contributions per local law | EOR platform |
| 3. Invoice generation | EOR invoices your company for total cost (salary + employer contributions + fee) | EOR |
| 4. Funds transfer | Your company transfers funds to EOR | Finance |
| 5. Local payroll run | EOR pays the employee and remits taxes to local authorities | EOR |
| 6. Payslip delivery | Employee receives payslip through the platform | EOR platform |
Steps 3–5 often span 5–10 business days because EORs must account for bank processing times in multiple countries, local payroll authority deadlines, and currency conversion. A delay at any stage cascades to the next.
| Issue | What's Happening | First Step |
|---|---|---|
| Employee not in payroll run | Employee record was not submitted or approved before the cutoff | Check if onboarding was completed in the platform before the cutoff date |
| Payslip shows wrong amount | Salary data, FX rate, or benefit deductions may be incorrect | Compare payslip breakdown against the contract and raise a query with the EOR |
| Payment delayed | Funds transfer from your company may not have cleared in time | Check with Finance that the EOR invoice was paid by the required date |
| Tax code incorrect | Employee's tax situation may not have been set up correctly | EOR needs the employee's local tax ID or residency documentation |
| Benefits deduction missing | Benefit enrolment may not have synced to payroll in time | Confirm enrolment was completed before the platform's benefits cutoff |
A common source of confusion is who is responsible for what. The EOR platform automates a lot, but your ops and HR team still owns key inputs.
| Your Team Owns | The EOR Platform Handles |
|---|---|
| Submitting employee data accurately and on time | Calculating local taxes and contributions |
| Approving changes before the payroll cutoff | Generating compliant payslips |
| Ensuring Finance pays EOR invoices on time | Remitting taxes to local authorities |
| Managing employee queries about their contract | Processing salary payments in local currency |
| Offboarding employees and updating the platform | Maintaining compliance with local employment law |
The EOR platform processes what it's given. Errors in the output almost always trace back to incomplete or late input. The single most effective thing your team can do to prevent payroll issues is submit changes early and check the platform's cutoff calendar at the start of each month.
This playbook defines how ops and HR support tickets should be triaged, routed, and escalated. It is designed to reduce resolution time, prevent over-escalation, and ensure the right person handles each issue at the right level. It is written for support agents, ops coordinators, and first-line HR contacts.
| Tier | Who Handles It | Typical Resolution Time |
|---|---|---|
| Tier 1 — Self-serve / First response | Support agent or HR coordinator | Same day |
| Tier 2 — Specialist review | Senior ops, payroll lead, or HRBP | 1–3 business days |
| Tier 3 — Escalation / External | EOR provider, legal, platform support | 3–5+ business days |
The goal is to resolve as much as possible at Tier 1 and only escalate when the issue genuinely requires it. Tier 3 should be rare.
Criteria for Tier 1
A ticket stays at Tier 1 if all of the following are true:
Tier 1 Examples
| Ticket Type | Resolution Path |
|---|---|
| How do I update my bank details? | Direct to platform self-serve guide |
| I can't log into the HR system | Password reset or IT handoff |
| When is the next payroll cutoff? | Check cutoff calendar, reply directly |
| How do I request leave? | Point to policy doc or HRIS walkthrough |
| I need a copy of my payslip | Download from platform or generate on their behalf |
Criteria for Escalation to Tier 2
Escalate to Tier 2 when any of the following apply:
How to Escalate to Tier 2
Criteria for Escalation to Tier 3
Tier 3 involves escalating outside your team to an EOR provider, benefits vendor, legal counsel, or platform support. This should only happen when:
External Escalation Process
When escalating payroll issues to an EOR, always include:
Incomplete escalations significantly increase resolution time.
| Question | If Yes → | If No → |
|---|---|---|
| Can this be resolved with existing docs/access? | Resolve at Tier 1 | Move to next question |
| Does it involve payroll, salary, or compliance? | Escalate to Tier 2 | Move to next question |
| Does it require EOR or external vendor action? | Escalate to Tier 3 | Review with Tier 2 before escalating |
| Is it a potential data/legal incident? | Escalate to Tier 3 immediately + notify manager | Proceed with standard triage |
| Tier | First Response SLA | Resolution Target | Breach Action |
|---|---|---|---|
| Tier 1 | 4 business hours | Same day | Escalate to Tier 2 |
| Tier 2 | 1 business day | 1–3 business days | Flag to team lead |
| Tier 3 | 1 business day (your acknowledgement to employee) | Per vendor SLA | Escalate internally and chase vendor |
SLAs apply from the moment a ticket is received, not from when it is first read. Ensure ticket queues are monitored during business hours and that out-of-office cover is in place for critical queues.