{"openapi":"3.1.0","info":{"title":"WedLaunch API","version":"1.0.0","description":"The WedLaunch API gives you full programmatic access to your wedding vendor business data. Build custom integrations, automate workflows, sync with other tools, and extend your WedLaunch experience.\n\n## Authentication\n\nAll API requests require a Bearer token. Generate API keys from your WedLaunch dashboard under Settings > API Keys.\n\n```\nAuthorization: Bearer wl_live_...\n```\n\n## Rate Limiting\n\nDefault: 60 requests/minute per API key. Rate limits are returned in response headers:\n- `X-RateLimit-Limit` — Your rate limit\n- `X-RateLimit-Remaining` — Remaining requests\n\n## Pagination\n\nList endpoints support pagination via `page` and `limit` query parameters. Response includes a `meta` object with pagination details.\n\n## Response Format\n\nAll responses follow a consistent envelope:\n```json\n{\n  \"data\": { ... },\n  \"meta\": { \"page\": 1, \"limit\": 20, \"total\": 100, \"has_more\": true },\n  \"error\": null\n}\n```\n","contact":{"name":"WedLaunch API Support","url":"https://wedlaunch.com/developers"}},"servers":[{"url":"https://wedlaunch.com","description":"Production"}],"security":[{"BearerAuth":[]}],"paths":{"/api/v1/contacts":{"get":{"summary":"List contacts","description":"Manage your leads, clients, and prospects. Deal pipeline state lives on projects, not contacts — filter by relationship (lead | client | past_client | vendor | other) here, and use /projects for funnel stage.","tags":["Contacts"],"parameters":[{"name":"page","in":"query","schema":{"type":"integer","default":1},"description":"Page number"},{"name":"limit","in":"query","schema":{"type":"integer","default":20,"maximum":100},"description":"Items per page"},{"name":"search","in":"query","schema":{"type":"string"},"description":"Filter by search"},{"name":"relationship","in":"query","schema":{"type":"string"},"description":"Filter by relationship"},{"name":"source","in":"query","schema":{"type":"string"},"description":"Filter by source"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse"}}}},"401":{"description":"Unauthorized"},"429":{"description":"Rate limit exceeded"}}},"post":{"summary":"Create contact","tags":["Contacts"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"201":{"description":"Created"},"401":{"description":"Unauthorized"},"409":{"description":"Conflict"}}}},"/api/v1/contacts/{id}":{"get":{"summary":"Get contact","tags":["Contacts"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Resource ID"}],"responses":{"200":{"description":"Success"},"404":{"description":"Not found"}}},"patch":{"summary":"Update contact","tags":["Contacts"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Resource ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Updated"},"404":{"description":"Not found"}}},"delete":{"summary":"Delete contact","tags":["Contacts"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Resource ID"}],"responses":{"200":{"description":"Deleted"},"404":{"description":"Not found"}}}},"/api/v1/projects":{"get":{"summary":"List projects","description":"Track projects (weddings, corporate events, photo sessions) you are servicing","tags":["Projects"],"parameters":[{"name":"page","in":"query","schema":{"type":"integer","default":1},"description":"Page number"},{"name":"limit","in":"query","schema":{"type":"integer","default":20,"maximum":100},"description":"Items per page"},{"name":"search","in":"query","schema":{"type":"string"},"description":"Filter by search"},{"name":"pipeline_stage","in":"query","schema":{"type":"string"},"description":"Filter by pipeline_stage"},{"name":"project_stage","in":"query","schema":{"type":"string"},"description":"Filter by project_stage"},{"name":"contact_id","in":"query","schema":{"type":"string"},"description":"Filter by contact_id"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse"}}}},"401":{"description":"Unauthorized"},"429":{"description":"Rate limit exceeded"}}},"post":{"summary":"Create project","tags":["Projects"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"201":{"description":"Created"},"401":{"description":"Unauthorized"},"409":{"description":"Conflict"}}}},"/api/v1/projects/{id}":{"get":{"summary":"Get project","tags":["Projects"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Resource ID"}],"responses":{"200":{"description":"Success"},"404":{"description":"Not found"}}},"patch":{"summary":"Update project","tags":["Projects"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Resource ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Updated"},"404":{"description":"Not found"}}},"delete":{"summary":"Delete project","tags":["Projects"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Resource ID"}],"responses":{"200":{"description":"Deleted"},"404":{"description":"Not found"}}}},"/api/v1/project-types":{"get":{"summary":"List project types","description":"Tenant-defined project categories (e.g. Wedding, Senior Portrait, Corporate Activation) with default event types, contact roles, and vendor categories. The \"Wedding\" row is system-seeded and cannot be renamed or deleted.","tags":["Project Types"],"parameters":[{"name":"page","in":"query","schema":{"type":"integer","default":1},"description":"Page number"},{"name":"limit","in":"query","schema":{"type":"integer","default":20,"maximum":100},"description":"Items per page"},{"name":"search","in":"query","schema":{"type":"string"},"description":"Filter by search"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse"}}}},"401":{"description":"Unauthorized"},"429":{"description":"Rate limit exceeded"}}},"post":{"summary":"Create project type","tags":["Project Types"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"201":{"description":"Created"},"401":{"description":"Unauthorized"},"409":{"description":"Conflict"}}}},"/api/v1/project-types/{id}":{"get":{"summary":"Get project type","tags":["Project Types"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Resource ID"}],"responses":{"200":{"description":"Success"},"404":{"description":"Not found"}}},"patch":{"summary":"Update project type","tags":["Project Types"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Resource ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Updated"},"404":{"description":"Not found"}}},"delete":{"summary":"Delete project type","tags":["Project Types"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Resource ID"}],"responses":{"200":{"description":"Deleted"},"404":{"description":"Not found"}}}},"/api/v1/events":{"get":{"summary":"List events","description":"Manage events associated with weddings","tags":["Events"],"parameters":[{"name":"page","in":"query","schema":{"type":"integer","default":1},"description":"Page number"},{"name":"limit","in":"query","schema":{"type":"integer","default":20,"maximum":100},"description":"Items per page"},{"name":"project_id","in":"query","schema":{"type":"string"},"description":"Filter by project_id"},{"name":"contact_id","in":"query","schema":{"type":"string"},"description":"Filter by contact_id"},{"name":"event_type","in":"query","schema":{"type":"string"},"description":"Filter by event_type"},{"name":"status","in":"query","schema":{"type":"string"},"description":"Filter by status"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse"}}}},"401":{"description":"Unauthorized"},"429":{"description":"Rate limit exceeded"}}},"post":{"summary":"Create event","tags":["Events"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"201":{"description":"Created"},"401":{"description":"Unauthorized"},"409":{"description":"Conflict"}}}},"/api/v1/events/{id}":{"get":{"summary":"Get event","tags":["Events"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Resource ID"}],"responses":{"200":{"description":"Success"},"404":{"description":"Not found"}}},"patch":{"summary":"Update event","tags":["Events"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Resource ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Updated"},"404":{"description":"Not found"}}},"delete":{"summary":"Delete event","tags":["Events"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Resource ID"}],"responses":{"200":{"description":"Deleted"},"404":{"description":"Not found"}}}},"/api/v1/appointments":{"get":{"summary":"List appointments","description":"Schedule and manage client meetings","tags":["Appointments"],"parameters":[{"name":"page","in":"query","schema":{"type":"integer","default":1},"description":"Page number"},{"name":"limit","in":"query","schema":{"type":"integer","default":20,"maximum":100},"description":"Items per page"},{"name":"status","in":"query","schema":{"type":"string"},"description":"Filter by status"},{"name":"contact_id","in":"query","schema":{"type":"string"},"description":"Filter by contact_id"},{"name":"start_after","in":"query","schema":{"type":"string"},"description":"Filter by start_after"},{"name":"start_before","in":"query","schema":{"type":"string"},"description":"Filter by start_before"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse"}}}},"401":{"description":"Unauthorized"},"429":{"description":"Rate limit exceeded"}}},"post":{"summary":"Create appointment","tags":["Appointments"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"201":{"description":"Created"},"401":{"description":"Unauthorized"},"409":{"description":"Conflict"}}}},"/api/v1/appointments/{id}":{"get":{"summary":"Get appointment","tags":["Appointments"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Resource ID"}],"responses":{"200":{"description":"Success"},"404":{"description":"Not found"}}},"patch":{"summary":"Update appointment","tags":["Appointments"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Resource ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Updated"},"404":{"description":"Not found"}}},"delete":{"summary":"Delete appointment","tags":["Appointments"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Resource ID"}],"responses":{"200":{"description":"Deleted"},"404":{"description":"Not found"}}}},"/api/v1/contracts":{"get":{"summary":"List contracts","description":"Create and track service contracts","tags":["Contracts"],"parameters":[{"name":"page","in":"query","schema":{"type":"integer","default":1},"description":"Page number"},{"name":"limit","in":"query","schema":{"type":"integer","default":20,"maximum":100},"description":"Items per page"},{"name":"status","in":"query","schema":{"type":"string"},"description":"Filter by status"},{"name":"contact_id","in":"query","schema":{"type":"string"},"description":"Filter by contact_id"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse"}}}},"401":{"description":"Unauthorized"},"429":{"description":"Rate limit exceeded"}}},"post":{"summary":"Create contract","tags":["Contracts"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"201":{"description":"Created"},"401":{"description":"Unauthorized"},"409":{"description":"Conflict"}}}},"/api/v1/contracts/{id}":{"get":{"summary":"Get contract","tags":["Contracts"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Resource ID"}],"responses":{"200":{"description":"Success"},"404":{"description":"Not found"}}},"patch":{"summary":"Update contract","tags":["Contracts"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Resource ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Updated"},"404":{"description":"Not found"}}},"delete":{"summary":"Delete contract","tags":["Contracts"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Resource ID"}],"responses":{"200":{"description":"Deleted"},"404":{"description":"Not found"}}}},"/api/v1/invoices":{"get":{"summary":"List invoices","description":"Manage billing and payment invoices","tags":["Invoices"],"parameters":[{"name":"page","in":"query","schema":{"type":"integer","default":1},"description":"Page number"},{"name":"limit","in":"query","schema":{"type":"integer","default":20,"maximum":100},"description":"Items per page"},{"name":"status","in":"query","schema":{"type":"string"},"description":"Filter by status"},{"name":"contact_id","in":"query","schema":{"type":"string"},"description":"Filter by contact_id"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse"}}}},"401":{"description":"Unauthorized"},"429":{"description":"Rate limit exceeded"}}},"post":{"summary":"Create invoice","tags":["Invoices"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"201":{"description":"Created"},"401":{"description":"Unauthorized"},"409":{"description":"Conflict"}}}},"/api/v1/invoices/{id}":{"get":{"summary":"Get invoice","tags":["Invoices"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Resource ID"}],"responses":{"200":{"description":"Success"},"404":{"description":"Not found"}}},"patch":{"summary":"Update invoice","tags":["Invoices"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Resource ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Updated"},"404":{"description":"Not found"}}},"delete":{"summary":"Delete invoice","tags":["Invoices"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Resource ID"}],"responses":{"200":{"description":"Deleted"},"404":{"description":"Not found"}}}},"/api/v1/proposals":{"get":{"summary":"List proposals","description":"Create and send service proposals","tags":["Proposals"],"parameters":[{"name":"page","in":"query","schema":{"type":"integer","default":1},"description":"Page number"},{"name":"limit","in":"query","schema":{"type":"integer","default":20,"maximum":100},"description":"Items per page"},{"name":"status","in":"query","schema":{"type":"string"},"description":"Filter by status"},{"name":"contact_id","in":"query","schema":{"type":"string"},"description":"Filter by contact_id"},{"name":"event_id","in":"query","schema":{"type":"string"},"description":"Filter by event_id"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse"}}}},"401":{"description":"Unauthorized"},"429":{"description":"Rate limit exceeded"}}},"post":{"summary":"Create proposal","tags":["Proposals"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"201":{"description":"Created"},"401":{"description":"Unauthorized"},"409":{"description":"Conflict"}}}},"/api/v1/proposals/{id}":{"get":{"summary":"Get proposal","tags":["Proposals"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Resource ID"}],"responses":{"200":{"description":"Success"},"404":{"description":"Not found"}}},"patch":{"summary":"Update proposal","tags":["Proposals"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Resource ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Updated"},"404":{"description":"Not found"}}},"delete":{"summary":"Delete proposal","tags":["Proposals"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Resource ID"}],"responses":{"200":{"description":"Deleted"},"404":{"description":"Not found"}}}},"/api/v1/services":{"get":{"summary":"List services","description":"Configure your vendor service catalog","tags":["Services"],"parameters":[{"name":"page","in":"query","schema":{"type":"integer","default":1},"description":"Page number"},{"name":"limit","in":"query","schema":{"type":"integer","default":20,"maximum":100},"description":"Items per page"},{"name":"search","in":"query","schema":{"type":"string"},"description":"Filter by search"},{"name":"category","in":"query","schema":{"type":"string"},"description":"Filter by category"},{"name":"is_active","in":"query","schema":{"type":"string"},"description":"Filter by is_active"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse"}}}},"401":{"description":"Unauthorized"},"429":{"description":"Rate limit exceeded"}}},"post":{"summary":"Create service","tags":["Services"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"201":{"description":"Created"},"401":{"description":"Unauthorized"},"409":{"description":"Conflict"}}}},"/api/v1/services/{id}":{"get":{"summary":"Get service","tags":["Services"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Resource ID"}],"responses":{"200":{"description":"Success"},"404":{"description":"Not found"}}},"patch":{"summary":"Update service","tags":["Services"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Resource ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Updated"},"404":{"description":"Not found"}}},"delete":{"summary":"Delete service","tags":["Services"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Resource ID"}],"responses":{"200":{"description":"Deleted"},"404":{"description":"Not found"}}}},"/api/v1/packages":{"get":{"summary":"List packages","description":"Manage pricing packages for your services","tags":["Packages"],"parameters":[{"name":"page","in":"query","schema":{"type":"integer","default":1},"description":"Page number"},{"name":"limit","in":"query","schema":{"type":"integer","default":20,"maximum":100},"description":"Items per page"},{"name":"search","in":"query","schema":{"type":"string"},"description":"Filter by search"},{"name":"service_id","in":"query","schema":{"type":"string"},"description":"Filter by service_id"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse"}}}},"401":{"description":"Unauthorized"},"429":{"description":"Rate limit exceeded"}}},"post":{"summary":"Create package","tags":["Packages"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"201":{"description":"Created"},"401":{"description":"Unauthorized"},"409":{"description":"Conflict"}}}},"/api/v1/packages/{id}":{"get":{"summary":"Get package","tags":["Packages"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Resource ID"}],"responses":{"200":{"description":"Success"},"404":{"description":"Not found"}}},"patch":{"summary":"Update package","tags":["Packages"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Resource ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Updated"},"404":{"description":"Not found"}}},"delete":{"summary":"Delete package","tags":["Packages"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Resource ID"}],"responses":{"200":{"description":"Deleted"},"404":{"description":"Not found"}}}},"/api/v1/vendors":{"get":{"summary":"List vendors","description":"Browse and manage vendor profiles","tags":["Vendors"],"parameters":[{"name":"page","in":"query","schema":{"type":"integer","default":1},"description":"Page number"},{"name":"limit","in":"query","schema":{"type":"integer","default":20,"maximum":100},"description":"Items per page"},{"name":"search","in":"query","schema":{"type":"string"},"description":"Filter by search"},{"name":"category","in":"query","schema":{"type":"string"},"description":"Filter by category"},{"name":"city","in":"query","schema":{"type":"string"},"description":"Filter by city"},{"name":"state","in":"query","schema":{"type":"string"},"description":"Filter by state"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse"}}}},"401":{"description":"Unauthorized"},"429":{"description":"Rate limit exceeded"}}}},"/api/v1/vendors/{id}":{"get":{"summary":"Get vendor","tags":["Vendors"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Resource ID"}],"responses":{"200":{"description":"Success"},"404":{"description":"Not found"}}},"patch":{"summary":"Update vendor","tags":["Vendors"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Resource ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Updated"},"404":{"description":"Not found"}}}},"/api/v1/conversations":{"get":{"summary":"List conversations","description":"Access message threads with contacts","tags":["Conversations"],"parameters":[{"name":"page","in":"query","schema":{"type":"integer","default":1},"description":"Page number"},{"name":"limit","in":"query","schema":{"type":"integer","default":20,"maximum":100},"description":"Items per page"},{"name":"contact_id","in":"query","schema":{"type":"string"},"description":"Filter by contact_id"},{"name":"channel","in":"query","schema":{"type":"string"},"description":"Filter by channel"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse"}}}},"401":{"description":"Unauthorized"},"429":{"description":"Rate limit exceeded"}}},"post":{"summary":"Create conversation","tags":["Conversations"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"201":{"description":"Created"},"401":{"description":"Unauthorized"},"409":{"description":"Conflict"}}}},"/api/v1/leads/ingest":{"post":{"summary":"Submit a raw lead payload for async LLM classification","description":"Universal lead intake endpoint. POST any JSON body representing a lead (form submission, scraped inquiry, etc.). The raw payload is persisted immediately and classified asynchronously by an LLM that normalizes the fields into WedLaunch's canonical contact + project schema.\n\n**Response:** `202 Accepted` with an `event_id` you can poll or cross-reference. Never returns classification results synchronously.\n\n**Optional hints:**\n- `X-Lead-Source` header (e.g. `jotform`, `elementor`, `theknot_scrape`)\n- Body fields `_source` or `_form_id` as self-declared source markers\n\n**Limits:** body must be no larger than 32 KB. Accepts `application/json`, `application/x-www-form-urlencoded`, or `multipart/form-data` — form-encoded fields are flattened to a JSON object before classification, so JotForm and Elementor default webhook formats work without changes on the sender side.","tags":["Leads"],"parameters":[{"name":"X-Lead-Source","in":"header","required":false,"schema":{"type":"string"},"description":"Optional source hint (e.g. jotform, elementor, theknot_scrape)."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Any JSON object. Field names are not validated.","additionalProperties":true},"examples":{"jotform":{"summary":"JotForm-style payload","value":{"First Name":"Jane","Last Name":"Doe","Email":"jane@example.com","Phone Number":"+1 555 123 4567","Type of Event":"Wedding","Date of Event":"2026-10-10","Event Location / Ideal Venue":"Central Park","Tell Us More":"Looking for full planning services for ~150 guests."}},"elementor":{"summary":"Elementor-style payload","value":{"First Name":"Jane","Email":"jane@example.com","Phone":"555-123-4567","Message":"Planning a fall wedding for 100 guests.","Wedding Date":"2026-10-10","Guest Count":100,"Venue":"Central Park"}}}}}},"responses":{"202":{"description":"Payload accepted for async classification","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"event_id":{"type":"string","format":"uuid"}},"required":["event_id"]}}}}}},"400":{"description":"Body is not a JSON object"},"401":{"description":"Unauthorized"},"403":{"description":"API key missing write scope"},"413":{"description":"Body exceeds 32KB limit"},"429":{"description":"Rate limit exceeded"},"500":{"description":"Failed to persist payload"}}}},"/wh/leads/{token}":{"post":{"summary":"Submit a lead via a tokenized webhook URL","description":"Tokenized inbound webhook surface — the URL token alone identifies the tenant and source. No headers, no auth setup. Funnels into the same async LLM classification pipeline as `/api/v1/leads/ingest`.\n\n**Token format:** `wlh_live_<hex>`. Provision tokens from Settings → Inbound Webhooks. Treat each URL like a password — anyone with it can submit leads on the tenant's behalf. Revoking a token returns 410 Gone on subsequent requests.\n\n**Source attribution:** the source slug is set when the webhook is created and stamped on every lead from that URL. `X-Lead-Source` header and body `_source` / `_form_id` hints are ignored on this surface — the slug is the source of truth.\n\n**Limits:** body must be no larger than 32 KB. Default rate limit: 60 requests/minute per token. Accepts `application/json`, `application/x-www-form-urlencoded`, or `multipart/form-data`.","tags":["Leads"],"security":[],"parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","pattern":"^wlh_live_[A-Za-z0-9]+$"},"description":"The webhook token (e.g. wlh_live_abc123...). Provision from Settings → Inbound Webhooks."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Any JSON object. Field names are not validated.","additionalProperties":true}},"application/x-www-form-urlencoded":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"202":{"description":"Payload accepted for async classification","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"event_id":{"type":"string","format":"uuid"}},"required":["event_id"]}}}}}},"400":{"description":"Body is not a JSON object"},"404":{"description":"Webhook token not found"},"410":{"description":"Webhook has been revoked"},"413":{"description":"Body exceeds 32KB limit"},"429":{"description":"Rate limit exceeded"},"500":{"description":"Failed to persist payload"}}}}},"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key from your WedLaunch dashboard"}},"schemas":{"PaginatedResponse":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"has_more":{"type":"boolean"}}},"error":{"type":"object","nullable":true}}}}},"tags":[{"name":"Contacts","description":"Manage your leads, clients, and prospects. Deal pipeline state lives on projects, not contacts — filter by relationship (lead | client | past_client | vendor | other) here, and use /projects for funnel stage."},{"name":"Projects","description":"Track projects (weddings, corporate events, photo sessions) you are servicing"},{"name":"Project Types","description":"Tenant-defined project categories (e.g. Wedding, Senior Portrait, Corporate Activation) with default event types, contact roles, and vendor categories. The \"Wedding\" row is system-seeded and cannot be renamed or deleted."},{"name":"Events","description":"Manage events associated with weddings"},{"name":"Appointments","description":"Schedule and manage client meetings"},{"name":"Contracts","description":"Create and track service contracts"},{"name":"Invoices","description":"Manage billing and payment invoices"},{"name":"Proposals","description":"Create and send service proposals"},{"name":"Services","description":"Configure your vendor service catalog"},{"name":"Packages","description":"Manage pricing packages for your services"},{"name":"Vendors","description":"Browse and manage vendor profiles"},{"name":"Conversations","description":"Access message threads with contacts"},{"name":"Leads","description":"Flexible lead ingestion — post raw form payloads for async LLM classification."}]}