{"openapi":"3.1.0","info":{"title":"Shindig API","version":"1.0.0","description":"REST API for Shindig event shopping automation (Plus / Plus 50 plans).\n\nAuthenticate with your API key from **Settings → Company Config → API & MCP Access**:\n\n`Authorization: Bearer <your-api-key>`\n\nInteractive docs: `/api/v1/docs` (alias: `/api/docs`)\n\n## Agent notes\n- Dates are **YYYYMMDD integers** (e.g. `20260701`), not ISO strings.\n- On **PATCH** `/events/{eventId}`: omitted fields **keep** existing values. Pass `[]` for\n  `formItems` or `eventProducts` only when clearing intentionally.\n- Discover product/variant IDs with **GET** `/products` before setting `eventProducts`.\n- When `password` is set, `privateMessage` is required. When `userPortalEnabled` is true,\n  `portalPassword` is required.\n- Discount codes (`couponCodeForLink`) are soft-checked: missing/inactive → `Warning`;\n  the event still saves.\n- Report max ranges: sales-summary / event sales **365** days; sales-detail / paypal-payouts **90** days.\n  Omit `page` to return all rows.\n- MCP exposes the same operations at `/mcp` (same Bearer key). Help: `GET /help?q=`.\n"},"servers":[{"url":"/api/v1","description":"Shindig API v1"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"API key from Company Config (same key as MCP)"}},"parameters":{"YyyymmddBegin":{"name":"beginDate","in":"query","schema":{"type":"integer"},"description":"Range start as YYYYMMDD integer (e.g. 20260101)"},"YyyymmddEnd":{"name":"endDate","in":"query","schema":{"type":"integer"},"description":"Range end as YYYYMMDD integer (e.g. 20261231)"},"YyyymmddBeginRequired":{"name":"beginDate","in":"query","required":true,"schema":{"type":"integer"},"description":"Range start as YYYYMMDD integer (e.g. 20260101)"},"YyyymmddEndRequired":{"name":"endDate","in":"query","required":true,"schema":{"type":"integer"},"description":"Range end as YYYYMMDD integer (e.g. 20261231)"}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"}}},"FormItem":{"type":"object","properties":{"itemLabel":{"type":"string","description":"Short field label shown to shoppers"},"itemPrompt":{"type":"string","description":"Prompt / help text for the field"},"ordering":{"type":"number","description":"Display order (lower first)"},"isRequired":{"type":"boolean"}}},"EventProduct":{"type":"object","required":["shopifyProductId","shopifyVariantId"],"properties":{"shopifyProductId":{"oneOf":[{"type":"string"},{"type":"number"}],"description":"Numeric Shopify product id from GET /products"},"shopifyVariantId":{"oneOf":[{"type":"string"},{"type":"number"}],"description":"Numeric Shopify variant id from GET /products"},"productTitle":{"type":"string","description":"Ignored on save; titles come from Shopify"},"variantTitle":{"type":"string","description":"Ignored on save; titles come from Shopify"}}},"SaveEventRequest":{"type":"object","description":"Create (POST) or update (PATCH) body. On create: title, description, startDate, endDate, and siteName are required. On update: omitted fields keep existing values.\n","properties":{"title":{"type":"string","description":"Event title (required on create)"},"description":{"type":"string","description":"Event description HTML (required on create)"},"startDate":{"type":"integer","description":"Start date as YYYYMMDD integer (required on create)"},"endDate":{"type":"integer","description":"End date as YYYYMMDD integer (required on create)"},"siteName":{"type":"string","description":"Site ID for shopping URLs (?_f=); alphanumeric/dash/underscore (required on create)\n"},"active":{"type":"boolean","description":"Defaults to true on create"},"password":{"type":"string","description":"Event shopping password; requires privateMessage when set"},"privateMessage":{"type":"string","description":"Required when password is set"},"couponCodeForLink":{"type":"string","description":"Discount code soft-checked in Shopify on save. Missing or inactive codes produce a Warning on the response; the event is still saved.\n"},"referralPerc":{"type":"number","minimum":0,"maximum":1,"description":"Referral percentage 0–1"},"payPalPayoutEmailAddress":{"type":"string"},"salesSnapshotEnabled":{"type":"boolean"},"salesGoalAmount":{"type":"number","description":"Optional fundraising goal (company currency); 0 clears"},"portalPassword":{"type":"string","description":"Required when userPortalEnabled is true"},"userPortalEnabled":{"type":"boolean"},"formItems":{"type":"array","description":"Checkout form fields; omit on update to keep existing; [] clears","items":{"$ref":"#/components/schemas/FormItem"}},"eventProducts":{"type":"array","description":"Promoted Shopify products. Omit on update to keep existing; pass [] to clear. Non-empty lists are verified against Shopify Admin; titles come from Shopify. Use GET /products to search for IDs.\n","items":{"$ref":"#/components/schemas/EventProduct"}}}},"SaveEventResult":{"type":"object","properties":{"Success":{"type":"boolean"},"Message":{"type":"string"},"Warning":{"type":"string","description":"Soft-check warning (e.g. discount code); empty when ok"}}},"EventListItem":{"type":"object","properties":{"eventId":{"type":"string"},"title":{"type":"string"},"startDate":{"type":"integer","description":"YYYYMMDD"},"endDate":{"type":"integer","description":"YYYYMMDD"},"siteName":{"type":"string"},"publicGuid":{"type":"string"},"active":{"type":"boolean"},"salesSnapshotEnabled":{"type":"boolean"},"userPortalEnabled":{"type":"boolean"},"startsAtUtc":{"type":"string","nullable":true},"shoppingUrls":{"type":"array","items":{"type":"string"}},"salesSnapshotUrl":{"type":"string","nullable":true},"portalLoginUrl":{"type":"string","nullable":true}}},"EventListResponse":{"type":"object","properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/EventListItem"}}}},"EventDetails":{"type":"object","properties":{"eventId":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"startDate":{"type":"integer"},"endDate":{"type":"integer"},"active":{"type":"boolean"},"siteName":{"type":"string"},"password":{"type":"string"},"privateMessage":{"type":"string"},"couponCodeForLink":{"type":"string"},"referralPerc":{"type":"number"},"payPalPayoutEmailAddress":{"type":"string"},"publicGuid":{"type":"string"},"salesSnapshotEnabled":{"type":"boolean"},"salesGoalAmount":{"type":"number"},"userPortalEnabled":{"type":"boolean"},"portalPassword":{"type":"string"},"formItems":{"type":"array","items":{"$ref":"#/components/schemas/FormItem"}},"eventProducts":{"type":"array","items":{"$ref":"#/components/schemas/EventProduct"}},"startsAtUtc":{"type":"string","nullable":true}}},"EventDetailsResponse":{"type":"object","properties":{"event":{"$ref":"#/components/schemas/EventDetails"}}},"EventSalesTotals":{"type":"object","properties":{"eventId":{"type":"string"},"title":{"type":"string"},"totalSales":{"type":"number"},"totalOrders":{"type":"number"},"averageSale":{"type":"number"},"beginDate":{"type":"integer","description":"Present when a date range was requested"},"endDate":{"type":"integer","description":"Present when a date range was requested"},"error":{"type":"string"}}},"ProductSearchResult":{"type":"object","properties":{"products":{"type":"array","items":{"type":"object","properties":{"shopifyProductId":{"type":"string"},"productTitle":{"type":"string"},"variants":{"type":"array","items":{"type":"object","properties":{"shopifyVariantId":{"type":"string"},"variantTitle":{"type":"string"}}}},"variantsTruncated":{"type":"boolean"}}}},"hasNextPage":{"type":"boolean"},"cursor":{"type":"string","nullable":true}}},"SalesSummaryRow":{"type":"object","properties":{"eventId":{"type":"string"},"eventTitle":{"type":"string"},"saleCount":{"type":"number"},"totalPrice":{"type":"number"},"totalPriceRet":{"type":"number"},"referralPerc":{"type":"number"},"totalReferral":{"type":"number"},"referralEmail":{"type":"string"}}},"SalesSummaryResponse":{"type":"object","properties":{"errorMessage":{"type":"string"},"data":{"type":"array","items":{"$ref":"#/components/schemas/SalesSummaryRow"}},"hasNextPage":{"type":"boolean"},"totalEventCount":{"type":"number"}}},"SalesDetailRow":{"type":"object","properties":{"orderNumber":{"type":"string"},"orderDate":{"type":"string"},"eventId":{"type":"string"},"eventTitle":{"type":"string"},"replicatedSiteName":{"type":"string"},"totalPrice":{"type":"number"},"totalPriceRet":{"type":"number"},"balance":{"type":"number"},"formDataJson":{"type":"string"},"isEventActive":{"type":"boolean"},"isEventExpired":{"type":"boolean"},"isEventNotStarted":{"type":"boolean"},"referralPerc":{"type":"number"},"totalReferral":{"type":"number"},"referralEmail":{"type":"string"}}},"SalesDetailResponse":{"type":"object","properties":{"errorMessage":{"type":"string"},"data":{"type":"array","items":{"$ref":"#/components/schemas/SalesDetailRow"}},"hasNextPage":{"type":"boolean"},"totalOrderCount":{"type":"number"}}},"PaypalPayoutRow":{"type":"object","properties":{"eventId":{"type":"string"},"eventTitle":{"type":"string"},"referralEmail":{"type":"string"},"referralPerc":{"type":"number"},"saleCount":{"type":"number"},"totalPrice":{"type":"number"},"totalReferral":{"type":"number"}}},"PaypalPayoutsResponse":{"type":"object","properties":{"errorMessage":{"type":"string"},"data":{"type":"array","items":{"$ref":"#/components/schemas/PaypalPayoutRow"}},"totalRows":{"type":"number"},"totalPayoutAmount":{"type":"number"}}},"HelpSearchResponse":{"type":"object","properties":{"sections":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"category":{"type":"string"},"excerpt":{"type":"string"}}}}}},"HelpSectionResponse":{"type":"object","properties":{"section":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"category":{"type":"string"},"body":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}}}}}},"ApiRoot":{"type":"object","properties":{"name":{"type":"string"},"version":{"type":"string"},"docsUrl":{"type":"string"},"openApiUrl":{"type":"string"},"mcpUrl":{"type":"string"}}}}},"paths":{"/":{"get":{"summary":"API discovery","operationId":"getApiRoot","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"API metadata (docs, OpenAPI, MCP URLs)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiRoot"}}}}}}},"/events":{"get":{"summary":"List events","description":"Lists active events by default. Pass includeInactive=true to include deactivated events; each row includes an active boolean.\n","operationId":"listActiveEvents","parameters":[{"name":"includeInactive","in":"query","schema":{"type":"boolean"},"description":"When true, include deactivated events"}],"responses":{"200":{"description":"Events with shopping URLs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventListResponse"}}}},"401":{"description":"Unauthorized"}}},"post":{"summary":"Create event","description":"Required: title, description, startDate, endDate, siteName. Use GET /products before setting eventProducts.\n","operationId":"createEvent","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveEventRequest"}}}},"responses":{"201":{"description":"Event created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveEventResult"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/products":{"get":{"summary":"Search shop products","description":"Search active Shopify products for promoted-product IDs. Requires a query (min 2 characters). Default limit 10, max 25. Uses cursor pagination. status:active is applied when the query does not already include a status: filter.\n","operationId":"searchShopProducts","parameters":[{"name":"query","in":"query","required":true,"schema":{"type":"string","minLength":2},"description":"Shopify product search query (title, SKU, etc.)"},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":25}},{"name":"cursor","in":"query","schema":{"type":"string"},"description":"Pagination cursor from a previous response"}],"responses":{"200":{"description":"Matching products and variants","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductSearchResult"}}}},"400":{"description":"Validation or Shopify error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized"}}}},"/events/{eventId}":{"get":{"summary":"Get event details","operationId":"getEventDetails","parameters":[{"name":"eventId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Event configuration (includes password fields; no orders)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventDetailsResponse"}}}},"404":{"description":"Event not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"summary":"Update event","description":"Partial update: omitted fields keep existing values (including formItems and eventProducts). Pass [] to clear those arrays intentionally.\n","operationId":"updateEvent","parameters":[{"name":"eventId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveEventRequest"}}}},"responses":{"200":{"description":"Event updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveEventResult"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Event not found"}}}},"/events/{eventId}/deactivate":{"post":{"summary":"Deactivate event","operationId":"deactivateEvent","parameters":[{"name":"eventId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Event deactivated"}}}},"/events/{eventId}/reactivate":{"post":{"summary":"Reactivate event","operationId":"reactivateEvent","parameters":[{"name":"eventId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Event reactivated"}}}},"/events/{eventId}/sales":{"get":{"summary":"Event sales totals","description":"Net sales for one event (same math as the portal dashboard). Omit beginDate/endDate for lifetime; provide both (YYYYMMDD) for a range (max 365 days).\n","operationId":"getEventTotalSales","parameters":[{"name":"eventId","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/YyyymmddBegin"},{"$ref":"#/components/parameters/YyyymmddEnd"}],"responses":{"200":{"description":"Sales totals","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventSalesTotals"}}}}}}},"/reports/sales-summary":{"get":{"summary":"Sales summary report","description":"Max date range 365 days. Omit page to return all rows.","operationId":"salesSummaryReport","parameters":[{"$ref":"#/components/parameters/YyyymmddBeginRequired"},{"$ref":"#/components/parameters/YyyymmddEndRequired"},{"name":"resultFilterText","in":"query","schema":{"type":"string"},"description":"Optional filter (event id / title substring)"},{"name":"page","in":"query","schema":{"type":"integer"},"description":"1-based page; omit to return all rows"},{"name":"pageSize","in":"query","schema":{"type":"integer"}}],"responses":{"200":{"description":"Report rows","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesSummaryResponse"}}}}}}},"/reports/sales-detail":{"get":{"summary":"Sales detail report","description":"Order-level sales detail for a date range (max 90 days). Same data as the admin Sales Detail report. Omit page to return all rows. Pass eventIds as a comma-separated list to filter.\n","operationId":"salesDetailReport","parameters":[{"$ref":"#/components/parameters/YyyymmddBeginRequired"},{"$ref":"#/components/parameters/YyyymmddEndRequired"},{"name":"resultFilterText","in":"query","schema":{"type":"string"}},{"name":"eventIds","in":"query","schema":{"type":"string"},"description":"Comma-separated event ids"},{"name":"page","in":"query","schema":{"type":"integer"},"description":"1-based page; omit to return all rows"},{"name":"pageSize","in":"query","schema":{"type":"integer"}}],"responses":{"200":{"description":"Order-level report rows","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesDetailResponse"}}}}}}},"/reports/paypal-payouts":{"get":{"summary":"PayPal payouts report","description":"Aggregated referral commissions for PayPal Mass Payouts CSV (max 90 days). Requires a plan with referral features.\n","operationId":"paypalPayoutsReport","parameters":[{"$ref":"#/components/parameters/YyyymmddBeginRequired"},{"$ref":"#/components/parameters/YyyymmddEndRequired"}],"responses":{"200":{"description":"Payout report rows","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaypalPayoutsResponse"}}}},"403":{"description":"Referral features not available on this plan","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/help":{"get":{"summary":"Search help","description":"Search the product Help Center (prefer when unsure about behavior).","operationId":"searchHelp","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer"}}],"responses":{"200":{"description":"Help search hits","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HelpSearchResponse"}}}}}}},"/help/{sectionId}":{"get":{"summary":"Get help section","operationId":"getHelpSection","parameters":[{"name":"sectionId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Full help section","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HelpSectionResponse"}}}},"404":{"description":"Section not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}