syncro: expand ticket creation to full 19-field workflow
Documents the 3-call create pattern (ticket → Initial Issue comment →
appointment), adds problem type and appointment type dropdowns with IDs,
fixes priority format to number-prefixed strings ("2 Normal"), adds Howard
to tech user ID table, and adds asset/contact lookup steps.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -108,26 +108,177 @@ echo "Authenticated as: $ME"
|
||||
|---|---|---|---|
|
||||
| List tickets | GET | `/tickets?status=<status>&per_page=25` | — |
|
||||
| Get ticket | GET | `/tickets/<id>` | — |
|
||||
| Create ticket | POST | `/tickets` | `{"customer_id": N, "subject": "...", "problem_type": "...", "status": "New"}` |
|
||||
| Create ticket | POST | `/tickets` | see full create workflow below |
|
||||
| Update ticket | PUT | `/tickets/<id>` | `{"status": "In Progress", "priority": "..."}` |
|
||||
| Delete ticket | DELETE | `/tickets/<id>` | — |
|
||||
|
||||
**Ticket statuses:** `New`, `In Progress`, `Waiting on Customer`, `Waiting on Vendor`, `Scheduled`, `Resolved`, `Invoiced`, `Closed`
|
||||
|
||||
**Ticket fields (create/update):**
|
||||
- `customer_id` (required for create)
|
||||
- `subject` (required for create)
|
||||
- `problem_type` (string, free-form)
|
||||
- `status` (string, one of the statuses above)
|
||||
- `priority` (string) — set this; leave blank only if user says not to
|
||||
- `due_date` (ISO date)
|
||||
- `user_id` (assign to tech) — set this; Mike = 1735, Winter = 1737, Rob = 1760
|
||||
- `contact_id` (customer contact)
|
||||
- `ticket_type_id` (ticket category)
|
||||
**Priority format** (number-prefixed string): `"1 High"`, `"2 Normal"`, `"3 Low"`, `"4 Urgent"`
|
||||
Default: `"2 Normal"`. Use `"4 Urgent"` for emergency/after-hours.
|
||||
|
||||
**Always set `user_id` and `priority` on create** unless the user says otherwise. Ask if unknown.
|
||||
- Assignee = whoever worked the ticket (Mike = 1735, Winter = 1737, Rob = 1760)
|
||||
- Priority = `Normal` by default; `Urgent` for emergency/after-hours tickets
|
||||
**Problem types (Issue Type dropdown — use closest match, else "Not determined"):**
|
||||
`API`, `Email`, `Emergency Service`, `File Services / Permissions`, `Hardware`, `Maintenance`,
|
||||
`New User / M365 Account Creation`, `New User / Workstation Deployment`, `Not determined`,
|
||||
`Onsite`, `Other`, `Phone/VOIP`, `Remote`, `Security`, `Server Migration`, `Service Request`,
|
||||
`Software`, `Website`
|
||||
|
||||
**Appointment types:**
|
||||
|
||||
| Name | ID | location_type |
|
||||
|---|---|---|
|
||||
| In Shop | 4321 | shop |
|
||||
| Onsite | 4322 | customer |
|
||||
| Phone Call | 4323 | pre_defined |
|
||||
| Reminder | 193053 | manual_entry |
|
||||
| Remote | 59289 | pre_defined |
|
||||
|
||||
**Tech user IDs:** Mike = 1735, Howard = 1750, Winter = 1737, Rob = 1760
|
||||
|
||||
---
|
||||
|
||||
### Ticket creation workflow (full — 3 API calls)
|
||||
|
||||
Ticket creation in Syncro maps to three separate API calls. Gather all inputs first, show a full preview, wait for confirmation, then execute in order.
|
||||
|
||||
#### Step 1 — Gather inputs
|
||||
|
||||
Collect in one pass (do not ask field by field):
|
||||
|
||||
| # | Field | Notes |
|
||||
|---|---|---|
|
||||
| 1 | **Subject** | Brief title: reason for the ticket |
|
||||
| 2 | **Issue Type** (`problem_type`) | From dropdown above; "Not determined" if unclear |
|
||||
| 3 | **Priority** | "2 Normal" default; "4 Urgent" for emergencies |
|
||||
| 4 | **Description** | Expanded detail — becomes the "Initial Issue" comment body |
|
||||
| 5 | **Do Not Email** | Suppress customer notification on ticket create? (yes for internal/reminder tickets) |
|
||||
| 6 | **Due Date** | ISO date |
|
||||
| 7 | **Assigned Tech** | Who owns the ticket |
|
||||
| 8 | **Contact** | Look up from `GET /customers/{id}` → `.contacts[]`; show list, ask user to pick |
|
||||
| 9 | **Address/Site** | `address_id` — also comes from customer contacts with address data |
|
||||
| 10 | **Appointment Type** | From table above; omit section if no appointment needed |
|
||||
| 11 | **Location** | Free text; usually blank unless onsite at non-primary address |
|
||||
| 12 | **Start Time** | ISO8601 datetime; omit if no scheduled appointment |
|
||||
| 13 | **End Time** | Default: start + 90 minutes |
|
||||
| 14 | **Appointment Owner** | Usually same as assigned tech; noted for calendar attribution (not a separate API field — inherits from ticket `user_id`) |
|
||||
| 15 | **Do Not Invite** | If not onsite, suppress calendar invite — note: not directly controllable via API; inform user if they need this set manually |
|
||||
| 16 | **Asset** | Search `GET /customer_assets?customer_id=N&query=<name>` if a specific device is involved |
|
||||
|
||||
#### Step 2 — Look up customer data
|
||||
|
||||
Before showing the preview, fetch what you need:
|
||||
|
||||
```bash
|
||||
# Get contacts and addresses
|
||||
curl -s "${BASE}/customers/${CUST_ID}?api_key=${API_KEY}" | jq '{contacts: [.customer.contacts[] | {id, name, address1, email}]}'
|
||||
|
||||
# Search assets
|
||||
curl -s "${BASE}/customer_assets?customer_id=${CUST_ID}&query=<name>&api_key=${API_KEY}" | jq '[.assets[] | {id, name, asset_type}]'
|
||||
```
|
||||
|
||||
#### Step 3 — Show preview and confirm
|
||||
|
||||
Display the full ticket before posting. Include all populated fields. Wait for explicit confirmation.
|
||||
|
||||
```
|
||||
TICKET PREVIEW
|
||||
--------------
|
||||
Customer: <name>
|
||||
Subject: <subject>
|
||||
Issue Type: <problem_type>
|
||||
Priority: <priority>
|
||||
Description: <description>
|
||||
Due Date: <due_date>
|
||||
Assigned To: <tech name>
|
||||
Contact: <contact name>
|
||||
Address: <address>
|
||||
Do Not Email: <yes/no>
|
||||
|
||||
APPOINTMENT
|
||||
-----------
|
||||
Type: <type name>
|
||||
Start: <start_at>
|
||||
End: <end_at> (90 min)
|
||||
Location: <location or blank>
|
||||
|
||||
ASSET: <asset name or none>
|
||||
|
||||
Confirm? (yes/no)
|
||||
```
|
||||
|
||||
#### Step 4 — Execute (after confirmation)
|
||||
|
||||
**Call 1 — Create ticket:**
|
||||
|
||||
```bash
|
||||
curl -s -X POST "${BASE}/tickets?api_key=${API_KEY}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d @/tmp/ticket_payload.json
|
||||
# Parse: TICKET_ID=$(... | jq -r '.ticket.id')
|
||||
# Parse: CUST_ID=$(... | jq -r '.ticket.customer_id')
|
||||
```
|
||||
|
||||
Payload fields (omit null/blank):
|
||||
```json
|
||||
{
|
||||
"customer_id": N,
|
||||
"subject": "...",
|
||||
"problem_type": "...",
|
||||
"status": "New",
|
||||
"priority": "2 Normal",
|
||||
"user_id": N,
|
||||
"due_date": "YYYY-MM-DD",
|
||||
"contact_id": N,
|
||||
"address_id": N,
|
||||
"start_at": "ISO8601",
|
||||
"end_at": "ISO8601",
|
||||
"asset_ids": [N]
|
||||
}
|
||||
```
|
||||
|
||||
**Call 2 — Post initial description as "Initial Issue" comment:**
|
||||
|
||||
```bash
|
||||
curl -s -X POST "${BASE}/tickets/${TICKET_ID}/comment?api_key=${API_KEY}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d @/tmp/comment_payload.json
|
||||
# Parse: .comment.id (NOT .id — see Hard Rules)
|
||||
```
|
||||
|
||||
Payload:
|
||||
```json
|
||||
{
|
||||
"subject": "Initial Issue",
|
||||
"body": "<the full description>",
|
||||
"hidden": false,
|
||||
"do_not_email": true
|
||||
}
|
||||
```
|
||||
Set `do_not_email: true` if "Do Not Email" was checked; `false` otherwise.
|
||||
|
||||
**Call 3 — Create appointment (only if start_at provided):**
|
||||
|
||||
```bash
|
||||
curl -s -X POST "${BASE}/appointments?api_key=${API_KEY}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d @/tmp/appt_payload.json
|
||||
```
|
||||
|
||||
Payload:
|
||||
```json
|
||||
{
|
||||
"ticket_id": N,
|
||||
"customer_id": N,
|
||||
"appointment_type_id": N,
|
||||
"start_at": "ISO8601",
|
||||
"end_at": "ISO8601",
|
||||
"location": ""
|
||||
}
|
||||
```
|
||||
|
||||
Note: "Do Not Invite" (suppress calendar invite email) is not API-controllable. Tell the user to toggle it in the Syncro GUI if needed.
|
||||
|
||||
**Always use temp files for payloads** — never inline JSON in curl -d with ticket data (special characters, newlines in description will break the shell).
|
||||
|
||||
#### Comments
|
||||
|
||||
|
||||
Reference in New Issue
Block a user