---
name: comment-dedup
description: Never retry POST /comment without first GET /tickets/{id} to confirm it didn't land; always use heredoc payloads
applies-to: syncro, all
---

# Syncro Comment Deduplication

## The rule

Never retry a POST `/comment` call without first doing a `GET /tickets/{id}` to confirm the first attempt did not land.

Syncro has no DELETE endpoint for comments. A duplicate comment cannot be removed via the API — only manually through the Syncro GUI by an admin. Duplicate comments are visible to clients (public comments) and to all technicians (hidden comments), and the content cannot be redacted without deleting the entire comment.

## Incident that established this rule

2026-05-01: A comment with completely wrong content ("Karen Rossini" and the ALDOCS Cascades share) was posted to a Sombra Residential ticket. Root cause: a `/tmp` path mismatch on Windows caused curl to read a stale payload from a previous session rather than the newly written one. The wrong comment could not be deleted via API — Howard had to manually delete it through the Syncro GUI.

## Required pattern

**Before retrying any failed comment POST:**

```bash
# Check if the comment landed before retrying
curl -s "https://computerguru.syncromsp.com/api/v1/tickets/${TICKET_ID}?api_key=${API_KEY}" \
  | jq '.ticket.comments[-1]'
```

If the comment is there, do not retry. If it is missing, diagnose why before retrying (network failure, wrong API key, wrong ticket ID).

## Payload pattern — use heredocs, not temp files

Do not write comment payloads to `/tmp/` files and read them back with curl. On Windows, `/tmp` resolves differently in Git Bash vs. the Claude Code Write tool, causing stale-file reads.

**Correct — heredoc piped directly to curl:**

```bash
curl -s -X POST "${BASE}/tickets/${TICKET_ID}/comment?api_key=${API_KEY}" \
  -H "Content-Type: application/json" \
  --data-binary @- <<'JSON'
{"subject": "Resolution", "body": "...", "hidden": false, "do_not_email": false}
JSON
```

Use `<<'JSON'` (single-quoted, literal) for static payloads. Use `<<JSON` (double-quoted, interpolating) when the payload includes shell variables like `${TIMER_ID}`.

**Wrong — temp file approach (prone to path mismatch):**

```bash
# Write tool writes to C:\tmp\, Git Bash reads from %LOCALAPPDATA%\Temp\
# These are different directories on Windows
cat > /tmp/comment.json << 'EOF'
{"subject": "Resolution", ...}
EOF
curl ... -d @/tmp/comment.json  # May read wrong file
```

## Applies also to

All Syncro POST endpoints, not just comments. Timer entries, line items, and invoices all have the same no-retry-without-check rule since duplicates are visible and often cannot be deleted via API.
