# GigOrganizer Workflow Patterns

Sequences that teach AI agents the *order* of operations, not just individual endpoints.

---

## 1. Create and Send a Contract

```
1. GET /api/credits                  → check GigPack balance
   If access.canCreateContract = true → proceed to step 2 (credit path)
   If access.canCreateContract = false → do NOT call POST /api/checkout/esign with a token (not token-authenticated — creates a guest checkout detached from the account). Direct the user to https://gigorganizer.com/dashboard/create in the browser.

2. ⚠️ CONFIRM before deducting:
   If access.displayBalance.kind = unlimited → "You have unlimited GigPacks. I'll use 1 to create this contract. Proceed?"
   Else → "You have X GigPacks. I'll use 1 to create this contract. Proceed?"
   This is a consumable entitlement — never silently deduct.

3. POST /api/credits/use             → deducts 1 credit, creates contract
   Returns { purchaseId } (use as session_id in subsequent routes)
   Contract creation is browserless — but send-for-signature still requires the purchase page.

4. Give the user the purchase page URL:
   https://gigorganizer.com/purchase/session/{purchaseId}

5. GET /api/purchase/session/{purchaseId}/esign/db-status  [read]
   → Poll until clientStatus = "signed", then performerStatus = "signed"
```

**Access semantics for post-creation routes:**
- **Token-accessible:** `GET /api/purchase/session/{id}` [read], `GET .../esign/db-status` [read]
- **Guest-accessible** (URL-based, no API token needed): purchase page, status page, signed PDF download
- **Session-only** (not token-accessible): `POST .../esign` (send for signing)

The agent can check e-sign status via token. Sending for signature requires the purchase page.

---

## 2. Add Team Members and Send Invitations

```
1. GET /api/purchase/session/{sessionId}/musicians
   → See current roster

2. POST /api/purchase/session/{sessionId}/musicians
   Body: { "musicianName": "...", "musicianEmail": "...", "teamMemberType": "guitar", "payAmount": 25000 }
   → Add each team member (repeat for each person). payAmount is in cents.

3. POST /api/purchase/session/{sessionId}/musicians/invite
   Body: { "musicianIds": ["id1", "id2", ...] }
   → Sends invitation emails with ICS calendar attachments
   ⚠️ 5-minute cooldown between invitations
```

**Two-stage confirmation flow:**
- Stage 1 (Availability): Team member confirms they can hold the date → status = "available"
- Stage 2 (Final Commitment): Organizer triggers commitment request → status = "confirmed"

---

## 3. Track Payments

```
1. POST /api/purchase/session/{sessionId}/payment-status
   Body: { "type": "deposit", "action": "mark_paid", "paidBy": "venmo" }
   → Mark deposit as paid

2. POST /api/purchase/session/{sessionId}/documents/send
   Body: { "documentType": "deposit-receipt" }
   → Send receipt to client (requires deposit marked as paid)

3. POST /api/purchase/session/{sessionId}/payment-status
   Body: { "type": "balance", "action": "mark_paid", "paidBy": "check" }
   → Mark balance as paid

4. POST /api/purchase/session/{sessionId}/documents/send
   Body: { "documentType": "full-receipt" }
   → Send full payment receipt
```

**Document types and gates:**
| Type | Gate |
|------|------|
| `payment-schedule` | None |
| `deposit-invoice` | None |
| `balance-invoice` | None |
| `deposit-receipt` | Requires deposit paid |
| `balance-receipt` | Requires balance paid |
| `full-receipt` | Requires all payments |
| `contract-pdf` | None |

---

## 4. Client Communication Sequence

```
After contract is sent:
  POST .../email           → Body: { "message": "optional" } → Send contract summary + signing link
  POST .../nudge-client    → Body: { "customMessage": "optional" } → Gentle reminder to sign

After contract is signed:
  POST .../documents/send  → Body: { "documentType": "deposit-invoice" } → Send deposit invoice
  POST .../client-reminder → Body: { "customMessage": "optional" } → Reminder about deposit

Before the event:
  POST .../client-reminder → Pre-event logistics reminder
  POST .../documents/send  → Body: { "documentType": "contract-pdf" } → Contract copy

After the event:
  (Post-gig balance collection and review requests are automated via cron)
```

---

## 5. Tax Season Workflow (W-9 + 1099)

```
1. GET /api/tax/team-members
   → List all team members with payment totals and W-9 status

2. ⚠️ W-9 REQUESTS ARE DASHBOARD-ONLY — not available via API token.
   Direct the user to: https://gigorganizer.com/dashboard/tax/team
   (POST /api/tax/team-members/{id}/w9 requires session auth and is not in
   the token capability allowlist.) You can still read each member's
   w9_status from step 1 (not_requested → pending → completed).

3. ⚠️ 1099 FILING IS DASHBOARD-ONLY — not available via API token.
   Direct user to: https://gigorganizer.com/dashboard/tax
   (POST /api/tax/filings/create and /file require session auth
   and are not in the token capability allowlist.)
```

**Filing threshold:** 1099-NEC required for payments ≥ $600/year to a single payee.
**IRS deadline:** January 31 for the previous tax year.

---

## 6. Gig Day Prep (Read-Only)

```
1. GET /api/purchases
   → Filter for today's gigs (eventDate = today)

2. GET /api/purchase/session/{sessionId}/musicians
   → Check team roster: who confirmed, who hasn't responded

3. GET /api/purchase/session/{sessionId}/esign/db-status
   → Verify contract is signed

4. GET /api/purchase/session/{sessionId}/tasks
   → Check prep tasks: what's done, what's outstanding

5. GET /api/purchase/session/{sessionId}/notes
   → Read private gig notes
```

---

## 7. ContractFormData Field Reference

Fields used in `POST /api/checkout/esign` body → `formData`:
> ⚠️ `POST /api/checkout/esign` is a browser/cookie path — not token-callable. Token agents must NOT call it; use this table only as a `formData` shape reference for `POST /api/credits/use`.

**Tier 1 — Extractable from email (~47% of fields):**
| Field | Example |
|-------|---------|
| `eventDate` | "2026-06-14" |
| `clientName` | "Sarah Chen" |
| `clientEmail` | "sarah@email.com" |
| `feeAmount` | "2500" |
| `eventType` | "Wedding" |
| `startTime` / `endTime` | "18:00" / "22:00" |
| `venueName` | "The Grand Ballroom" |
| `venueAddress` | "123 Main Street" |
| `numberOfMusicians` | "4" |
| `depositMode` | "percent" or "fixed" |
| `depositPercent` | "50" |
| `depositFixedAmount` | "500" |
| `guestCount` | "200" |
| `isOutdoor` | true |
| `isPublic` | false |

No deposit required is explicit, not omitted:
```json
{
  "depositMode": "percent",
  "depositPercent": "0",
  "depositFixedAmount": "",
  "depositDueDate": ""
}
```

**Tier 2 — Auto-filled from event type presets:**
Wedding → 50% deposit, 90-min arrival, no recording, private
Club/Bar → 0% deposit, 60-min arrival, promotional recording
Corporate → 25% deposit, 60-min arrival, no recording

**Tier 3 — Must ask the user (11 fields):**
`performerName`, `performerEmail`, `contactName`, `contactEmail`,
`depositDueDate`, `governingLawState`, `enabledClauseIds`,
`riderText`, `performanceNotes`, `privateNotes`, `buyerType`

---

## Voice Command Mappings

| What the user says | API calls |
|-------------------|-----------|
| "Create a contract for the wedding on May 5th" | GET credits, POST credits/use; if no credits → direct user to browser: gigorganizer.com/dashboard/create (do NOT call POST checkout/esign with token) |
| "Send the contract for signature" | Dashboard action (not token) — hand over the purchase page URL: gigorganizer.com/purchase/session/{id} |
| "Mark the deposit as paid" | POST payment-status |
| "Invite the band to the gig" | POST musicians, POST musicians/invite |
| "Send a reminder to the client" | POST nudge-client |
| "Request W-9 from John" | Dashboard action (not token) → gigorganizer.com/dashboard/tax/team |
| "File 1099s for this year" | Dashboard only → gigorganizer.com/dashboard/tax |
| "List all pending gigs" | GET purchases |
| "What's the signing status?" | GET esign/db-status |
| "What's on today?" | GET purchases (filter by date) |
| "Add a task for soundcheck at 4pm" | POST tasks |
| "How much revenue this month?" | GET dashboard/payments |
| "Who's in my contacts?" | GET contacts |
